developers
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2009
- 22 participants
- 180 discussions
[Maria-developers] Progress (by Sanja): Avoid flushing keycache to disk in case of DROPping table (53)
by worklog-noreply@askmonty.org 13 Nov '09
by worklog-noreply@askmonty.org 13 Nov '09
13 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Avoid flushing keycache to disk in case of DROPping table
CREATION DATE..: Thu, 27 Aug 2009, 11:12
SUPERVISOR.....: Monty
IMPLEMENTOR....: Sanja
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 53 (http://askmonty.org/worklog/?tid=53)
VERSION........: Server-5.0
STATUS.........: Complete
PRIORITY.......: 60
WORKED HOURS...: 21
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 24
PROGRESS NOTES:
-=-=(Sanja - Fri, 13 Nov 2009, 10:55)=-=-
Ported to maria 5.1 _ maria and partitioning support added and tested
Worked 2 hours and estimate 0 hours remain (original estimate increased by 2 hours).
-=-=(Sanja - Fri, 13 Nov 2009, 00:24)=-=-
Ported to mysql 5.1 and tested
Worked 5 hours and estimate 0 hours remain (original estimate increased by 5 hours).
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
Status updated.
--- /tmp/wklog.53.old.27223 2009-10-06 12:30:38.000000000 +0300
+++ /tmp/wklog.53.new.27223 2009-10-06 12:30:38.000000000 +0300
@@ -1 +1 @@
-Assigned
+Complete
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
After review fixes and tests.
Worked 1 hour and estimate 0 hours remain (original estimate decreased by 10 hours).
-=-=(Sanja - Thu, 03 Sep 2009, 19:43)=-=-
New patch and its testing
Worked 8 hours and estimate 11 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:20)=-=-
moving to 5.0 part1
Worked 2 hours and estimate 19 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:19)=-=-
first patch
Worked 3 hours and estimate 21 hours remain (original estimate unchanged).
-=-=(Sanja - Thu, 27 Aug 2009, 11:15)=-=-
High-Level Specification modified.
--- /tmp/wklog.53.old.23490 2009-08-27 11:15:24.000000000 +0300
+++ /tmp/wklog.53.new.23490 2009-08-27 11:15:24.000000000 +0300
@@ -1 +1,3 @@
-
+To make special handler call 'prepare to drop' which mark table as changed (in
+case of server crash just before removing table it force table to be repaired)
+then flush keycache without writing on disk.
DESCRIPTION:
When DROP TABLE executed keycache flushed to disk before removing table which is
wasting of resources. So better to have table removed from keycache without
writing changes on disk.
HIGH-LEVEL SPECIFICATION:
To make special handler call 'prepare to drop' which mark table as changed (in
case of server crash just before removing table it force table to be repaired)
then flush keycache without writing on disk.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] Progress (by Sanja): Avoid flushing keycache to disk in case of DROPping table (53)
by worklog-noreply@askmonty.org 13 Nov '09
by worklog-noreply@askmonty.org 13 Nov '09
13 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Avoid flushing keycache to disk in case of DROPping table
CREATION DATE..: Thu, 27 Aug 2009, 11:12
SUPERVISOR.....: Monty
IMPLEMENTOR....: Sanja
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 53 (http://askmonty.org/worklog/?tid=53)
VERSION........: Server-5.0
STATUS.........: Complete
PRIORITY.......: 60
WORKED HOURS...: 21
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 24
PROGRESS NOTES:
-=-=(Sanja - Fri, 13 Nov 2009, 10:55)=-=-
Ported to maria 5.1 _ maria and partitioning support added and tested
Worked 2 hours and estimate 0 hours remain (original estimate increased by 2 hours).
-=-=(Sanja - Fri, 13 Nov 2009, 00:24)=-=-
Ported to mysql 5.1 and tested
Worked 5 hours and estimate 0 hours remain (original estimate increased by 5 hours).
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
Status updated.
--- /tmp/wklog.53.old.27223 2009-10-06 12:30:38.000000000 +0300
+++ /tmp/wklog.53.new.27223 2009-10-06 12:30:38.000000000 +0300
@@ -1 +1 @@
-Assigned
+Complete
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
After review fixes and tests.
Worked 1 hour and estimate 0 hours remain (original estimate decreased by 10 hours).
-=-=(Sanja - Thu, 03 Sep 2009, 19:43)=-=-
New patch and its testing
Worked 8 hours and estimate 11 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:20)=-=-
moving to 5.0 part1
Worked 2 hours and estimate 19 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:19)=-=-
first patch
Worked 3 hours and estimate 21 hours remain (original estimate unchanged).
-=-=(Sanja - Thu, 27 Aug 2009, 11:15)=-=-
High-Level Specification modified.
--- /tmp/wklog.53.old.23490 2009-08-27 11:15:24.000000000 +0300
+++ /tmp/wklog.53.new.23490 2009-08-27 11:15:24.000000000 +0300
@@ -1 +1,3 @@
-
+To make special handler call 'prepare to drop' which mark table as changed (in
+case of server crash just before removing table it force table to be repaired)
+then flush keycache without writing on disk.
DESCRIPTION:
When DROP TABLE executed keycache flushed to disk before removing table which is
wasting of resources. So better to have table removed from keycache without
writing changes on disk.
HIGH-LEVEL SPECIFICATION:
To make special handler call 'prepare to drop' which mark table as changed (in
case of server crash just before removing table it force table to be repaired)
then flush keycache without writing on disk.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] Progress (by Sanja): Avoid flushing keycache to disk in case of DROPping table (53)
by worklog-noreply@askmonty.org 12 Nov '09
by worklog-noreply@askmonty.org 12 Nov '09
12 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Avoid flushing keycache to disk in case of DROPping table
CREATION DATE..: Thu, 27 Aug 2009, 11:12
SUPERVISOR.....: Monty
IMPLEMENTOR....: Sanja
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 53 (http://askmonty.org/worklog/?tid=53)
VERSION........: Server-5.0
STATUS.........: Complete
PRIORITY.......: 60
WORKED HOURS...: 19
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 24
PROGRESS NOTES:
-=-=(Sanja - Fri, 13 Nov 2009, 00:24)=-=-
Ported to mysql 5.1 and tested
Worked 5 hours and estimate 0 hours remain (original estimate increased by 5 hours).
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
Status updated.
--- /tmp/wklog.53.old.27223 2009-10-06 12:30:38.000000000 +0300
+++ /tmp/wklog.53.new.27223 2009-10-06 12:30:38.000000000 +0300
@@ -1 +1 @@
-Assigned
+Complete
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
After review fixes and tests.
Worked 1 hour and estimate 0 hours remain (original estimate decreased by 10 hours).
-=-=(Sanja - Thu, 03 Sep 2009, 19:43)=-=-
New patch and its testing
Worked 8 hours and estimate 11 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:20)=-=-
moving to 5.0 part1
Worked 2 hours and estimate 19 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:19)=-=-
first patch
Worked 3 hours and estimate 21 hours remain (original estimate unchanged).
-=-=(Sanja - Thu, 27 Aug 2009, 11:15)=-=-
High-Level Specification modified.
--- /tmp/wklog.53.old.23490 2009-08-27 11:15:24.000000000 +0300
+++ /tmp/wklog.53.new.23490 2009-08-27 11:15:24.000000000 +0300
@@ -1 +1,3 @@
-
+To make special handler call 'prepare to drop' which mark table as changed (in
+case of server crash just before removing table it force table to be repaired)
+then flush keycache without writing on disk.
DESCRIPTION:
When DROP TABLE executed keycache flushed to disk before removing table which is
wasting of resources. So better to have table removed from keycache without
writing changes on disk.
HIGH-LEVEL SPECIFICATION:
To make special handler call 'prepare to drop' which mark table as changed (in
case of server crash just before removing table it force table to be repaired)
then flush keycache without writing on disk.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] Progress (by Sanja): Avoid flushing keycache to disk in case of DROPping table (53)
by worklog-noreply@askmonty.org 12 Nov '09
by worklog-noreply@askmonty.org 12 Nov '09
12 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Avoid flushing keycache to disk in case of DROPping table
CREATION DATE..: Thu, 27 Aug 2009, 11:12
SUPERVISOR.....: Monty
IMPLEMENTOR....: Sanja
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 53 (http://askmonty.org/worklog/?tid=53)
VERSION........: Server-5.0
STATUS.........: Complete
PRIORITY.......: 60
WORKED HOURS...: 19
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 24
PROGRESS NOTES:
-=-=(Sanja - Fri, 13 Nov 2009, 00:24)=-=-
Ported to mysql 5.1 and tested
Worked 5 hours and estimate 0 hours remain (original estimate increased by 5 hours).
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
Status updated.
--- /tmp/wklog.53.old.27223 2009-10-06 12:30:38.000000000 +0300
+++ /tmp/wklog.53.new.27223 2009-10-06 12:30:38.000000000 +0300
@@ -1 +1 @@
-Assigned
+Complete
-=-=(Sanja - Tue, 06 Oct 2009, 12:30)=-=-
After review fixes and tests.
Worked 1 hour and estimate 0 hours remain (original estimate decreased by 10 hours).
-=-=(Sanja - Thu, 03 Sep 2009, 19:43)=-=-
New patch and its testing
Worked 8 hours and estimate 11 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:20)=-=-
moving to 5.0 part1
Worked 2 hours and estimate 19 hours remain (original estimate unchanged).
-=-=(Sanja - Tue, 01 Sep 2009, 15:19)=-=-
first patch
Worked 3 hours and estimate 21 hours remain (original estimate unchanged).
-=-=(Sanja - Thu, 27 Aug 2009, 11:15)=-=-
High-Level Specification modified.
--- /tmp/wklog.53.old.23490 2009-08-27 11:15:24.000000000 +0300
+++ /tmp/wklog.53.new.23490 2009-08-27 11:15:24.000000000 +0300
@@ -1 +1,3 @@
-
+To make special handler call 'prepare to drop' which mark table as changed (in
+case of server crash just before removing table it force table to be repaired)
+then flush keycache without writing on disk.
DESCRIPTION:
When DROP TABLE executed keycache flushed to disk before removing table which is
wasting of resources. So better to have table removed from keycache without
writing changes on disk.
HIGH-LEVEL SPECIFICATION:
To make special handler call 'prepare to drop' which mark table as changed (in
case of server crash just before removing table it force table to be repaired)
then flush keycache without writing on disk.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
I think I have even asked this before, but since I still don't believe
it's true: Is there no way that one Launchpad bug can depend on
another bug?
henrik
--
email: henrik.ingo(a)avoinelama.fi
tel: +358-40-5697354
www: www.avoinelama.fi/~hingo
book: www.openlife.cc
1
0
[Maria-developers] Progress (by Bothorsen): Add a mysqlbinlog option to filter updates to certain tables (40)
by worklog-noreply@askmonty.org 12 Nov '09
by worklog-noreply@askmonty.org 12 Nov '09
12 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add a mysqlbinlog option to filter updates to certain tables
CREATION DATE..: Mon, 10 Aug 2009, 13:25
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Psergey
CATEGORY.......: Server-RawIdeaBin
TASK ID........: 40 (http://askmonty.org/worklog/?tid=40)
VERSION........: Server-9.x
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 18
ESTIMATE.......: 46 (hours remain)
ORIG. ESTIMATE.: 48
PROGRESS NOTES:
-=-=(Bothorsen - Thu, 12 Nov 2009, 13:13)=-=-
Work hours by Alexi and Bo + estimated time for the task.
Worked 16 hours and estimate 46 hours remain (original estimate increased by 14 hours).
-=-=(Alexi - Sun, 08 Nov 2009, 15:18)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.15787 2009-11-08 15:18:11.000000000 +0200
+++ /tmp/wklog.40.new.15787 2009-11-08 15:18:11.000000000 +0200
@@ -62,7 +62,7 @@
it considers the query to extent to the end of the event.
2. For 'db' (current db) the trailing zero is redundant since the length
is already known.
-3. db_len = 0 means that this is the current db.
+3. In tables_info, db_len = 0 means that this is the current db.
When reading Query events from binary log, we can recognize its format
by its post-header length: in extended case the post-header includes 4
@@ -75,6 +75,77 @@
+ #define Q_QUERY_LEN_OFFSET Q_STATUS_VARS_LEN_OFFSET + 2
+ #define Q_QUERY_TABLES_INFO_LEN_OFFSET Q_QUERY_LEN_OFFSET + 2
+
+***********************************************************************
+HELP NEEDED
+***********************************************************************
+The QUERY_HEADER_LEN is used in the definition of MAX_LOG_EVENT_HEADER:
+
+log_event.h
+~~~~~~~~~~~
+#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
+ LOG_EVENT_HEADER_LEN + /* write_header */ \
+ QUERY_HEADER_LEN + /* write_data */ \
+ EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
+ MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
+ NAME_LEN + 1)
+
+which is used only for setting
+
+ thd->variables.max_allowed_packet
+ mysql->net.max_packet_size
+
+Looks like (but I am not quite sure) that QUERY_HEADER_LEN can simply
+(without making any other changes) be substituted in this definition by
+QUERY_HEADER_LEN_EXT.
+
+Below I list all places where MAX_LOG_EVENT_HEADER is used:
+
+slave.cc
+~~~~~~~~
+static int init_slave_thread(...)
+{ ...
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all
+ slave threads, since a replication event can become this much larger
+ than the corresponding packet (query) sent from client to master.
+ */
+ thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
+ ...
+}
+pthread_handler_t handle_slave_io(...)
+{ ...
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
+ thread, since a replication event can become this much larger than
+ the corresponding packet (query) sent from client to master.
+ */
+ mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
+ ...
+}
+
+sql_repl.cc
+~~~~~~~~~~~
+void mysql_binlog_send(...)
+{ ...
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
+ this larger than the corresponding packet (query) sent
+ from client to master.
+ */
+ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
+ ...
+}
+bool mysql_show_binlog_events(...)
+{ ...
+ /*
+ to account binlog event header size
+ */
+ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
+ ...
+}
+
3. Changes in log events
************************
@@ -84,7 +155,7 @@
This setting is done in Format description event constructor which creates
the event for writing to binary log:
- if (binlog_with_tables_info)
+ if (opt_binlog_with_tables_info)
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN_EXT;
else
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN;
@@ -99,12 +170,12 @@
following manner:
switch (binlog_ver) {
- case 4: /* MySQL 5.0 and higher */
+ #ifndef MYSQL_CLIENT
+ case 4: /* MySQL 5.0 and higher */
...
-+ #else
-+ <error>
+ break;
+ #endif
+
case 1:
case 3:
...
@@ -132,7 +203,7 @@
--------------------------------
[Creates the event for binlogging]
-In case of binlog_with_tables_info = TRUE, set additionally query_len,
+In case of opt_binlog_with_tables_info = TRUE, set additionally query_len,
tables_info_len, and tables_info members (the constructor is to have
an additional 'tables_info' argument).
@@ -140,7 +211,7 @@
----------------
[Writes the event to binlog]
-In case of binlog_with_tables_info = TRUE, write additional members
+In case of opt_binlog_with_tables_info = TRUE, write additional members
(query_len, tables_info_len, and tables_info) to binary log. Also
write corresponding whole event length to the common-header.
-=-=(Alexi - Sun, 08 Nov 2009, 10:40)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.5055 2009-11-08 08:40:02.000000000 +0000
+++ /tmp/wklog.40.new.5055 2009-11-08 08:40:02.000000000 +0000
@@ -3,6 +3,7 @@
1. Adding --binlog-with-tables-info option
******************************************
+GLOBAL, read-only option.
When set, Query events are to be written in the extended binary
format which contains tables_info. When not set, Query events
-=-=(Alexi - Thu, 05 Nov 2009, 12:37)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.11441 2009-11-05 12:37:16.000000000 +0200
+++ /tmp/wklog.40.new.11441 2009-11-05 12:37:16.000000000 +0200
@@ -1,9 +1,18 @@
OPTION: 2.5 Extend Query Events With Tables Info
================================================
-1. Query_log_event Binary Format
-********************************
-Changes to be done:
+1. Adding --binlog-with-tables-info option
+******************************************
+
+When set, Query events are to be written in the extended binary
+format which contains tables_info. When not set, Query events
+are to be written in usual format (without any changes).
+
+2. Query event extended binary format
+*************************************
+
+When --binlog-with-tables-info is set, Query events are writen
+to binary log in the following (extended) format.
Query_log_event binary format
---------------------------------
@@ -24,12 +33,12 @@
error_code 2
status_vars_len 2
+ query_len 2 (see Note 1)
-+ tables_info_len 2 (see Note 2)
++ tables_info_len 2
---------------------------------
BODY:
status_vars status_vars_len
- db db_len + 1
-+ db db_len (see Note 3)
++ db db_len (see Note 2)
query query_len
+ tables_info
@@ -37,7 +46,7 @@
---------------------------------
Name Size (bytes)
---------------------------------
- db_len 1 (see Note 4)
+ db_len 1 (see Note 3)
db db_len
table_name_len 1
table_name table_name_len
@@ -48,19 +57,99 @@
table_name table_name_len
NOTES
-1. Currently Query_log_event format doesn't include 'query_len' because
+1. In usual format, Query_log_event doesn't include 'query_len' because
it considers the query to extent to the end of the event.
-2. If tables_info is not included in the event (--binlog-with-tables-info
- option), tables_info_len = 0.
-3. The trailing zero is redundant since the length is already known.
-4. In case of db = current db, db_len = 0 and db = empty, because
- current db is already included in the current event format.
+2. For 'db' (current db) the trailing zero is redundant since the length
+ is already known.
+3. db_len = 0 means that this is the current db.
+
+When reading Query events from binary log, we can recognize its format
+by its post-header length: in extended case the post-header includes 4
+additional bytes.
+
+ #define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 4)
++ #define QUERY_HEADER_LEN_EXT (QUERY_HEADER_LEN + 4)
+ ...
+ #define Q_STATUS_VARS_LEN_OFFSET 11
++ #define Q_QUERY_LEN_OFFSET Q_STATUS_VARS_LEN_OFFSET + 2
++ #define Q_QUERY_TABLES_INFO_LEN_OFFSET Q_QUERY_LEN_OFFSET + 2
+
+3. Changes in log events
+************************
+
+3.1. Format description event
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Changes needed here concern setting post-header length for Query events.
+This setting is done in Format description event constructor which creates
+the event for writing to binary log:
+
+ if (binlog_with_tables_info)
+ post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN_EXT;
+ else
+ post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN;
+
+This change is to be done only for case binlog_ver = 4.
+
+NOTE. The refered above constructor is allowed to be invoked in a client
+context for creating "artificial" Format description events in case of
+MySQL < 5.0 (e.g. see mysqlbinlog code). To avoid compilation problems
+(because of 'binlog_with_tables_info') and taking into account the
+"MySQL < 5.0" restriction, we have to #ifdef out the above code in
+following manner:
+
+ switch (binlog_ver) {
+ case 4: /* MySQL 5.0 and higher */
++ #ifndef MYSQL_CLIENT
+ ...
++ #else
++ <error>
++ #endif
+ case 1:
+ case 3:
+ ...
+ }
+
+3.2. Query event
+~~~~~~~~~~~~~~~~
+Changes needed here include adding tables_info and tables_info_len
+members (member for query length already exists) and modifying the
+following function-members:
+
+Query_log_event(buf) constructor
+--------------------------------
+[Parses binary format written to the 'buf']
+
+Getting post-header length from the Format description event (passed
+to the constructor as an argument), define whether buf contains an
+extended or usual Query event and parse the buf contents accordingly.
+
+NOTE. Defining Query event format here should be done with taking into
+account that this constructor can be called within a Query-derived
+event with the event_type argument != QUERY_EVENT.
+
+Query_log_event(thd) constructor
+--------------------------------
+[Creates the event for binlogging]
+
+In case of binlog_with_tables_info = TRUE, set additionally query_len,
+tables_info_len, and tables_info members (the constructor is to have
+an additional 'tables_info' argument).
+
+write() function
+----------------
+[Writes the event to binlog]
+
+In case of binlog_with_tables_info = TRUE, write additional members
+(query_len, tables_info_len, and tables_info) to binary log. Also
+write corresponding whole event length to the common-header.
+
+<To be continued>
-2. Where to get tables info from?
+4. Where to get tables info from?
*********************************
-2.1. Case study: CREATE TABLE
-******************************
+4.1. Case study: CREATE TABLE
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** CREATE TABLE table [SELECT ...]
@@ -129,4 +218,4 @@
}
}
-To be continued
+<To be continued>
-=-=(Alexi - Wed, 04 Nov 2009, 10:21)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.6734 2009-11-04 10:21:20.000000000 +0200
+++ /tmp/wklog.40.new.6734 2009-11-04 10:21:20.000000000 +0200
@@ -21,9 +21,9 @@
slave_proxy_id 4
exec_time 4
db_len 1
-+ query_len 2 (see Note 1)
error_code 2
status_vars_len 2
++ query_len 2 (see Note 1)
+ tables_info_len 2 (see Note 2)
---------------------------------
BODY:
-=-=(Alexi - Tue, 03 Nov 2009, 11:19)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.7187 2009-11-03 11:19:22.000000000 +0200
+++ /tmp/wklog.40.new.7187 2009-11-03 11:19:22.000000000 +0200
@@ -1 +1,132 @@
+OPTION: 2.5 Extend Query Events With Tables Info
+================================================
+1. Query_log_event Binary Format
+********************************
+Changes to be done:
+
+ Query_log_event binary format
+ ---------------------------------
+ Name Size (bytes)
+ ---------------------------------
+ COMMON HEADER:
+ timestamp 4
+ type 1
+ server_id 4
+ total_size 4
+ master_position 4
+ flags 2
+ ---------------------------------
+ POST HEADER:
+ slave_proxy_id 4
+ exec_time 4
+ db_len 1
++ query_len 2 (see Note 1)
+ error_code 2
+ status_vars_len 2
++ tables_info_len 2 (see Note 2)
+ ---------------------------------
+ BODY:
+ status_vars status_vars_len
+- db db_len + 1
++ db db_len (see Note 3)
+ query query_len
++ tables_info
+
+ tables_info binary format
+ ---------------------------------
+ Name Size (bytes)
+ ---------------------------------
+ db_len 1 (see Note 4)
+ db db_len
+ table_name_len 1
+ table_name table_name_len
+ ...
+ db_len 1
+ db db_len
+ table_name_len 1
+ table_name table_name_len
+
+NOTES
+1. Currently Query_log_event format doesn't include 'query_len' because
+ it considers the query to extent to the end of the event.
+2. If tables_info is not included in the event (--binlog-with-tables-info
+ option), tables_info_len = 0.
+3. The trailing zero is redundant since the length is already known.
+4. In case of db = current db, db_len = 0 and db = empty, because
+ current db is already included in the current event format.
+
+2. Where to get tables info from?
+*********************************
+
+2.1. Case study: CREATE TABLE
+******************************
+
+*** CREATE TABLE table [SELECT ...]
+
+ bool mysql_create_table_no_lock(
+ THD *thd,
+ const char *db,
+ const char *table_name, ...)
+ {
+ ...
+ // -------------------------------------
+ // WL40: To be included in tables_info:
+ // * db, table_name
+ // * thd->lex->query_tables (tables refered to in
+ // the select-part; empty if no select-part)
+ // -------------------------------------
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ }
+
+*** CREATE TABLE table LIKE src-table
+
+ bool mysql_create_like_table(
+ ...
+ TABLE_LIST *table,
+ TABLE_LIST *src_table,
+ ...)
+ {
+ ...
+ if (thd->current_stmt_binlog_row_based)
+ { // RBR: In this case we don't replicate temp tables
+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ if (src_table->table->s->tmp_table)
+ { // CREATE normal-table LIKE temp-table:
+
+ // Generate new query without LIKE-part
+ store_create_info(thd, table, &query, create_info, FALSE);
+
+ // -------------------------------------
+ // WL40: To include to tables_info:
+ // * table (src_table is not included)
+ // -------------------------------------
+ write_bin_log(thd, TRUE, query.ptr(), query.length());
+ }
+ else
+ { // CREATE normal-table LIKE normal-table
+
+ // -------------------------------------
+ // WL40: To include to log_tables_info:
+ // * table
+ // * src_table
+ // -------------------------------------
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ }
+ }
+ // CREATE temp-table LIKE ...
+ // This case is not replicated
+ }
+ else
+ { // SBR:
+ // -------------------------------------
+ // WL40: To include to tables_info:
+ // * table
+ // * src_table
+ // -------------------------------------
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ }
+ }
+
+To be continued
-=-=(Alexi - Mon, 02 Nov 2009, 11:34)=-=-
Worked 2 hours on option 2.5
Worked 2 hours and estimate 48 hours remain (original estimate increased by 50 hours).
-=-=(Alexi - Mon, 02 Nov 2009, 11:20)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.4848 2009-11-02 11:20:24.000000000 +0200
+++ /tmp/wklog.40.new.4848 2009-11-02 11:20:24.000000000 +0200
@@ -90,3 +90,25 @@
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
+2.5 Extend Query Events With Tables Info
+----------------------------------------
+
+We could extend query events structure with a tables info - a list of tables
+which the query refers to:
+
+ <current query event structure>
+ tables_info_len
+ dbase_len dbase
+ table_len table
+ ...
+ dbase_len dbase
+ table_len table
+
+Note. In case of <dbase> = current data base, we can set dbase_len = 0
+ and dbase = empty because current query event structure already
+ includes current data base name.
+
+Note. Possibly it is reasonable also to add a --binlog-with-tables-info
+ option which defines whether tables info must be included to the
+ query events.
+
-=-=(Knielsen - Fri, 14 Aug 2009, 15:47)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.10896 2009-08-14 15:47:39.000000000 +0300
+++ /tmp/wklog.40.new.10896 2009-08-14 15:47:39.000000000 +0300
@@ -72,3 +72,21 @@
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
+
+2.4 Implement server functionality to ignore certain tables
+-----------------------------------------------------------
+
+We could add a general facility in the server to ignore certain tables:
+
+ SET SESSION ignored_tables = "db1.t1,db2.t2";
+
+This would work similar to --replicate-ignore-table, but in a general way not
+restricted to the slave SQL thread.
+
+It would then be trivial for mysqlbinlog to add such statements at the start
+of the output, or probably the user could just do it manually with no need for
+additional options for mysqlbinlog.
+
+It might be useful to integrate this with the code that already handles
+--replicate-ignore-db and similar slave options.
+
-=-=(Psergey - Mon, 10 Aug 2009, 15:41)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.12989 2009-08-10 15:41:23.000000000 +0300
+++ /tmp/wklog.40.new.12989 2009-08-10 15:41:23.000000000 +0300
@@ -1,6 +1,7 @@
-
1. Context
----------
+(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
+overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
------------------------------------------------------------
-=-=(View All Progress Notes, 13 total)=-=-
http://askmonty.org/worklog/index.pl?tid=40&nolimit=1
DESCRIPTION:
Replication slave can be set to filter updates to certain tables with
--replicate-[wild-]{do,ignore}-table options.
This task is about adding similar functionality to mysqlbinlog.
HIGH-LEVEL SPECIFICATION:
1. Context
----------
(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
--replicate-ignore-table=db.tbl
--replicate-wild-do-table=pattern.pattern
--replicate-wild-ignore-table=pattern.pattern
They affect both RBR and SBR events. SBR events are checked after the
statement has been parsed, the server iterates over list of used tables and
checks them againist --replicate instructions.
What is interesting is that this scheme still allows to update the ignored
table through a VIEW.
2. Table filtering in mysqlbinlog
---------------------------------
Per-table filtering of RBR events is easy (as it is relatively easy to extract
the name of the table that the event applies to).
Per-table filtering of SBR events is hard, as generally it is not apparent
which tables the statement refers to.
This opens possible options:
2.1 Put the parser into mysqlbinlog
-----------------------------------
Once we have a full parser in mysqlbinlog, we'll be able to check which tables
are used by a statement, and will allow to show behaviour identical to those
that one obtains when using --replicate-* slave options.
(It is not clear how much effort is needed to put the parser into mysqlbinlog.
Any guesses?)
2.2 Use dumb regexp match
-------------------------
Use a really dumb approach. A query is considered to be modifying table X if
it matches an expression
CREATE TABLE $tablename
DROP $tablename
UPDATE ...$tablename ... SET // here '...' can't contain the word 'SET'
DELETE ...$tablename ... WHERE // same as above
ALTER TABLE $tablename
.. etc (go get from the grammar) ..
The advantage over doing the same in awk is that mysqlbinlog will also process
RBR statements, and together with that will provide a working solution for
those who are careful with their table names not mixing with string constants
and such.
(TODO: string constants are of particular concern as they come from
[potentially hostile] users, unlike e.g. table aliases which come from
[not hostile] developers. Remove also all string constants before attempting
to do match?)
2.3 Have the master put annotations
-----------------------------------
We could add a master option so that it injects into query a mark that tells
which tables the query will affect, e.g. for the query
UPDATE t1 LEFT JOIN db3.t2 ON ... WHERE ...
the binlog will have
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
2.4 Implement server functionality to ignore certain tables
-----------------------------------------------------------
We could add a general facility in the server to ignore certain tables:
SET SESSION ignored_tables = "db1.t1,db2.t2";
This would work similar to --replicate-ignore-table, but in a general way not
restricted to the slave SQL thread.
It would then be trivial for mysqlbinlog to add such statements at the start
of the output, or probably the user could just do it manually with no need for
additional options for mysqlbinlog.
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
2.5 Extend Query Events With Tables Info
----------------------------------------
We could extend query events structure with a tables info - a list of tables
which the query refers to:
<current query event structure>
tables_info_len
dbase_len dbase
table_len table
...
dbase_len dbase
table_len table
Note. In case of <dbase> = current data base, we can set dbase_len = 0
and dbase = empty because current query event structure already
includes current data base name.
Note. Possibly it is reasonable also to add a --binlog-with-tables-info
option which defines whether tables info must be included to the
query events.
LOW-LEVEL DESIGN:
OPTION: 2.5 Extend Query Events With Tables Info
================================================
1. Adding --binlog-with-tables-info option
******************************************
GLOBAL, read-only option.
When set, Query events are to be written in the extended binary
format which contains tables_info. When not set, Query events
are to be written in usual format (without any changes).
2. Query event extended binary format
*************************************
When --binlog-with-tables-info is set, Query events are writen
to binary log in the following (extended) format.
Query_log_event binary format
---------------------------------
Name Size (bytes)
---------------------------------
COMMON HEADER:
timestamp 4
type 1
server_id 4
total_size 4
master_position 4
flags 2
---------------------------------
POST HEADER:
slave_proxy_id 4
exec_time 4
db_len 1
error_code 2
status_vars_len 2
+ query_len 2 (see Note 1)
+ tables_info_len 2
---------------------------------
BODY:
status_vars status_vars_len
- db db_len + 1
+ db db_len (see Note 2)
query query_len
+ tables_info
tables_info binary format
---------------------------------
Name Size (bytes)
---------------------------------
db_len 1 (see Note 3)
db db_len
table_name_len 1
table_name table_name_len
...
db_len 1
db db_len
table_name_len 1
table_name table_name_len
NOTES
1. In usual format, Query_log_event doesn't include 'query_len' because
it considers the query to extent to the end of the event.
2. For 'db' (current db) the trailing zero is redundant since the length
is already known.
3. In tables_info, db_len = 0 means that this is the current db.
When reading Query events from binary log, we can recognize its format
by its post-header length: in extended case the post-header includes 4
additional bytes.
#define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 4)
+ #define QUERY_HEADER_LEN_EXT (QUERY_HEADER_LEN + 4)
...
#define Q_STATUS_VARS_LEN_OFFSET 11
+ #define Q_QUERY_LEN_OFFSET Q_STATUS_VARS_LEN_OFFSET + 2
+ #define Q_QUERY_TABLES_INFO_LEN_OFFSET Q_QUERY_LEN_OFFSET + 2
***********************************************************************
HELP NEEDED
***********************************************************************
The QUERY_HEADER_LEN is used in the definition of MAX_LOG_EVENT_HEADER:
log_event.h
~~~~~~~~~~~
#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
LOG_EVENT_HEADER_LEN + /* write_header */ \
QUERY_HEADER_LEN + /* write_data */ \
EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
NAME_LEN + 1)
which is used only for setting
thd->variables.max_allowed_packet
mysql->net.max_packet_size
Looks like (but I am not quite sure) that QUERY_HEADER_LEN can simply
(without making any other changes) be substituted in this definition by
QUERY_HEADER_LEN_EXT.
Below I list all places where MAX_LOG_EVENT_HEADER is used:
slave.cc
~~~~~~~~
static int init_slave_thread(...)
{ ...
/*
Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all
slave threads, since a replication event can become this much larger
than the corresponding packet (query) sent from client to master.
*/
thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
...
}
pthread_handler_t handle_slave_io(...)
{ ...
/*
Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
thread, since a replication event can become this much larger than
the corresponding packet (query) sent from client to master.
*/
mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
...
}
sql_repl.cc
~~~~~~~~~~~
void mysql_binlog_send(...)
{ ...
/*
Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
this larger than the corresponding packet (query) sent
from client to master.
*/
thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
...
}
bool mysql_show_binlog_events(...)
{ ...
/*
to account binlog event header size
*/
thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
...
}
3. Changes in log events
************************
3.1. Format description event
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Changes needed here concern setting post-header length for Query events.
This setting is done in Format description event constructor which creates
the event for writing to binary log:
if (opt_binlog_with_tables_info)
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN_EXT;
else
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN;
This change is to be done only for case binlog_ver = 4.
NOTE. The refered above constructor is allowed to be invoked in a client
context for creating "artificial" Format description events in case of
MySQL < 5.0 (e.g. see mysqlbinlog code). To avoid compilation problems
(because of 'binlog_with_tables_info') and taking into account the
"MySQL < 5.0" restriction, we have to #ifdef out the above code in
following manner:
switch (binlog_ver) {
+ #ifndef MYSQL_CLIENT
case 4: /* MySQL 5.0 and higher */
...
break;
+ #endif
case 1:
case 3:
...
}
3.2. Query event
~~~~~~~~~~~~~~~~
Changes needed here include adding tables_info and tables_info_len
members (member for query length already exists) and modifying the
following function-members:
Query_log_event(buf) constructor
--------------------------------
[Parses binary format written to the 'buf']
Getting post-header length from the Format description event (passed
to the constructor as an argument), define whether buf contains an
extended or usual Query event and parse the buf contents accordingly.
NOTE. Defining Query event format here should be done with taking into
account that this constructor can be called within a Query-derived
event with the event_type argument != QUERY_EVENT.
Query_log_event(thd) constructor
--------------------------------
[Creates the event for binlogging]
In case of opt_binlog_with_tables_info = TRUE, set additionally query_len,
tables_info_len, and tables_info members (the constructor is to have
an additional 'tables_info' argument).
write() function
----------------
[Writes the event to binlog]
In case of opt_binlog_with_tables_info = TRUE, write additional members
(query_len, tables_info_len, and tables_info) to binary log. Also
write corresponding whole event length to the common-header.
<To be continued>
4. Where to get tables info from?
*********************************
4.1. Case study: CREATE TABLE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** CREATE TABLE table [SELECT ...]
bool mysql_create_table_no_lock(
THD *thd,
const char *db,
const char *table_name, ...)
{
...
// -------------------------------------
// WL40: To be included in tables_info:
// * db, table_name
// * thd->lex->query_tables (tables refered to in
// the select-part; empty if no select-part)
// -------------------------------------
write_bin_log(thd, TRUE, thd->query, thd->query_length);
}
*** CREATE TABLE table LIKE src-table
bool mysql_create_like_table(
...
TABLE_LIST *table,
TABLE_LIST *src_table,
...)
{
...
if (thd->current_stmt_binlog_row_based)
{ // RBR: In this case we don't replicate temp tables
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (src_table->table->s->tmp_table)
{ // CREATE normal-table LIKE temp-table:
// Generate new query without LIKE-part
store_create_info(thd, table, &query, create_info, FALSE);
// -------------------------------------
// WL40: To include to tables_info:
// * table (src_table is not included)
// -------------------------------------
write_bin_log(thd, TRUE, query.ptr(), query.length());
}
else
{ // CREATE normal-table LIKE normal-table
// -------------------------------------
// WL40: To include to log_tables_info:
// * table
// * src_table
// -------------------------------------
write_bin_log(thd, TRUE, thd->query, thd->query_length);
}
}
// CREATE temp-table LIKE ...
// This case is not replicated
}
else
{ // SBR:
// -------------------------------------
// WL40: To include to tables_info:
// * table
// * src_table
// -------------------------------------
write_bin_log(thd, TRUE, thd->query, thd->query_length);
}
}
<To be continued>
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] Progress (by Bothorsen): Add a mysqlbinlog option to filter updates to certain tables (40)
by worklog-noreply@askmonty.org 12 Nov '09
by worklog-noreply@askmonty.org 12 Nov '09
12 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add a mysqlbinlog option to filter updates to certain tables
CREATION DATE..: Mon, 10 Aug 2009, 13:25
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Psergey
CATEGORY.......: Server-RawIdeaBin
TASK ID........: 40 (http://askmonty.org/worklog/?tid=40)
VERSION........: Server-9.x
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 18
ESTIMATE.......: 46 (hours remain)
ORIG. ESTIMATE.: 48
PROGRESS NOTES:
-=-=(Bothorsen - Thu, 12 Nov 2009, 13:13)=-=-
Work hours by Alexi and Bo + estimated time for the task.
Worked 16 hours and estimate 46 hours remain (original estimate increased by 14 hours).
-=-=(Alexi - Sun, 08 Nov 2009, 15:18)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.15787 2009-11-08 15:18:11.000000000 +0200
+++ /tmp/wklog.40.new.15787 2009-11-08 15:18:11.000000000 +0200
@@ -62,7 +62,7 @@
it considers the query to extent to the end of the event.
2. For 'db' (current db) the trailing zero is redundant since the length
is already known.
-3. db_len = 0 means that this is the current db.
+3. In tables_info, db_len = 0 means that this is the current db.
When reading Query events from binary log, we can recognize its format
by its post-header length: in extended case the post-header includes 4
@@ -75,6 +75,77 @@
+ #define Q_QUERY_LEN_OFFSET Q_STATUS_VARS_LEN_OFFSET + 2
+ #define Q_QUERY_TABLES_INFO_LEN_OFFSET Q_QUERY_LEN_OFFSET + 2
+
+***********************************************************************
+HELP NEEDED
+***********************************************************************
+The QUERY_HEADER_LEN is used in the definition of MAX_LOG_EVENT_HEADER:
+
+log_event.h
+~~~~~~~~~~~
+#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
+ LOG_EVENT_HEADER_LEN + /* write_header */ \
+ QUERY_HEADER_LEN + /* write_data */ \
+ EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
+ MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
+ NAME_LEN + 1)
+
+which is used only for setting
+
+ thd->variables.max_allowed_packet
+ mysql->net.max_packet_size
+
+Looks like (but I am not quite sure) that QUERY_HEADER_LEN can simply
+(without making any other changes) be substituted in this definition by
+QUERY_HEADER_LEN_EXT.
+
+Below I list all places where MAX_LOG_EVENT_HEADER is used:
+
+slave.cc
+~~~~~~~~
+static int init_slave_thread(...)
+{ ...
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all
+ slave threads, since a replication event can become this much larger
+ than the corresponding packet (query) sent from client to master.
+ */
+ thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
+ ...
+}
+pthread_handler_t handle_slave_io(...)
+{ ...
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
+ thread, since a replication event can become this much larger than
+ the corresponding packet (query) sent from client to master.
+ */
+ mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
+ ...
+}
+
+sql_repl.cc
+~~~~~~~~~~~
+void mysql_binlog_send(...)
+{ ...
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
+ this larger than the corresponding packet (query) sent
+ from client to master.
+ */
+ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
+ ...
+}
+bool mysql_show_binlog_events(...)
+{ ...
+ /*
+ to account binlog event header size
+ */
+ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
+ ...
+}
+
3. Changes in log events
************************
@@ -84,7 +155,7 @@
This setting is done in Format description event constructor which creates
the event for writing to binary log:
- if (binlog_with_tables_info)
+ if (opt_binlog_with_tables_info)
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN_EXT;
else
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN;
@@ -99,12 +170,12 @@
following manner:
switch (binlog_ver) {
- case 4: /* MySQL 5.0 and higher */
+ #ifndef MYSQL_CLIENT
+ case 4: /* MySQL 5.0 and higher */
...
-+ #else
-+ <error>
+ break;
+ #endif
+
case 1:
case 3:
...
@@ -132,7 +203,7 @@
--------------------------------
[Creates the event for binlogging]
-In case of binlog_with_tables_info = TRUE, set additionally query_len,
+In case of opt_binlog_with_tables_info = TRUE, set additionally query_len,
tables_info_len, and tables_info members (the constructor is to have
an additional 'tables_info' argument).
@@ -140,7 +211,7 @@
----------------
[Writes the event to binlog]
-In case of binlog_with_tables_info = TRUE, write additional members
+In case of opt_binlog_with_tables_info = TRUE, write additional members
(query_len, tables_info_len, and tables_info) to binary log. Also
write corresponding whole event length to the common-header.
-=-=(Alexi - Sun, 08 Nov 2009, 10:40)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.5055 2009-11-08 08:40:02.000000000 +0000
+++ /tmp/wklog.40.new.5055 2009-11-08 08:40:02.000000000 +0000
@@ -3,6 +3,7 @@
1. Adding --binlog-with-tables-info option
******************************************
+GLOBAL, read-only option.
When set, Query events are to be written in the extended binary
format which contains tables_info. When not set, Query events
-=-=(Alexi - Thu, 05 Nov 2009, 12:37)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.11441 2009-11-05 12:37:16.000000000 +0200
+++ /tmp/wklog.40.new.11441 2009-11-05 12:37:16.000000000 +0200
@@ -1,9 +1,18 @@
OPTION: 2.5 Extend Query Events With Tables Info
================================================
-1. Query_log_event Binary Format
-********************************
-Changes to be done:
+1. Adding --binlog-with-tables-info option
+******************************************
+
+When set, Query events are to be written in the extended binary
+format which contains tables_info. When not set, Query events
+are to be written in usual format (without any changes).
+
+2. Query event extended binary format
+*************************************
+
+When --binlog-with-tables-info is set, Query events are writen
+to binary log in the following (extended) format.
Query_log_event binary format
---------------------------------
@@ -24,12 +33,12 @@
error_code 2
status_vars_len 2
+ query_len 2 (see Note 1)
-+ tables_info_len 2 (see Note 2)
++ tables_info_len 2
---------------------------------
BODY:
status_vars status_vars_len
- db db_len + 1
-+ db db_len (see Note 3)
++ db db_len (see Note 2)
query query_len
+ tables_info
@@ -37,7 +46,7 @@
---------------------------------
Name Size (bytes)
---------------------------------
- db_len 1 (see Note 4)
+ db_len 1 (see Note 3)
db db_len
table_name_len 1
table_name table_name_len
@@ -48,19 +57,99 @@
table_name table_name_len
NOTES
-1. Currently Query_log_event format doesn't include 'query_len' because
+1. In usual format, Query_log_event doesn't include 'query_len' because
it considers the query to extent to the end of the event.
-2. If tables_info is not included in the event (--binlog-with-tables-info
- option), tables_info_len = 0.
-3. The trailing zero is redundant since the length is already known.
-4. In case of db = current db, db_len = 0 and db = empty, because
- current db is already included in the current event format.
+2. For 'db' (current db) the trailing zero is redundant since the length
+ is already known.
+3. db_len = 0 means that this is the current db.
+
+When reading Query events from binary log, we can recognize its format
+by its post-header length: in extended case the post-header includes 4
+additional bytes.
+
+ #define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 4)
++ #define QUERY_HEADER_LEN_EXT (QUERY_HEADER_LEN + 4)
+ ...
+ #define Q_STATUS_VARS_LEN_OFFSET 11
++ #define Q_QUERY_LEN_OFFSET Q_STATUS_VARS_LEN_OFFSET + 2
++ #define Q_QUERY_TABLES_INFO_LEN_OFFSET Q_QUERY_LEN_OFFSET + 2
+
+3. Changes in log events
+************************
+
+3.1. Format description event
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Changes needed here concern setting post-header length for Query events.
+This setting is done in Format description event constructor which creates
+the event for writing to binary log:
+
+ if (binlog_with_tables_info)
+ post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN_EXT;
+ else
+ post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN;
+
+This change is to be done only for case binlog_ver = 4.
+
+NOTE. The refered above constructor is allowed to be invoked in a client
+context for creating "artificial" Format description events in case of
+MySQL < 5.0 (e.g. see mysqlbinlog code). To avoid compilation problems
+(because of 'binlog_with_tables_info') and taking into account the
+"MySQL < 5.0" restriction, we have to #ifdef out the above code in
+following manner:
+
+ switch (binlog_ver) {
+ case 4: /* MySQL 5.0 and higher */
++ #ifndef MYSQL_CLIENT
+ ...
++ #else
++ <error>
++ #endif
+ case 1:
+ case 3:
+ ...
+ }
+
+3.2. Query event
+~~~~~~~~~~~~~~~~
+Changes needed here include adding tables_info and tables_info_len
+members (member for query length already exists) and modifying the
+following function-members:
+
+Query_log_event(buf) constructor
+--------------------------------
+[Parses binary format written to the 'buf']
+
+Getting post-header length from the Format description event (passed
+to the constructor as an argument), define whether buf contains an
+extended or usual Query event and parse the buf contents accordingly.
+
+NOTE. Defining Query event format here should be done with taking into
+account that this constructor can be called within a Query-derived
+event with the event_type argument != QUERY_EVENT.
+
+Query_log_event(thd) constructor
+--------------------------------
+[Creates the event for binlogging]
+
+In case of binlog_with_tables_info = TRUE, set additionally query_len,
+tables_info_len, and tables_info members (the constructor is to have
+an additional 'tables_info' argument).
+
+write() function
+----------------
+[Writes the event to binlog]
+
+In case of binlog_with_tables_info = TRUE, write additional members
+(query_len, tables_info_len, and tables_info) to binary log. Also
+write corresponding whole event length to the common-header.
+
+<To be continued>
-2. Where to get tables info from?
+4. Where to get tables info from?
*********************************
-2.1. Case study: CREATE TABLE
-******************************
+4.1. Case study: CREATE TABLE
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** CREATE TABLE table [SELECT ...]
@@ -129,4 +218,4 @@
}
}
-To be continued
+<To be continued>
-=-=(Alexi - Wed, 04 Nov 2009, 10:21)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.6734 2009-11-04 10:21:20.000000000 +0200
+++ /tmp/wklog.40.new.6734 2009-11-04 10:21:20.000000000 +0200
@@ -21,9 +21,9 @@
slave_proxy_id 4
exec_time 4
db_len 1
-+ query_len 2 (see Note 1)
error_code 2
status_vars_len 2
++ query_len 2 (see Note 1)
+ tables_info_len 2 (see Note 2)
---------------------------------
BODY:
-=-=(Alexi - Tue, 03 Nov 2009, 11:19)=-=-
Low Level Design modified.
--- /tmp/wklog.40.old.7187 2009-11-03 11:19:22.000000000 +0200
+++ /tmp/wklog.40.new.7187 2009-11-03 11:19:22.000000000 +0200
@@ -1 +1,132 @@
+OPTION: 2.5 Extend Query Events With Tables Info
+================================================
+1. Query_log_event Binary Format
+********************************
+Changes to be done:
+
+ Query_log_event binary format
+ ---------------------------------
+ Name Size (bytes)
+ ---------------------------------
+ COMMON HEADER:
+ timestamp 4
+ type 1
+ server_id 4
+ total_size 4
+ master_position 4
+ flags 2
+ ---------------------------------
+ POST HEADER:
+ slave_proxy_id 4
+ exec_time 4
+ db_len 1
++ query_len 2 (see Note 1)
+ error_code 2
+ status_vars_len 2
++ tables_info_len 2 (see Note 2)
+ ---------------------------------
+ BODY:
+ status_vars status_vars_len
+- db db_len + 1
++ db db_len (see Note 3)
+ query query_len
++ tables_info
+
+ tables_info binary format
+ ---------------------------------
+ Name Size (bytes)
+ ---------------------------------
+ db_len 1 (see Note 4)
+ db db_len
+ table_name_len 1
+ table_name table_name_len
+ ...
+ db_len 1
+ db db_len
+ table_name_len 1
+ table_name table_name_len
+
+NOTES
+1. Currently Query_log_event format doesn't include 'query_len' because
+ it considers the query to extent to the end of the event.
+2. If tables_info is not included in the event (--binlog-with-tables-info
+ option), tables_info_len = 0.
+3. The trailing zero is redundant since the length is already known.
+4. In case of db = current db, db_len = 0 and db = empty, because
+ current db is already included in the current event format.
+
+2. Where to get tables info from?
+*********************************
+
+2.1. Case study: CREATE TABLE
+******************************
+
+*** CREATE TABLE table [SELECT ...]
+
+ bool mysql_create_table_no_lock(
+ THD *thd,
+ const char *db,
+ const char *table_name, ...)
+ {
+ ...
+ // -------------------------------------
+ // WL40: To be included in tables_info:
+ // * db, table_name
+ // * thd->lex->query_tables (tables refered to in
+ // the select-part; empty if no select-part)
+ // -------------------------------------
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ }
+
+*** CREATE TABLE table LIKE src-table
+
+ bool mysql_create_like_table(
+ ...
+ TABLE_LIST *table,
+ TABLE_LIST *src_table,
+ ...)
+ {
+ ...
+ if (thd->current_stmt_binlog_row_based)
+ { // RBR: In this case we don't replicate temp tables
+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ if (src_table->table->s->tmp_table)
+ { // CREATE normal-table LIKE temp-table:
+
+ // Generate new query without LIKE-part
+ store_create_info(thd, table, &query, create_info, FALSE);
+
+ // -------------------------------------
+ // WL40: To include to tables_info:
+ // * table (src_table is not included)
+ // -------------------------------------
+ write_bin_log(thd, TRUE, query.ptr(), query.length());
+ }
+ else
+ { // CREATE normal-table LIKE normal-table
+
+ // -------------------------------------
+ // WL40: To include to log_tables_info:
+ // * table
+ // * src_table
+ // -------------------------------------
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ }
+ }
+ // CREATE temp-table LIKE ...
+ // This case is not replicated
+ }
+ else
+ { // SBR:
+ // -------------------------------------
+ // WL40: To include to tables_info:
+ // * table
+ // * src_table
+ // -------------------------------------
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ }
+ }
+
+To be continued
-=-=(Alexi - Mon, 02 Nov 2009, 11:34)=-=-
Worked 2 hours on option 2.5
Worked 2 hours and estimate 48 hours remain (original estimate increased by 50 hours).
-=-=(Alexi - Mon, 02 Nov 2009, 11:20)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.4848 2009-11-02 11:20:24.000000000 +0200
+++ /tmp/wklog.40.new.4848 2009-11-02 11:20:24.000000000 +0200
@@ -90,3 +90,25 @@
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
+2.5 Extend Query Events With Tables Info
+----------------------------------------
+
+We could extend query events structure with a tables info - a list of tables
+which the query refers to:
+
+ <current query event structure>
+ tables_info_len
+ dbase_len dbase
+ table_len table
+ ...
+ dbase_len dbase
+ table_len table
+
+Note. In case of <dbase> = current data base, we can set dbase_len = 0
+ and dbase = empty because current query event structure already
+ includes current data base name.
+
+Note. Possibly it is reasonable also to add a --binlog-with-tables-info
+ option which defines whether tables info must be included to the
+ query events.
+
-=-=(Knielsen - Fri, 14 Aug 2009, 15:47)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.10896 2009-08-14 15:47:39.000000000 +0300
+++ /tmp/wklog.40.new.10896 2009-08-14 15:47:39.000000000 +0300
@@ -72,3 +72,21 @@
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
+
+2.4 Implement server functionality to ignore certain tables
+-----------------------------------------------------------
+
+We could add a general facility in the server to ignore certain tables:
+
+ SET SESSION ignored_tables = "db1.t1,db2.t2";
+
+This would work similar to --replicate-ignore-table, but in a general way not
+restricted to the slave SQL thread.
+
+It would then be trivial for mysqlbinlog to add such statements at the start
+of the output, or probably the user could just do it manually with no need for
+additional options for mysqlbinlog.
+
+It might be useful to integrate this with the code that already handles
+--replicate-ignore-db and similar slave options.
+
-=-=(Psergey - Mon, 10 Aug 2009, 15:41)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.12989 2009-08-10 15:41:23.000000000 +0300
+++ /tmp/wklog.40.new.12989 2009-08-10 15:41:23.000000000 +0300
@@ -1,6 +1,7 @@
-
1. Context
----------
+(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
+overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
------------------------------------------------------------
-=-=(View All Progress Notes, 13 total)=-=-
http://askmonty.org/worklog/index.pl?tid=40&nolimit=1
DESCRIPTION:
Replication slave can be set to filter updates to certain tables with
--replicate-[wild-]{do,ignore}-table options.
This task is about adding similar functionality to mysqlbinlog.
HIGH-LEVEL SPECIFICATION:
1. Context
----------
(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
--replicate-ignore-table=db.tbl
--replicate-wild-do-table=pattern.pattern
--replicate-wild-ignore-table=pattern.pattern
They affect both RBR and SBR events. SBR events are checked after the
statement has been parsed, the server iterates over list of used tables and
checks them againist --replicate instructions.
What is interesting is that this scheme still allows to update the ignored
table through a VIEW.
2. Table filtering in mysqlbinlog
---------------------------------
Per-table filtering of RBR events is easy (as it is relatively easy to extract
the name of the table that the event applies to).
Per-table filtering of SBR events is hard, as generally it is not apparent
which tables the statement refers to.
This opens possible options:
2.1 Put the parser into mysqlbinlog
-----------------------------------
Once we have a full parser in mysqlbinlog, we'll be able to check which tables
are used by a statement, and will allow to show behaviour identical to those
that one obtains when using --replicate-* slave options.
(It is not clear how much effort is needed to put the parser into mysqlbinlog.
Any guesses?)
2.2 Use dumb regexp match
-------------------------
Use a really dumb approach. A query is considered to be modifying table X if
it matches an expression
CREATE TABLE $tablename
DROP $tablename
UPDATE ...$tablename ... SET // here '...' can't contain the word 'SET'
DELETE ...$tablename ... WHERE // same as above
ALTER TABLE $tablename
.. etc (go get from the grammar) ..
The advantage over doing the same in awk is that mysqlbinlog will also process
RBR statements, and together with that will provide a working solution for
those who are careful with their table names not mixing with string constants
and such.
(TODO: string constants are of particular concern as they come from
[potentially hostile] users, unlike e.g. table aliases which come from
[not hostile] developers. Remove also all string constants before attempting
to do match?)
2.3 Have the master put annotations
-----------------------------------
We could add a master option so that it injects into query a mark that tells
which tables the query will affect, e.g. for the query
UPDATE t1 LEFT JOIN db3.t2 ON ... WHERE ...
the binlog will have
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
2.4 Implement server functionality to ignore certain tables
-----------------------------------------------------------
We could add a general facility in the server to ignore certain tables:
SET SESSION ignored_tables = "db1.t1,db2.t2";
This would work similar to --replicate-ignore-table, but in a general way not
restricted to the slave SQL thread.
It would then be trivial for mysqlbinlog to add such statements at the start
of the output, or probably the user could just do it manually with no need for
additional options for mysqlbinlog.
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
2.5 Extend Query Events With Tables Info
----------------------------------------
We could extend query events structure with a tables info - a list of tables
which the query refers to:
<current query event structure>
tables_info_len
dbase_len dbase
table_len table
...
dbase_len dbase
table_len table
Note. In case of <dbase> = current data base, we can set dbase_len = 0
and dbase = empty because current query event structure already
includes current data base name.
Note. Possibly it is reasonable also to add a --binlog-with-tables-info
option which defines whether tables info must be included to the
query events.
LOW-LEVEL DESIGN:
OPTION: 2.5 Extend Query Events With Tables Info
================================================
1. Adding --binlog-with-tables-info option
******************************************
GLOBAL, read-only option.
When set, Query events are to be written in the extended binary
format which contains tables_info. When not set, Query events
are to be written in usual format (without any changes).
2. Query event extended binary format
*************************************
When --binlog-with-tables-info is set, Query events are writen
to binary log in the following (extended) format.
Query_log_event binary format
---------------------------------
Name Size (bytes)
---------------------------------
COMMON HEADER:
timestamp 4
type 1
server_id 4
total_size 4
master_position 4
flags 2
---------------------------------
POST HEADER:
slave_proxy_id 4
exec_time 4
db_len 1
error_code 2
status_vars_len 2
+ query_len 2 (see Note 1)
+ tables_info_len 2
---------------------------------
BODY:
status_vars status_vars_len
- db db_len + 1
+ db db_len (see Note 2)
query query_len
+ tables_info
tables_info binary format
---------------------------------
Name Size (bytes)
---------------------------------
db_len 1 (see Note 3)
db db_len
table_name_len 1
table_name table_name_len
...
db_len 1
db db_len
table_name_len 1
table_name table_name_len
NOTES
1. In usual format, Query_log_event doesn't include 'query_len' because
it considers the query to extent to the end of the event.
2. For 'db' (current db) the trailing zero is redundant since the length
is already known.
3. In tables_info, db_len = 0 means that this is the current db.
When reading Query events from binary log, we can recognize its format
by its post-header length: in extended case the post-header includes 4
additional bytes.
#define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 4)
+ #define QUERY_HEADER_LEN_EXT (QUERY_HEADER_LEN + 4)
...
#define Q_STATUS_VARS_LEN_OFFSET 11
+ #define Q_QUERY_LEN_OFFSET Q_STATUS_VARS_LEN_OFFSET + 2
+ #define Q_QUERY_TABLES_INFO_LEN_OFFSET Q_QUERY_LEN_OFFSET + 2
***********************************************************************
HELP NEEDED
***********************************************************************
The QUERY_HEADER_LEN is used in the definition of MAX_LOG_EVENT_HEADER:
log_event.h
~~~~~~~~~~~
#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
LOG_EVENT_HEADER_LEN + /* write_header */ \
QUERY_HEADER_LEN + /* write_data */ \
EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
NAME_LEN + 1)
which is used only for setting
thd->variables.max_allowed_packet
mysql->net.max_packet_size
Looks like (but I am not quite sure) that QUERY_HEADER_LEN can simply
(without making any other changes) be substituted in this definition by
QUERY_HEADER_LEN_EXT.
Below I list all places where MAX_LOG_EVENT_HEADER is used:
slave.cc
~~~~~~~~
static int init_slave_thread(...)
{ ...
/*
Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all
slave threads, since a replication event can become this much larger
than the corresponding packet (query) sent from client to master.
*/
thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
...
}
pthread_handler_t handle_slave_io(...)
{ ...
/*
Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
thread, since a replication event can become this much larger than
the corresponding packet (query) sent from client to master.
*/
mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
...
}
sql_repl.cc
~~~~~~~~~~~
void mysql_binlog_send(...)
{ ...
/*
Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
this larger than the corresponding packet (query) sent
from client to master.
*/
thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
...
}
bool mysql_show_binlog_events(...)
{ ...
/*
to account binlog event header size
*/
thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
...
}
3. Changes in log events
************************
3.1. Format description event
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Changes needed here concern setting post-header length for Query events.
This setting is done in Format description event constructor which creates
the event for writing to binary log:
if (opt_binlog_with_tables_info)
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN_EXT;
else
post_header_len[QUERY_EVENT - 1] = QUERY_HEADER_LEN;
This change is to be done only for case binlog_ver = 4.
NOTE. The refered above constructor is allowed to be invoked in a client
context for creating "artificial" Format description events in case of
MySQL < 5.0 (e.g. see mysqlbinlog code). To avoid compilation problems
(because of 'binlog_with_tables_info') and taking into account the
"MySQL < 5.0" restriction, we have to #ifdef out the above code in
following manner:
switch (binlog_ver) {
+ #ifndef MYSQL_CLIENT
case 4: /* MySQL 5.0 and higher */
...
break;
+ #endif
case 1:
case 3:
...
}
3.2. Query event
~~~~~~~~~~~~~~~~
Changes needed here include adding tables_info and tables_info_len
members (member for query length already exists) and modifying the
following function-members:
Query_log_event(buf) constructor
--------------------------------
[Parses binary format written to the 'buf']
Getting post-header length from the Format description event (passed
to the constructor as an argument), define whether buf contains an
extended or usual Query event and parse the buf contents accordingly.
NOTE. Defining Query event format here should be done with taking into
account that this constructor can be called within a Query-derived
event with the event_type argument != QUERY_EVENT.
Query_log_event(thd) constructor
--------------------------------
[Creates the event for binlogging]
In case of opt_binlog_with_tables_info = TRUE, set additionally query_len,
tables_info_len, and tables_info members (the constructor is to have
an additional 'tables_info' argument).
write() function
----------------
[Writes the event to binlog]
In case of opt_binlog_with_tables_info = TRUE, write additional members
(query_len, tables_info_len, and tables_info) to binary log. Also
write corresponding whole event length to the common-header.
<To be continued>
4. Where to get tables info from?
*********************************
4.1. Case study: CREATE TABLE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** CREATE TABLE table [SELECT ...]
bool mysql_create_table_no_lock(
THD *thd,
const char *db,
const char *table_name, ...)
{
...
// -------------------------------------
// WL40: To be included in tables_info:
// * db, table_name
// * thd->lex->query_tables (tables refered to in
// the select-part; empty if no select-part)
// -------------------------------------
write_bin_log(thd, TRUE, thd->query, thd->query_length);
}
*** CREATE TABLE table LIKE src-table
bool mysql_create_like_table(
...
TABLE_LIST *table,
TABLE_LIST *src_table,
...)
{
...
if (thd->current_stmt_binlog_row_based)
{ // RBR: In this case we don't replicate temp tables
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (src_table->table->s->tmp_table)
{ // CREATE normal-table LIKE temp-table:
// Generate new query without LIKE-part
store_create_info(thd, table, &query, create_info, FALSE);
// -------------------------------------
// WL40: To include to tables_info:
// * table (src_table is not included)
// -------------------------------------
write_bin_log(thd, TRUE, query.ptr(), query.length());
}
else
{ // CREATE normal-table LIKE normal-table
// -------------------------------------
// WL40: To include to log_tables_info:
// * table
// * src_table
// -------------------------------------
write_bin_log(thd, TRUE, thd->query, thd->query_length);
}
}
// CREATE temp-table LIKE ...
// This case is not replicated
}
else
{ // SBR:
// -------------------------------------
// WL40: To include to tables_info:
// * table
// * src_table
// -------------------------------------
write_bin_log(thd, TRUE, thd->query, thd->query_length);
}
}
<To be continued>
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (igor:2765) Bug#42116 WL#17
by Igor Babaev 12 Nov '09
by Igor Babaev 12 Nov '09
12 Nov '09
#At lp:maria based on revid:monty@mysql.com-20091111111749-dnv4ams2mnb8b8rp
2765 Igor Babaev 2009-11-11
Corrected a line from the patch for table elimination (WL#17)
to fix a problem with the test case for bug#42116.
modified:
sql/sql_select.cc
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2009-11-11 11:17:49 +0000
+++ b/sql/sql_select.cc 2009-11-12 04:45:31 +0000
@@ -8937,7 +8937,7 @@ static uint reset_nj_counters(JOIN *join
// ~join->eliminated_tables);
nested_join->n_tables= reset_nj_counters(join, &nested_join->join_list);
}
- if (table->table && (table->table->map & ~join->eliminated_tables))
+ if (!table->table || (table->table->map & ~join->eliminated_tables))
n++;
}
DBUG_RETURN(n);
1
0
[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2732)
by Igor Babaev 12 Nov '09
by Igor Babaev 12 Nov '09
12 Nov '09
#At lp:maria/5.2 based on revid:psergey@askmonty.org-20091104224158-nk2s2luvlqwa02bl
2732 Igor Babaev 2009-11-11 [merge]
Merge of the patch introducing virtual columns into maria-5.2
added:
mysql-test/extra/rpl_tests/rpl_mixing_engines.test
mysql-test/include/partition_date_range.inc
mysql-test/include/rpl_loaddata_charset.inc
mysql-test/r/disabled_partition.require
mysql-test/r/partition_disabled.result
mysql-test/r/table_elim_debug.result
mysql-test/std_data/loaddata_utf8.dat
mysql-test/std_data/parts/t1.frm
mysql-test/suite/rpl/r/rpl_create_if_not_exists.result
mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result
mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result
mysql-test/suite/rpl/t/rpl_create_if_not_exists.test
mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test
mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test
mysql-test/suite/vcol/
mysql-test/suite/vcol/inc/
mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
mysql-test/suite/vcol/inc/vcol_cleanup.inc
mysql-test/suite/vcol/inc/vcol_column_def_options.inc
mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc
mysql-test/suite/vcol/inc/vcol_handler.inc
mysql-test/suite/vcol/inc/vcol_init_vars.pre
mysql-test/suite/vcol/inc/vcol_ins_upd.inc
mysql-test/suite/vcol/inc/vcol_keys.inc
mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc
mysql-test/suite/vcol/inc/vcol_partition.inc
mysql-test/suite/vcol/inc/vcol_select.inc
mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc
mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc
mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc
mysql-test/suite/vcol/inc/vcol_view.inc
mysql-test/suite/vcol/r/
mysql-test/suite/vcol/r/rpl_vcol.result
mysql-test/suite/vcol/r/vcol_archive.result
mysql-test/suite/vcol/r/vcol_blackhole.result
mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result
mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result
mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result
mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result
mysql-test/suite/vcol/r/vcol_csv.result
mysql-test/suite/vcol/r/vcol_handler_innodb.result
mysql-test/suite/vcol/r/vcol_handler_myisam.result
mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result
mysql-test/suite/vcol/r/vcol_keys_innodb.result
mysql-test/suite/vcol/r/vcol_keys_myisam.result
mysql-test/suite/vcol/r/vcol_memory.result
mysql-test/suite/vcol/r/vcol_merge.result
mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result
mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result
mysql-test/suite/vcol/r/vcol_partition_innodb.result
mysql-test/suite/vcol/r/vcol_partition_myisam.result
mysql-test/suite/vcol/r/vcol_select_innodb.result
mysql-test/suite/vcol/r/vcol_select_myisam.result
mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result
mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result
mysql-test/suite/vcol/r/vcol_syntax.result
mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
mysql-test/suite/vcol/r/vcol_view_innodb.result
mysql-test/suite/vcol/r/vcol_view_myisam.result
mysql-test/suite/vcol/t/
mysql-test/suite/vcol/t/rpl_vcol.test
mysql-test/suite/vcol/t/vcol_archive.test
mysql-test/suite/vcol/t/vcol_blackhole.test
mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test
mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test
mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test
mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test
mysql-test/suite/vcol/t/vcol_csv.test
mysql-test/suite/vcol/t/vcol_handler_innodb.test
mysql-test/suite/vcol/t/vcol_handler_myisam.test
mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test
mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test
mysql-test/suite/vcol/t/vcol_keys_innodb.test
mysql-test/suite/vcol/t/vcol_keys_myisam.test
mysql-test/suite/vcol/t/vcol_memory.test
mysql-test/suite/vcol/t/vcol_merge.test
mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test
mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test
mysql-test/suite/vcol/t/vcol_partition_innodb.test
mysql-test/suite/vcol/t/vcol_partition_myisam.test
mysql-test/suite/vcol/t/vcol_select_innodb.test
mysql-test/suite/vcol/t/vcol_select_myisam.test
mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test
mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test
mysql-test/suite/vcol/t/vcol_syntax.test
mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test
mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test
mysql-test/suite/vcol/t/vcol_view_innodb.test
mysql-test/suite/vcol/t/vcol_view_myisam.test
mysql-test/t/partition_disabled-master.opt
mysql-test/t/partition_disabled.test
mysql-test/t/table_elim_debug.test
storage/federated/README
storage/federatedx/
storage/federatedx/AUTHORS
storage/federatedx/CMakeLists.txt
storage/federatedx/ChangeLog
storage/federatedx/FAQ
storage/federatedx/Makefile.am
storage/federatedx/README
storage/federatedx/README.windows
storage/federatedx/TODO
storage/federatedx/federatedx_io.cc
storage/federatedx/federatedx_io_mysql.cc
storage/federatedx/federatedx_io_null.cc
storage/federatedx/federatedx_probes.h
storage/federatedx/federatedx_txn.cc
storage/federatedx/ha_federatedx.cc
storage/federatedx/ha_federatedx.h
storage/federatedx/plug.in
renamed:
storage/federated/plug.in => storage/federated/plug.in.disabled
modified:
.bzrignore
BUILD/SETUP.sh
BUILD/check-cpu
client/mysql.cc
client/mysql_upgrade.c
client/mysqladmin.cc
client/mysqldump.c
client/mysqltest.cc
cmd-line-utils/readline/bind.c
cmd-line-utils/readline/histfile.c
cmd-line-utils/readline/undo.c
extra/libevent/event-internal.h
extra/yassl/taocrypt/src/twofish.cpp
include/my_global.h
include/mysql_com.h
libmysql/libmysql.c
libmysqld/Makefile.am
mysql-test/collections/default.experimental
mysql-test/include/commit.inc
mysql-test/lib/mtr_cases.pm
mysql-test/mysql-test-run.pl
mysql-test/r/analyse.result
mysql-test/r/auto_increment.result
mysql-test/r/commit_1innodb.result
mysql-test/r/group_min_max.result
mysql-test/r/handler_myisam.result
mysql-test/r/lock_multi_bug38499.result
mysql-test/r/lock_multi_bug38691.result
mysql-test/r/merge.result
mysql-test/r/mysqlbinlog_row_trans.result
mysql-test/r/not_partition.result
mysql-test/r/partition.result
mysql-test/r/partition_pruning.result
mysql-test/r/partition_range.result
mysql-test/r/subselect.result
mysql-test/r/type_newdecimal.result
mysql-test/r/view.result
mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result
mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
mysql-test/suite/federated/disabled.def
mysql-test/suite/federated/federated.result
mysql-test/suite/federated/federated.test
mysql-test/suite/federated/federated_archive.result
mysql-test/suite/federated/federated_bug_13118.result
mysql-test/suite/federated/federated_bug_25714.result
mysql-test/suite/federated/federated_cleanup.inc
mysql-test/suite/federated/federated_innodb.result
mysql-test/suite/federated/federated_server.result
mysql-test/suite/federated/federated_server.test
mysql-test/suite/federated/federated_transactions.result
mysql-test/suite/funcs_1/r/is_engines_federated.result
mysql-test/suite/pbxt/r/partition_range.result
mysql-test/suite/pbxt/r/subselect.result
mysql-test/suite/pbxt/t/subselect.test
mysql-test/suite/rpl/r/rpl_concurrency_error.result
mysql-test/suite/rpl/r/rpl_drop_if_exists.result
mysql-test/suite/rpl/r/rpl_drop_temp.result
mysql-test/suite/rpl/r/rpl_events.result
mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result
mysql-test/suite/rpl/r/rpl_loaddata_charset.result
mysql-test/suite/rpl/r/rpl_rewrt_db.result
mysql-test/suite/rpl/t/rpl_concurrency_error.test
mysql-test/suite/rpl/t/rpl_drop_temp.test
mysql-test/suite/rpl/t/rpl_events.test
mysql-test/suite/rpl/t/rpl_loaddata_charset.test
mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt
mysql-test/suite/rpl/t/rpl_rewrt_db.test
mysql-test/t/analyse.test
mysql-test/t/auto_increment.test
mysql-test/t/group_min_max.test
mysql-test/t/handler_myisam.test
mysql-test/t/lock_multi_bug38499.test
mysql-test/t/lock_multi_bug38691.test
mysql-test/t/merge.test
mysql-test/t/not_partition.test
mysql-test/t/partition.test
mysql-test/t/partition_pruning.test
mysql-test/t/subselect.test
mysql-test/t/type_newdecimal.test
mysql-test/t/view.test
mysql-test/valgrind.supp
mysys/array.c
mysys/mf_iocache.c
mysys/mf_pack.c
mysys/my_copy.c
mysys/my_getopt.c
mysys/my_redel.c
mysys/safemalloc.c
mysys/typelib.c
regex/regcomp.c
scripts/make_binary_distribution.sh
server-tools/instance-manager/mysql_connection.cc
sql-common/client.c
sql-common/my_time.c
sql/client_settings.h
sql/events.cc
sql/field.cc
sql/field.h
sql/filesort.cc
sql/ha_partition.cc
sql/ha_partition.h
sql/handler.h
sql/item.cc
sql/item.h
sql/item_cmpfunc.cc
sql/item_create.cc
sql/item_func.cc
sql/item_func.h
sql/item_row.h
sql/item_strfunc.h
sql/item_subselect.h
sql/item_sum.cc
sql/item_sum.h
sql/item_timefunc.cc
sql/item_timefunc.h
sql/item_xmlfunc.cc
sql/item_xmlfunc.h
sql/lex.h
sql/lock.cc
sql/log.cc
sql/log_event.cc
sql/my_decimal.h
sql/mysql_priv.h
sql/mysqld.cc
sql/opt_range.cc
sql/partition_info.h
sql/procedure.h
sql/records.cc
sql/share/errmsg.txt
sql/slave.cc
sql/sp_head.cc
sql/spatial.cc
sql/sql_base.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_db.cc
sql/sql_delete.cc
sql/sql_handler.cc
sql/sql_insert.cc
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_parse.cc
sql/sql_partition.cc
sql/sql_plugin.cc
sql/sql_profile.cc
sql/sql_select.cc
sql/sql_show.cc
sql/sql_table.cc
sql/sql_update.cc
sql/sql_view.cc
sql/sql_yacc.yy
sql/table.cc
sql/table.h
sql/unireg.cc
sql/unireg.h
storage/heap/hp_test2.c
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.h
storage/myisam/ft_boolean_search.c
storage/myisam/ha_myisam.cc
storage/myisam/ha_myisam.h
storage/myisam/mi_check.c
storage/myisam/mi_create.c
storage/myisam/mi_delete.c
storage/myisam/mi_dynrec.c
storage/myisam/mi_open.c
storage/myisam/mi_packrec.c
storage/myisam/mi_search.c
storage/myisam/mi_update.c
storage/myisam/sort.c
storage/myisammrg/ha_myisammrg.cc
storage/myisammrg/myrg_open.c
storage/myisammrg/myrg_rkey.c
storage/ndb/include/mgmapi/ndb_logevent.h
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
storage/pbxt/src/cache_xt.cc
storage/pbxt/src/discover_xt.cc
storage/xtradb/handler/ha_innodb.cc
storage/xtradb/handler/ha_innodb.h
storage/xtradb/include/buf0buf.ic
storage/xtradb/include/srv0srv.h
storage/xtradb/srv/srv0srv.c
strings/ctype-ucs2.c
strings/ctype-utf8.c
strings/decimal.c
support-files/mysql.spec.sh
tests/mysql_client_test.c
win/make_mariadb_win_dist
=== modified file '.bzrignore'
--- a/.bzrignore 2009-09-15 12:12:51 +0000
+++ b/.bzrignore 2009-11-06 17:22:32 +0000
@@ -1921,3 +1921,4 @@ sql/share/ukrainian
libmysqld/examples/mysqltest.cc
extra/libevent/event-config.h
libmysqld/opt_table_elimination.cc
+libmysqld/ha_federatedx.cc
=== modified file 'BUILD/SETUP.sh'
--- a/BUILD/SETUP.sh 2009-10-06 14:53:46 +0000
+++ b/BUILD/SETUP.sh 2009-10-29 00:04:56 +0000
@@ -146,6 +146,13 @@ then
debug_cflags="$debug_cflags $debug_extra_cflags"
fi
+static_link="--with-mysqld-ldflags=-all-static "
+static_link="$static_link --with-client-ldflags=-all-static"
+# we need local-infile in all binaries for rpl000001
+# if you need to disable local-infile in the client, write a build script
+# and unset local_infile_configs
+local_infile_configs="--enable-local-infile"
+
#
# Configuration options.
#
@@ -154,6 +161,8 @@ base_configs="$base_configs --with-extra
base_configs="$base_configs --enable-thread-safe-client "
base_configs="$base_configs --with-big-tables"
base_configs="$base_configs --with-plugin-maria --with-maria-tmp-tables --without-plugin-innodb_plugin"
+# Compile our client programs with static libraries to allow them to be moved
+base_configs="$base_configs --with-mysqld-ldflags=-static --with-client-ldflags=-static"
if test -d "$path/../cmd-line-utils/readline"
then
@@ -163,14 +172,6 @@ then
base_configs="$base_configs --with-libedit"
fi
-static_link="--with-mysqld-ldflags=-all-static "
-static_link="$static_link --with-client-ldflags=-all-static"
-# we need local-infile in all binaries for rpl000001
-# if you need to disable local-infile in the client, write a build script
-# and unset local_infile_configs
-local_infile_configs="--enable-local-infile"
-
-
max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache"
max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server --with-libevent"
=== modified file 'BUILD/check-cpu'
--- a/BUILD/check-cpu 2009-07-10 13:04:40 +0000
+++ b/BUILD/check-cpu 2009-09-01 13:39:13 +0000
@@ -70,6 +70,11 @@ check_cpu () {
Alpha*EV6*)
cpu_arg="ev6";
;;
+ #Core 2 Duo
+ *Intel*Core\(TM\)2*)
+ cpu_arg="nocona"
+ core2="yes"
+ ;;
# Intel ia32
*Intel*Core*|*X[eE][oO][nN]*)
# a Xeon is just another pentium4 ...
@@ -134,10 +139,6 @@ check_cpu () {
*i386*)
cpu_arg="i386"
;;
- #Core 2 Duo
- *Intel*Core\(TM\)2*)
- cpu_arg="nocona"
- ;;
# Intel ia64
*Itanium*)
cpu_arg="itanium"
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2009-10-26 11:35:42 +0000
+++ b/client/mysql.cc 2009-11-06 17:22:32 +0000
@@ -86,7 +86,7 @@ extern "C" {
#endif
#undef bcmp // Fix problem with new readline
-#if defined( __WIN__)
+#if defined(__WIN__)
#include <conio.h>
#elif !defined(__NETWARE__)
#include <readline/readline.h>
@@ -106,7 +106,7 @@ extern "C" {
#define cmp_database(cs,A,B) strcmp((A),(B))
#endif
-#if !defined( __WIN__) && !defined(__NETWARE__) && !defined(THREAD)
+#if !defined(__WIN__) && !defined(__NETWARE__) && !defined(THREAD)
#define USE_POPEN
#endif
@@ -1870,7 +1870,7 @@ static int read_and_execute(bool interac
if (opt_outfile && glob_buffer.is_empty())
fflush(OUTFILE);
-#if defined( __WIN__) || defined(__NETWARE__)
+#if defined(__WIN__) || defined(__NETWARE__)
tee_fputs(prompt, stdout);
#if defined(__NETWARE__)
line=fgets(linebuffer, sizeof(linebuffer)-1, stdin);
@@ -1881,7 +1881,7 @@ static int read_and_execute(bool interac
if (p != NULL)
*p = '\0';
}
-#else defined(__WIN__)
+#else
if (!tmpbuf.is_alloced())
tmpbuf.alloc(65535);
tmpbuf.length(0);
@@ -1907,7 +1907,7 @@ static int read_and_execute(bool interac
if (opt_outfile)
fputs(prompt, OUTFILE);
line= readline(prompt);
-#endif /* defined( __WIN__) || defined(__NETWARE__) */
+#endif /* defined(__WIN__) || defined(__NETWARE__) */
/*
When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS
@@ -1955,10 +1955,10 @@ static int read_and_execute(bool interac
}
}
-#if defined( __WIN__) || defined(__NETWARE__)
+#if defined(__WIN__) || defined(__NETWARE__)
buffer.free();
#endif
-#if defined( __WIN__)
+#if defined(__WIN__)
tmpbuf.free();
#endif
@@ -3835,6 +3835,7 @@ com_edit(String *buffer,char *line __att
char errmsg[100];
sprintf(errmsg, "Command '%.40s' failed", buff);
put_info(errmsg, INFO_ERROR, 0, NullS);
+ goto err;
}
if (!my_stat(filename,&stat_arg,MYF(MY_WME)))
@@ -4635,7 +4636,7 @@ void tee_putc(int c, FILE *file)
putc(c, OUTFILE);
}
-#if defined( __WIN__) || defined(__NETWARE__)
+#if defined(__WIN__) || defined(__NETWARE__)
#include <time.h>
#else
#include <sys/times.h>
@@ -4647,7 +4648,7 @@ void tee_putc(int c, FILE *file)
static ulong start_timer(void)
{
-#if defined( __WIN__) || defined(__NETWARE__)
+#if defined(__WIN__) || defined(__NETWARE__)
return clock();
#else
struct tms tms_tmp;
=== modified file 'client/mysql_upgrade.c'
--- a/client/mysql_upgrade.c 2009-10-26 11:35:42 +0000
+++ b/client/mysql_upgrade.c 2009-11-06 17:22:32 +0000
@@ -552,6 +552,7 @@ static int upgrade_already_done(void)
FILE *in;
char upgrade_info_file[FN_REFLEN]= {0};
char buf[sizeof(MYSQL_SERVER_VERSION)+1];
+ char *res;
if (get_upgrade_info_file_name(upgrade_info_file))
return 0; /* Could not get filename => not sure */
=== modified file 'client/mysqladmin.cc'
--- a/client/mysqladmin.cc 2009-10-28 14:56:07 +0000
+++ b/client/mysqladmin.cc 2009-11-12 04:31:28 +0000
@@ -22,6 +22,7 @@
#endif
#include <sys/stat.h>
#include <mysql.h>
+#include <sql_common.h>
#define ADMIN_VERSION "9.0"
#define MAX_MYSQL_VAR 512
@@ -359,6 +360,11 @@ int main(int argc,char *argv[])
if (sql_connect(&mysql, option_wait))
{
+ /*
+ We couldn't get an initial connection and will definitely exit.
+ The following just determines the exit-code we'll give.
+ */
+
unsigned int err= mysql_errno(&mysql);
if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
error= 1;
@@ -377,41 +383,79 @@ int main(int argc,char *argv[])
}
else
{
- while (!interrupted)
+ /*
+ --count=0 aborts right here. Otherwise iff --sleep=t ("interval")
+ is given a t!=0, we get an endless loop, or n iterations if --count=n
+ was given an n!=0. If --sleep wasn't given, we get one iteration.
+
+ To wit, --wait loops the connection-attempts, while --sleep loops
+ the command execution (endlessly if no --count is given).
+ */
+
+ while (!interrupted && (!opt_count_iterations || nr_iterations))
{
new_line = 0;
- if ((error=execute_commands(&mysql,argc,commands)))
+
+ if ((error= execute_commands(&mysql,argc,commands)))
{
+ /*
+ Unknown/malformed command always aborts and can't be --forced.
+ If the user got confused about the syntax, proceeding would be
+ dangerous ...
+ */
if (error > 0)
- break; /* Wrong command error */
- if (!option_force)
+ break;
+
+ /*
+ Command was well-formed, but failed on the server. Might succeed
+ on retry (if conditions on server change etc.), but needs --force
+ to retry.
+ */
+ if (!option_force)
+ break;
+ } /* if((error= ... */
+
+ if (interval) /* --sleep=interval given */
+ {
+ /*
+ If connection was dropped (unintentionally, or due to SHUTDOWN),
+ re-establish it if --wait ("retry-connect") was given and user
+ didn't signal for us to die. Otherwise, signal failure.
+ */
+
+ if (mysql.net.vio == 0)
{
if (option_wait && !interrupted)
{
- mysql_close(&mysql);
- if (!sql_connect(&mysql, option_wait))
- {
- sleep(1); /* Don't retry too rapidly */
- continue; /* Retry */
- }
+ sleep(1);
+ sql_connect(&mysql, option_wait);
+ /*
+ continue normally and decrease counters so that
+ "mysqladmin --count=1 --wait=1 shutdown"
+ cannot loop endlessly.
+ */
}
- error=1;
- break;
- }
- }
- if (interval)
- {
- if (opt_count_iterations && --nr_iterations == 0)
- break;
+ else
+ {
+ /*
+ connexion broke, and we have no order to re-establish it. fail.
+ */
+ if (!option_force)
+ error= 1;
+ break;
+ }
+ } /* lost connection */
+
sleep(interval);
if (new_line)
puts("");
}
else
- break;
- }
- mysql_close(&mysql);
- }
+ break; /* no --sleep, done looping */
+ } /* command-loop */
+ } /* got connection */
+
+ mysql_close(&mysql);
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
my_free(user,MYF(MY_ALLOW_ZERO_PTR));
#ifdef HAVE_SMEM
@@ -429,6 +473,17 @@ sig_handler endprog(int signal_number __
interrupted=1;
}
+/**
+ @brief connect to server, optionally waiting for same to come up
+
+ @param mysql connection struct
+ @param wait wait for server to come up?
+ (0: no, ~0: forever, n: cycles)
+
+ @return Operation result
+ @retval 0 success
+ @retval 1 failure
+*/
static my_bool sql_connect(MYSQL *mysql, uint wait)
{
@@ -437,7 +492,7 @@ static my_bool sql_connect(MYSQL *mysql,
for (;;)
{
if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port,
- unix_port, 0))
+ unix_port, CLIENT_REMEMBER_OPTIONS))
{
mysql->reconnect= 1;
if (info)
@@ -448,9 +503,9 @@ static my_bool sql_connect(MYSQL *mysql,
return 0;
}
- if (!wait)
+ if (!wait) // was or reached 0, fail
{
- if (!option_silent)
+ if (!option_silent) // print diagnostics
{
if (!host)
host= (char*) LOCAL_HOST;
@@ -474,11 +529,18 @@ static my_bool sql_connect(MYSQL *mysql,
}
return 1;
}
+
if (wait != (uint) ~0)
- wait--; /* One less retry */
+ wait--; /* count down, one less retry */
+
if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) &&
(mysql_errno(mysql) != CR_CONNECTION_ERROR))
{
+ /*
+ Error is worse than "server doesn't answer (yet?)";
+ fail even if we still have "wait-coins" unless --force
+ was also given.
+ */
fprintf(stderr,"Got error: %s\n", mysql_error(mysql));
if (!option_force)
return 1;
@@ -502,11 +564,18 @@ static my_bool sql_connect(MYSQL *mysql,
}
-/*
- Execute a command.
- Return 0 on ok
- -1 on retryable error
- 1 on fatal error
+/**
+ @brief Execute all commands
+
+ @details We try to execute all commands we were given, in the order
+ given, but return with non-zero as soon as we encounter trouble.
+ By that token, individual commands can be considered a conjunction
+ with boolean short-cut.
+
+ @return success?
+ @retval 0 Yes! ALL commands worked!
+ @retval 1 No, one failed and will never work (malformed): fatal error!
+ @retval -1 No, one failed on the server, may work next time!
*/
static int execute_commands(MYSQL *mysql,int argc, char **argv)
@@ -577,7 +646,6 @@ static int execute_commands(MYSQL *mysql
mysql_error(mysql));
return -1;
}
- mysql_close(mysql); /* Close connection to avoid error messages */
argc=1; /* force SHUTDOWN to be the last command */
if (got_pidfile)
{
@@ -1130,14 +1198,16 @@ static void usage(void)
static int drop_db(MYSQL *mysql, const char *db)
{
char name_buff[FN_REFLEN+20], buf[10];
+ char *input;
+
if (!option_force)
{
puts("Dropping the database is potentially a very bad thing to do.");
puts("Any data stored in the database will be destroyed.\n");
printf("Do you really want to drop the '%s' database [y/N] ",db);
fflush(stdout);
- if (fgets(buf,sizeof(buf)-1,stdin) == 0 ||
- (*buf != 'y') && (*buf != 'Y'))
+ input= fgets(buf, sizeof(buf)-1, stdin);
+ if (!input || ((*input != 'y') && (*input != 'Y')))
{
puts("\nOK, aborting database drop!");
return -1;
=== modified file 'client/mysqldump.c'
--- a/client/mysqldump.c 2009-09-07 20:50:10 +0000
+++ b/client/mysqldump.c 2009-10-15 21:38:29 +0000
@@ -5008,7 +5008,7 @@ int main(int argc, char **argv)
exit_code= get_options(&argc, &argv);
if (exit_code)
{
- free_resources(0);
+ free_resources();
exit(exit_code);
}
@@ -5016,14 +5016,14 @@ int main(int argc, char **argv)
{
if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
{
- free_resources(0);
+ free_resources();
exit(EX_MYSQLERR);
}
}
if (connect_to_db(current_host, current_user, opt_password))
{
- free_resources(0);
+ free_resources();
exit(EX_MYSQLERR);
}
if (!path)
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc 2009-10-09 08:09:24 +0000
+++ b/client/mysqltest.cc 2009-10-15 21:52:31 +0000
@@ -443,10 +443,12 @@ DYNAMIC_STRING ds_res;
char builtin_echo[FN_REFLEN];
+static void cleanup_and_exit(int exit_code) __attribute__((noreturn));
+
void die(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
+ ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
void abort_not_supported_test(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
+ ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
void verbose_msg(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
void log_msg(const char *fmt, ...)
@@ -3737,10 +3739,9 @@ void do_wait_for_slave_to_stop(struct st
MYSQL* mysql = &cur_con->mysql;
for (;;)
{
- MYSQL_RES *res;
+ MYSQL_RES *UNINIT_VAR(res);
MYSQL_ROW row;
int done;
- LINT_INIT(res);
if (mysql_query(mysql,"show status like 'Slave_running'") ||
!(res=mysql_store_result(mysql)))
@@ -5275,13 +5276,12 @@ my_bool end_of_query(int c)
int read_line(char *buf, int size)
{
- char c, last_quote;
+ char c, UNINIT_VAR(last_quote);
char *p= buf, *buf_end= buf + size - 1;
int skip_char= 0;
enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
R_COMMENT, R_LINE_START} state= R_LINE_START;
DBUG_ENTER("read_line");
- LINT_INIT(last_quote);
start_lineno= cur_file->lineno;
DBUG_PRINT("info", ("Starting to read at lineno: %d", start_lineno));
@@ -6530,8 +6530,7 @@ void run_query_normal(struct st_connecti
if (!disable_result_log)
{
- ulonglong affected_rows; /* Ok to be undef if 'disable_info' is set */
- LINT_INIT(affected_rows);
+ ulonglong UNINIT_VAR(affected_rows); /* Ok to be undef if 'disable_info' is set */
if (res)
{
=== modified file 'cmd-line-utils/readline/bind.c'
--- a/cmd-line-utils/readline/bind.c 2009-09-07 20:50:10 +0000
+++ b/cmd-line-utils/readline/bind.c 2009-10-15 21:38:29 +0000
@@ -339,9 +339,7 @@ rl_generic_bind (type, keyseq, data, map
char *keys;
int keys_len;
register int i;
- KEYMAP_ENTRY k;
-
- k.function = 0;
+ KEYMAP_ENTRY k= { 0, NULL };
/* If no keys to bind to, exit right away. */
if (keyseq == 0 || *keyseq == 0)
@@ -776,7 +774,7 @@ _rl_read_file (filename, sizep)
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
-if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
+ if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
file_size + 1 < file_size)
{
if (file >= 0)
=== modified file 'cmd-line-utils/readline/histfile.c'
--- a/cmd-line-utils/readline/histfile.c 2009-06-29 14:00:47 +0000
+++ b/cmd-line-utils/readline/histfile.c 2009-08-28 16:21:54 +0000
@@ -186,7 +186,7 @@ read_history_range (filename, from, to)
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
-if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
+ if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
file_size + 1 < file_size)
{
errno = overflow_errno;
@@ -311,6 +311,7 @@ history_truncate_file (fname, lines)
int file, chars_read, rv;
struct stat finfo;
size_t file_size;
+ size_t bytes_written;
buffer = (char *)NULL;
filename = history_filename (fname);
@@ -340,7 +341,7 @@ history_truncate_file (fname, lines)
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
-if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
+ if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
file_size + 1 < file_size)
{
close (file);
@@ -400,7 +401,7 @@ if ((sizeof(off_t) > sizeof(size_t) && f
truncate to. */
if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
{
- write (file, bp, chars_read - (bp - buffer));
+ bytes_written= write (file, bp, chars_read - (bp - buffer));
#if defined (__BEOS__)
/* BeOS ignores O_TRUNC. */
=== modified file 'cmd-line-utils/readline/undo.c'
--- a/cmd-line-utils/readline/undo.c 2009-06-29 14:00:47 +0000
+++ b/cmd-line-utils/readline/undo.c 2009-08-28 16:21:54 +0000
@@ -137,7 +137,8 @@ UNDO_LIST *
_rl_copy_undo_list (head)
UNDO_LIST *head;
{
- UNDO_LIST *list, *new, *roving, *c;
+ UNDO_LIST *list, *new, *c;
+ UNDO_LIST *roving= NULL;
list = head;
new = 0;
=== modified file 'extra/libevent/event-internal.h'
--- a/extra/libevent/event-internal.h 2009-03-12 22:27:35 +0000
+++ b/extra/libevent/event-internal.h 2009-10-31 05:29:16 +0000
@@ -70,6 +70,11 @@ struct event_base {
/* Internal use only: Functions that might be missing from <sys/queue.h> */
#ifndef HAVE_TAILQFOREACH
+/* These following macros are copied from BSD sys/queue.h
+ Copyright (c) 1991, 1993, The Regents of the University of California.
+ All rights reserved.
+*/
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
=== modified file 'extra/yassl/taocrypt/src/twofish.cpp'
--- a/extra/yassl/taocrypt/src/twofish.cpp 2007-01-29 15:54:40 +0000
+++ b/extra/yassl/taocrypt/src/twofish.cpp 2009-10-30 18:50:56 +0000
@@ -55,6 +55,7 @@ void Twofish::Process(byte* out, const b
in += BLOCK_SIZE;
}
else if (mode_ == CBC)
+ {
if (dir_ == ENCRYPTION)
while (blocks--) {
r_[0] ^= *(word32*)in;
@@ -82,6 +83,7 @@ void Twofish::Process(byte* out, const b
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
+ }
}
#endif // DO_TWOFISH_ASM
=== modified file 'include/my_global.h'
--- a/include/my_global.h 2009-09-16 19:05:03 +0000
+++ b/include/my_global.h 2009-10-15 21:38:29 +0000
@@ -578,6 +578,25 @@ int __void__;
#define IF_VALGRIND(A,B) (B)
#endif
+/*
+ Suppress uninitialized variable warning without generating code.
+
+ The _cplusplus is a temporary workaround for C++ code pending a fix
+ for a g++ bug (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34772)
+*/
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(__cplusplus) || \
+ !defined(__GNUC__)
+#define UNINIT_VAR(x) x= 0
+#else
+#define UNINIT_VAR(x) x= x
+#endif
+
+/* Define some useful general macros */
+#if !defined(max)
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
#if !defined(HAVE_UINT)
#undef HAVE_UINT
#define HAVE_UINT
=== modified file 'include/mysql_com.h'
--- a/include/mysql_com.h 2009-10-19 17:14:48 +0000
+++ b/include/mysql_com.h 2009-11-12 04:31:28 +0000
@@ -68,7 +68,8 @@ enum enum_server_command
COM_END
};
-
+/* sql type stored in .frm files for virtual fields */
+#define MYSQL_TYPE_VIRTUAL 245
/*
Length of random string sent by server on handshake; this is also length of
obfuscated password, recieved from client
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2009-10-23 16:48:54 +0000
+++ b/libmysql/libmysql.c 2009-11-06 17:22:32 +0000
@@ -1648,8 +1648,7 @@ myodbc_remove_escape(MYSQL *mysql,char *
char *to;
#ifdef USE_MB
my_bool use_mb_flag=use_mb(mysql->charset);
- char *end;
- LINT_INIT(end);
+ char *UNINIT_VAR(end);
if (use_mb_flag)
for (end=name; *end ; end++) ;
#endif
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-09-15 10:46:35 +0000
+++ b/libmysqld/Makefile.am 2009-10-30 18:50:56 +0000
@@ -124,7 +124,7 @@ handler.o: handler.cc
# found to append fileslists that collected by configure
# to the sources list
-ha_federated.o:ha_federated.cc
+ha_federatedx.o:ha_federatedx.cc
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
ha_heap.o:ha_heap.cc
=== modified file 'mysql-test/collections/default.experimental'
--- a/mysql-test/collections/default.experimental 2009-07-08 07:31:49 +0000
+++ b/mysql-test/collections/default.experimental 2009-08-13 20:45:01 +0000
@@ -2,12 +2,5 @@ funcs_1.charset_collation_1
binlog.binlog_tmp_table # Bug#45578: Test binlog_tmp_table fails ramdonly on PB2: Unknown table 't2'
main.ctype_gbk_binlog # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists
rpl.rpl_row_create_table # Bug#45576: rpl_row_create_table fails on PB2
-rpl.rpl_extraColmaster_myisam # Bug#46013: rpl_extraColmaster_myisam fails on pb2
-rpl.rpl_stm_reset_slave # Bug#46014: rpl_stm_reset_slave crashes the server sporadically in pb2
-rpl.rpl_extraCol_myisam # Bug#40796
-rpl.rpl_extraColmaster_innodb # Bug#40796
-rpl.rpl_extraCol_innodb # Bug#40796
rpl_ndb.rpl_ndb_log # Bug#38998
rpl.rpl_innodb_bug28430 # Bug#46029
-rpl.rpl_row_basic_3innodb # Bug#45243
-rpl.rpl_truncate_3innodb # Bug#46030
=== added file 'mysql-test/extra/rpl_tests/rpl_mixing_engines.test'
--- a/mysql-test/extra/rpl_tests/rpl_mixing_engines.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_mixing_engines.test 2009-08-27 12:46:29 +0000
@@ -0,0 +1,710 @@
+###################################################################################
+# This test checks if transactions that mixes transactional and non-transactional
+# tables are correctly handled in statement mode. In an nutshell, we have what
+# follows:
+#
+# 1) "B T T C" generates in binlog the "B T T C" entries.
+#
+# 2) "B T T R" generates in binlog an "empty" entry.
+#
+# 3) "B T N C" generates in binlog the "B T N C" entries.
+#
+# 4) "B T N R" generates in binlog the "B T N R" entries.
+#
+# 5) "T" generates in binlog the "B T C" entry.
+#
+# 6) "N" generates in binlog the "N" entry.
+#
+# 7) "M" generates in binglog the "B M C" entries.
+#
+# 8) "B N N T C" generates in binglog the "N N B T C" entries.
+#
+# 9) "B N N T R" generates in binlog the "N N B T R" entries.
+#
+# 10) "B N N C" generates in binglog the "N N" entries.
+#
+# 11) "B N N R" generates in binlog the "N N" entries.
+#
+# 12) "B M T C" generates in the binlog the "B M T C" entries.
+#
+# 13) "B M T R" generates in the binlog the "B M T R" entries.
+###################################################################################
+
+--echo ###################################################################################
+--echo # CONFIGURATION
+--echo ###################################################################################
+connection master;
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+SET SQL_LOG_BIN=1;
+
+connection slave;
+
+SET SQL_LOG_BIN=0;
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+SET SQL_LOG_BIN=1;
+
+connection master;
+
+DELIMITER |;
+
+CREATE FUNCTION f1 () RETURNS VARCHAR(64)
+BEGIN
+ RETURN "Testing...";
+END|
+
+CREATE FUNCTION f2 () RETURNS VARCHAR(64)
+BEGIN
+ RETURN f1();
+END|
+
+CREATE PROCEDURE pc_i_tt_3 (IN x INT, IN y VARCHAR(64))
+BEGIN
+ INSERT INTO tt_3 VALUES (y,x,x);
+END|
+
+CREATE TRIGGER tr_i_tt_3_to_nt_3 BEFORE INSERT ON tt_3 FOR EACH ROW
+BEGIN
+ INSERT INTO nt_3 VALUES (NEW.a, NEW.b, NEW.c);
+END|
+
+CREATE TRIGGER tr_i_nt_4_to_tt_4 BEFORE INSERT ON nt_4 FOR EACH ROW
+BEGIN
+ INSERT INTO tt_4 VALUES (NEW.a, NEW.b, NEW.c);
+END|
+
+DELIMITER ;|
+
+--echo ###################################################################################
+--echo # MIXING TRANSACTIONAL and NON-TRANSACTIONAL TABLES
+--echo ###################################################################################
+connection master;
+
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #1) "B T T C" generates in binlog the "B T T C" entries.
+--echo #
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 4", 4, "new text 4");
+INSERT INTO tt_2 VALUES ("new text 4", 4, "new text 4");
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #1.e) "B T T C" with error in T generates in binlog the "B T T C" entries.
+--echo #
+INSERT INTO tt_1 VALUES ("new text -2", -2, "new text -2");
+BEGIN;
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -2", -2, "new text -2");
+INSERT INTO tt_2 VALUES ("new text -3", -3, "new text -3");
+COMMIT;
+
+BEGIN;
+INSERT INTO tt_2 VALUES ("new text -5", -5, "new text -5");
+--error ER_DUP_ENTRY
+INSERT INTO tt_2 VALUES ("new text -4", -4, "new text -4"), ("new text -5", -5, "new text -5");
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #2) "B T T R" generates in binlog an "empty" entry.
+--echo #
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 5", 5, "new text 5");
+INSERT INTO tt_2 VALUES ("new text 5", 5, "new text 5");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #2.e) "B T T R" with error in T generates in binlog an "empty" entry.
+--echo #
+INSERT INTO tt_1 VALUES ("new text -7", -7, "new text -7");
+BEGIN;
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES ("new text -6", -6, "new text -6"), ("new text -7", -7, "new text -7");
+INSERT INTO tt_2 VALUES ("new text -8", -8, "new text -8");
+ROLLBACK;
+
+BEGIN;
+INSERT INTO tt_2 VALUES ("new text -10", -10, "new text -10");
+--error ER_DUP_ENTRY
+INSERT INTO tt_2 VALUES ("new text -9", -9, "new text -9"), ("new text -10", -10, "new text -10");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #3) "B T N C" generates in binlog the "B T N C" entries.
+--echo #
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 6", 6, "new text 6");
+INSERT INTO nt_1 VALUES ("new text 6", 6, "new text 6");
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #3.e) "B T N C" with error in either T or N generates in binlog the "B T N C" entries.
+--echo #
+INSERT INTO tt_1 VALUES ("new text -12", -12, "new text -12");
+BEGIN;
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES ("new text -11", -11, "new text -11"), ("new text -12", -12, "new text -12");
+INSERT INTO nt_1 VALUES ("new text -13", -13, "new text -13");
+COMMIT;
+
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -14", -14, "new text -14");
+INSERT INTO nt_1 VALUES ("new text -16", -16, "new text -16");
+--error ER_DUP_ENTRY
+INSERT INTO nt_1 VALUES ("new text -15", -15, "new text -15"), ("new text -16", -16, "new text -16");
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #4) "B T N R" generates in binlog the "B T N R" entries.
+--echo #
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 7", 7, "new text 7");
+INSERT INTO nt_1 VALUES ("new text 7", 7, "new text 7");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #4.e) "B T N R" with error in either T or N generates in binlog the "B T N R" entries.
+--echo #
+INSERT INTO tt_1 VALUES ("new text -17", -17, "new text -17");
+BEGIN;
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES ("new text -16", -16, "new text -16"), ("new text -17", -17, "new text -17");
+INSERT INTO nt_1 VALUES ("new text -18", -18, "new text -18");
+ROLLBACK;
+
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -19", -19, "new text -19");
+INSERT INTO nt_1 VALUES ("new text -21", -21, "new text -21");
+--error ER_DUP_ENTRY
+INSERT INTO nt_1 VALUES ("new text -20", -20, "new text -20"), ("new text -21", -21, "new text -21");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #5) "T" generates in binlog the "B T C" entry.
+--echo #
+INSERT INTO tt_1 VALUES ("new text 8", 8, "new text 8");
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #5.e) "T" with error in T generates in binlog an "empty" entry.
+--echo #
+INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1");
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -22", -22, "new text -22");
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES ("new text -23", -23, "new text -23"), ("new text -1", -1, "new text -1");
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #6) "N" generates in binlog the "N" entry.
+--echo #
+INSERT INTO nt_1 VALUES ("new text 9", 9, "new text 9");
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #6.e) "N" with error in N generates in binlog an empty entry if the error
+--echo # happens in the first tuple. Otherwise, generates the "N" entry and
+--echo # the error is appended.
+--echo #
+INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1");
+--error ER_DUP_ENTRY
+INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1");
+--error ER_DUP_ENTRY
+INSERT INTO nt_1 VALUES ("new text -24", -24, "new text -24"), ("new text -1", -1, "new text -1");
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #7) "M" generates in binglog the "B M C" entries.
+--echo #
+
+DELETE FROM nt_1;
+
+INSERT INTO nt_1 SELECT * FROM tt_1;
+
+DELETE FROM tt_1;
+
+INSERT INTO tt_1 SELECT * FROM nt_1;
+
+INSERT INTO tt_3 VALUES ("new text 000", 000, '');
+
+INSERT INTO tt_3 VALUES("new text 100", 100, f1());
+
+INSERT INTO nt_4 VALUES("new text 100", 100, f1());
+
+INSERT INTO tt_3 VALUES("new text 200", 200, f2());
+
+INSERT INTO nt_4 VALUES ("new text 300", 300, '');
+
+INSERT INTO nt_4 VALUES ("new text 400", 400, f1());
+
+INSERT INTO nt_4 VALUES ("new text 500", 500, f2());
+
+CALL pc_i_tt_3(600, "Testing...");
+
+UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 1", nt_4.a= "new text 1", tt_3.a= "new text 1", tt_4.a= "new text 1" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+
+UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 2", tt_4.a= "new text 2", nt_3.a= "new text 2", nt_4.a = "new text 2" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 3", nt_3.a= "new text 3", nt_4.a= "new text 3", tt_4.a = "new text 3" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 4", nt_3.a= "new text 4", nt_4.a= "new text 4", tt_4.a = "new text 4" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #7.e) "M" with error in M generates in binglog the "B M R" entries.
+--echo #
+
+INSERT INTO nt_3 VALUES ("new text -26", -26, '');
+SELECT * FROM tt_3;
+--error ER_DUP_ENTRY
+INSERT INTO tt_3 VALUES ("new text -25", -25, ''), ("new text -26", -26, '');
+SELECT * FROM tt_3;
+
+INSERT INTO tt_4 VALUES ("new text -26", -26, '');
+SELECT * FROM nt_4;
+--error ER_DUP_ENTRY
+INSERT INTO nt_4 VALUES ("new text -25", -25, ''), ("new text -26", -26, '');
+SELECT * FROM nt_4;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #8) "B N N T C" generates in binglog the "N N B T C" entries.
+--echo #
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 10", 10, "new text 10");
+INSERT INTO nt_2 VALUES ("new text 10", 10, "new text 10");
+INSERT INTO tt_1 VALUES ("new text 10", 10, "new text 10");
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+--echo #
+--echo #8.e) "B N N T R" See 6.e and 9.e.
+--echo #
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #9) "B N N T R" generates in binlog the "N N B T R" entries.
+--echo #
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 11", 11, "new text 11");
+INSERT INTO nt_2 VALUES ("new text 11", 11, "new text 11");
+INSERT INTO tt_1 VALUES ("new text 11", 11, "new text 11");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #9.e) "B N N T R" with error in N generates in binlog the "N N B T R" entries.
+--echo #
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text -25", -25, "new text -25");
+INSERT INTO nt_2 VALUES ("new text -25", -25, "new text -25");
+--error ER_DUP_ENTRY
+INSERT INTO nt_2 VALUES ("new text -26", -26, "new text -26"), ("new text -25", -25, "new text -25");
+INSERT INTO tt_1 VALUES ("new text -27", -27, "new text -27");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #10) "B N N C" generates in binglog the "N N" entries.
+--echo #
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 12", 12, "new text 12");
+INSERT INTO nt_2 VALUES ("new text 12", 12, "new text 12");
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+--echo #
+--echo #10.e) "B N N C" See 6.e and 9.e.
+--echo #
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #11) "B N N R" generates in binlog the "N N" entries.
+--echo #
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 13", 13, "new text 13");
+INSERT INTO nt_2 VALUES ("new text 13", 13, "new text 13");
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+--echo #
+--echo #11.e) "B N N R" See 6.e and 9.e.
+--echo #
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #12) "B M T C" generates in the binlog the "B M T C" entries.
+--echo #
+DELETE FROM nt_1;
+BEGIN;
+INSERT INTO nt_1 SELECT * FROM tt_1;
+INSERT INTO tt_2 VALUES ("new text 14", 14, "new text 14");
+COMMIT;
+
+DELETE FROM tt_1;
+BEGIN;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+INSERT INTO tt_2 VALUES ("new text 15", 15, "new text 15");
+COMMIT;
+
+BEGIN;
+INSERT INTO tt_3 VALUES ("new text 700", 700, '');
+INSERT INTO tt_1 VALUES ("new text 800", 800, '');
+COMMIT;
+
+BEGIN;
+INSERT INTO tt_3 VALUES("new text 900", 900, f1());
+INSERT INTO tt_1 VALUES ("new text 1000", 1000, '');
+COMMIT;
+
+BEGIN;
+INSERT INTO tt_3 VALUES(1100, 1100, f2());
+INSERT INTO tt_1 VALUES ("new text 1200", 1200, '');
+COMMIT;
+
+BEGIN;
+INSERT INTO nt_4 VALUES ("new text 1300", 1300, '');
+INSERT INTO tt_1 VALUES ("new text 1400", 1400, '');
+COMMIT;
+
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 1500", 1500, f1());
+INSERT INTO tt_1 VALUES ("new text 1600", 1600, '');
+COMMIT;
+
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 1700", 1700, f2());
+INSERT INTO tt_1 VALUES ("new text 1800", 1800, '');
+COMMIT;
+
+BEGIN;
+CALL pc_i_tt_3(1900, "Testing...");
+INSERT INTO tt_1 VALUES ("new text 2000", 2000, '');
+COMMIT;
+
+BEGIN;
+UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 5", nt_4.a= "new text 5", tt_3.a= "new text 5", tt_4.a= "new text 5" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2100", 2100, '');
+COMMIT;
+
+BEGIN;
+UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 6", tt_4.a= "new text 6", nt_3.a= "new text 6", nt_4.a = "new text 6" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2200", 2200, '');
+COMMIT;
+
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 7", nt_3.a= "new text 7", nt_4.a= "new text 7", tt_4.a = "new text 7" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2300", 2300, '');
+COMMIT;
+
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 8", nt_3.a= "new text 8", nt_4.a= "new text 8", tt_4.a = "new text 8" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2400", 2400, '');
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #12.e) "B M T C" with error in M generates in the binlog the "B M T C" entries.
+--echo #
+
+--echo # There is a bug in the slave that needs to be fixed before enabling
+--echo # this part of the test. A bug report will be filed referencing this
+--echo # test case.
+
+BEGIN;
+INSERT INTO nt_3 VALUES ("new text -28", -28, '');
+--error ER_DUP_ENTRY
+INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, '');
+INSERT INTO tt_1 VALUES ("new text -27", -27, '');
+COMMIT;
+
+BEGIN;
+INSERT INTO tt_4 VALUES ("new text -28", -28, '');
+--error ER_DUP_ENTRY
+INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, '');
+INSERT INTO tt_1 VALUES ("new text -28", -28, '');
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #13) "B M T R" generates in the binlog the "B M T R" entries
+--echo #
+
+DELETE FROM nt_1;
+BEGIN;
+INSERT INTO nt_1 SELECT * FROM tt_1;
+INSERT INTO tt_2 VALUES ("new text 17", 17, "new text 17");
+ROLLBACK;
+
+DELETE FROM tt_1;
+BEGIN;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+INSERT INTO tt_2 VALUES ("new text 18", 18, "new text 18");
+ROLLBACK;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+
+BEGIN;
+INSERT INTO tt_3 VALUES ("new text 2500", 2500, '');
+INSERT INTO tt_1 VALUES ("new text 2600", 2600, '');
+ROLLBACK;
+
+BEGIN;
+INSERT INTO tt_3 VALUES("new text 2700", 2700, f1());
+INSERT INTO tt_1 VALUES ("new text 2800", 2800, '');
+ROLLBACK;
+
+BEGIN;
+INSERT INTO tt_3 VALUES(2900, 2900, f2());
+INSERT INTO tt_1 VALUES ("new text 3000", 3000, '');
+ROLLBACK;
+
+BEGIN;
+INSERT INTO nt_4 VALUES ("new text 3100", 3100, '');
+INSERT INTO tt_1 VALUES ("new text 3200", 3200, '');
+ROLLBACK;
+
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 3300", 3300, f1());
+INSERT INTO tt_1 VALUES ("new text 3400", 3400, '');
+ROLLBACK;
+
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 3500", 3500, f2());
+INSERT INTO tt_1 VALUES ("new text 3600", 3600, '');
+ROLLBACK;
+
+BEGIN;
+CALL pc_i_tt_3(3700, "Testing...");
+INSERT INTO tt_1 VALUES ("new text 3700", 3700, '');
+ROLLBACK;
+
+BEGIN;
+UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 9", nt_4.a= "new text 9", tt_3.a= "new text 9", tt_4.a= "new text 9" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 3800", 3800, '');
+ROLLBACK;
+
+BEGIN;
+UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 10", tt_4.a= "new text 10", nt_3.a= "new text 10", nt_4.a = "new text 10" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 3900", 3900, '');
+ROLLBACK;
+
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 11", nt_3.a= "new text 11", nt_4.a= "new text 11", tt_4.a = "new text 11" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 4000", 4000, '');
+ROLLBACK;
+
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 12", nt_3.a= "new text 12", nt_4.a= "new text 12", tt_4.a = "new text 12" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 4100", 4100, '');
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+--echo
+--echo
+--echo
+--echo
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+--echo #
+--echo #13.e) "B M T R" with error in M generates in the binlog the "B M T R" entries.
+--echo #
+
+BEGIN;
+INSERT INTO nt_3 VALUES ("new text -30", -30, '');
+--error ER_DUP_ENTRY
+INSERT INTO tt_3 VALUES ("new text -29", -29, ''), ("new text -30", -30, '');
+INSERT INTO tt_1 VALUES ("new text -30", -30, '');
+ROLLBACK;
+
+BEGIN;
+INSERT INTO tt_4 VALUES ("new text -30", -30, '');
+--error ER_DUP_ENTRY
+INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, '');
+INSERT INTO tt_1 VALUES ("new text -31", -31, '');
+ROLLBACK;
+
+--source include/show_binlog_events.inc
+
+connection master;
+sync_slave_with_master;
+
+--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-master.sql
+--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-slave.sql
+--diff_files $MYSQLTEST_VARDIR/tmp/test-master.sql $MYSQLTEST_VARDIR/tmp/test-slave.sql
+
+--echo ###################################################################################
+--echo # CLEAN
+--echo ###################################################################################
+
+connection master;
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE tt_3;
+DROP TABLE tt_4;
+DROP TABLE nt_1;
+DROP TABLE nt_2;
+DROP TABLE nt_3;
+DROP TABLE nt_4;
+DROP PROCEDURE pc_i_tt_3;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+
+sync_slave_with_master;
=== modified file 'mysql-test/include/commit.inc'
--- a/mysql-test/include/commit.inc 2009-06-19 11:27:24 +0000
+++ b/mysql-test/include/commit.inc 2009-08-26 23:13:03 +0000
@@ -725,9 +725,9 @@ call p_verify_status_increment(4, 4, 4,
alter table t3 add column (b int);
call p_verify_status_increment(2, 0, 2, 0);
alter table t3 rename t4;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 2, 2);
rename table t4 to t3;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 2, 2);
truncate table t3;
call p_verify_status_increment(4, 4, 4, 4);
create view v1 as select * from t2;
=== added file 'mysql-test/include/partition_date_range.inc'
--- a/mysql-test/include/partition_date_range.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/partition_date_range.inc 2009-09-01 12:53:27 +0000
@@ -0,0 +1,69 @@
+# Created for verifying bug#20577.
+# expects TABLE t1 (... , a DATE, ...)
+
+--sorted_result
+SELECT * FROM t1 WHERE a < '1001-01-01';
+--sorted_result
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+--sorted_result
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+--sorted_result
+SELECT * FROM t1 WHERE a > '1001-01-01';
+--sorted_result
+SELECT * FROM t1 WHERE a = '1001-01-01';
+--sorted_result
+SELECT * FROM t1 WHERE a < '1001-00-00';
+--sorted_result
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+--sorted_result
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+--sorted_result
+SELECT * FROM t1 WHERE a > '1001-00-00';
+--sorted_result
+SELECT * FROM t1 WHERE a = '1001-00-00';
+--echo # Disabling warnings for the invalid date
+--disable_warnings
+--sorted_result
+SELECT * FROM t1 WHERE a < '1999-02-31';
+--sorted_result
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+--sorted_result
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+--sorted_result
+SELECT * FROM t1 WHERE a > '1999-02-31';
+--sorted_result
+SELECT * FROM t1 WHERE a = '1999-02-31';
+--enable_warnings
+--sorted_result
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+--sorted_result
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+--sorted_result
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+--sorted_result
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+if ($explain_partitions)
+{
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+--echo # Disabling warnings for the invalid date
+--disable_warnings
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+--enable_warnings
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+}
=== added file 'mysql-test/include/rpl_loaddata_charset.inc'
--- a/mysql-test/include/rpl_loaddata_charset.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/rpl_loaddata_charset.inc 2009-08-12 05:31:56 +0000
@@ -0,0 +1,35 @@
+connection master;
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+CREATE DATABASE mysqltest CHARSET UTF8;
+USE mysqltest;
+CREATE TABLE t (cl varchar(100)) CHARSET UTF8;
+
+if (!$LOAD_LOCAL)
+{
+ LOAD DATA INFILE '../../std_data/loaddata_utf8.dat' INTO TABLE t
+ FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
+}
+if ($LOAD_LOCAL)
+{
+ LOAD DATA LOCAL INFILE './std_data/loaddata_utf8.dat' INTO TABLE t
+ FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
+}
+
+save_master_pos;
+echo ----------content on master----------;
+SELECT hex(cl) FROM t;
+
+connection slave;
+sync_with_master;
+echo ----------content on slave----------;
+USE mysqltest;
+SELECT hex(cl) FROM t;
+
+connection master;
+DROP DATABASE mysqltest;
+save_master_pos;
+connection slave;
+sync_with_master;
=== modified file 'mysql-test/lib/mtr_cases.pm'
--- a/mysql-test/lib/mtr_cases.pm 2009-10-14 08:09:56 +0000
+++ b/mysql-test/lib/mtr_cases.pm 2009-11-06 17:24:38 +0000
@@ -249,6 +249,10 @@ sub collect_one_suite($)
$suitedir= my_find_dir($::basedir,
["mysql-test/suite",
"mysql-test",
+ "share/mysql-test/suite",
+ "share/mysql-test",
+ "share/mysql/mysql-test/suite",
+ "share/mysql/mysql-test",
# Look in storage engine specific suite dirs
"storage/*/mysql-test-suites"
],
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2009-10-26 11:35:42 +0000
+++ b/mysql-test/mysql-test-run.pl 2009-11-06 17:24:38 +0000
@@ -127,7 +127,6 @@ my $path_config_file; # The ge
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts";
-my $opt_suites;
our $opt_usage;
our $opt_list_options;
@@ -1001,6 +1000,12 @@ sub command_line_setup {
{
$basedir= dirname($basedir);
}
+ # For .deb, it's like RPM, but installed in /usr/share/mysql/mysql-test.
+ # So move up one more directory level yet.
+ if ( ! $source_dist and ! -d "$basedir/bin" )
+ {
+ $basedir= dirname($basedir);
+ }
# Look for the client binaries directory
if ($path_client_bindir)
=== modified file 'mysql-test/r/analyse.result'
--- a/mysql-test/r/analyse.result 2007-05-30 16:25:16 +0000
+++ b/mysql-test/r/analyse.result 2009-08-27 10:59:25 +0000
@@ -28,9 +28,7 @@ test.t1.bool N Y 1 1 0 0 1.0000 NULL ENU
test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
drop table t1,t2;
EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
-id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <derived2> system NULL NULL NULL NULL 1
-2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
create table t1 (a int not null);
create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
@@ -153,4 +151,9 @@ select f3 from t1 procedure analyse(1, 1
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.f3 5.99999 9.55555 7 7 0 0 7.77777 1.77778 FLOAT(6,5) NOT NULL
drop table t1;
+CREATE TABLE t1(a INT,b INT,c INT,d INT,e INT,f INT,g INT,h INT,i INT,j INT,k INT);
+INSERT INTO t1 VALUES ();
+SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE();
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
+DROP TABLE t1;
End of 4.1 tests
=== modified file 'mysql-test/r/auto_increment.result'
--- a/mysql-test/r/auto_increment.result 2009-02-05 09:49:32 +0000
+++ b/mysql-test/r/auto_increment.result 2009-08-20 12:30:59 +0000
@@ -462,3 +462,17 @@ select last_insert_id();
last_insert_id()
3
drop table t1;
+#
+# Bug#46616: Assertion `!table->auto_increment_field_not_null' on view
+# manipulations
+#
+CREATE TABLE t1 ( a INT );
+INSERT INTO t1 VALUES (1), (1);
+CREATE TABLE t2 ( a INT AUTO_INCREMENT KEY );
+CREATE TABLE IF NOT EXISTS t2 AS SELECT a FROM t1;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+UPDATE t2 SET a = 2;
+SELECT a FROM t2;
+a
+2
+DROP TABLE t1, t2;
=== modified file 'mysql-test/r/commit_1innodb.result'
--- a/mysql-test/r/commit_1innodb.result 2009-06-19 11:27:24 +0000
+++ b/mysql-test/r/commit_1innodb.result 2009-08-26 23:13:03 +0000
@@ -841,17 +841,17 @@ call p_verify_status_increment(2, 0, 2,
SUCCESS
alter table t3 rename t4;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 2, 2);
SUCCESS
rename table t4 to t3;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 2, 2);
SUCCESS
truncate table t3;
call p_verify_status_increment(4, 4, 4, 4);
-ERROR
-Expected commit increment: 4 actual: 2
+SUCCESS
+
create view v1 as select * from t2;
call p_verify_status_increment(1, 0, 1, 0);
SUCCESS
=== added file 'mysql-test/r/disabled_partition.require'
--- a/mysql-test/r/disabled_partition.require 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/disabled_partition.require 2009-01-08 14:16:44 +0000
@@ -0,0 +1,2 @@
+Variable_name Value
+have_partitioning DISABLED
=== modified file 'mysql-test/r/group_min_max.result'
--- a/mysql-test/r/group_min_max.result 2009-07-13 17:36:54 +0000
+++ b/mysql-test/r/group_min_max.result 2009-08-30 07:03:37 +0000
@@ -2502,3 +2502,15 @@ a MAX(b)
2 1
DROP TABLE t;
End of 5.0 tests
+#
+# Bug #46607: Assertion failed: (cond_type == Item::FUNC_ITEM) results in
+# server crash
+#
+CREATE TABLE t (a INT, b INT, INDEX (a,b));
+INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1);
+INSERT INTO t SELECT * FROM t;
+SELECT a, MAX(b) FROM t WHERE b GROUP BY a;
+a MAX(b)
+2 1
+DROP TABLE t;
+End of 5.1 tests
=== modified file 'mysql-test/r/handler_myisam.result'
--- a/mysql-test/r/handler_myisam.result 2009-07-10 23:12:13 +0000
+++ b/mysql-test/r/handler_myisam.result 2009-08-21 05:55:35 +0000
@@ -741,3 +741,19 @@ USE information_schema;
HANDLER COLUMNS OPEN;
ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema
USE test;
+#
+# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
+#
+CREATE TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+DROP TABLE t1;
+End of 5.1 tests
=== modified file 'mysql-test/r/lock_multi_bug38499.result'
--- a/mysql-test/r/lock_multi_bug38499.result 2009-03-23 14:22:31 +0000
+++ b/mysql-test/r/lock_multi_bug38499.result 2009-08-28 21:49:16 +0000
@@ -1,3 +1,5 @@
+SET @odl_sync_frm = @@global.sync_frm;
+SET @@global.sync_frm = OFF;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1( a INT, b INT );
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
@@ -17,3 +19,4 @@ ALTER TABLE t1 ADD COLUMN a INT;
# 2.2.1. normal mode
# 2.2.2. PS mode
DROP TABLE t1;
+SET @@global.sync_frm = @odl_sync_frm;
=== modified file 'mysql-test/r/lock_multi_bug38691.result'
--- a/mysql-test/r/lock_multi_bug38691.result 2009-03-23 14:22:31 +0000
+++ b/mysql-test/r/lock_multi_bug38691.result 2009-08-28 21:49:16 +0000
@@ -1,3 +1,5 @@
+SET @odl_sync_frm = @@global.sync_frm;
+SET @@global.sync_frm = OFF;
DROP TABLE IF EXISTS t1,t2,t3;
CREATE TABLE t1 (
a int(11) unsigned default NULL,
@@ -15,3 +17,4 @@ CREATE TABLE t3 SELECT * FROM t1;
# normal mode
# PS mode
DROP TABLE t1, t2, t3;
+SET @@global.sync_frm = @odl_sync_frm;
=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result 2009-10-28 07:52:34 +0000
+++ b/mysql-test/r/merge.result 2009-11-06 17:22:32 +0000
@@ -2159,4 +2159,16 @@ ERROR HY000: Table storage engine for 'm
DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7;
SELECT 1 FROM m1;
ERROR 42S02: Table 'test.m1' doesn't exist
+#
+# Bug #46614: Assertion in show_create_trigger()
+#
+CREATE TABLE t1(a int);
+CREATE TABLE t2(a int);
+CREATE TABLE t3(a int) ENGINE = MERGE UNION(t1, t2);
+CREATE TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo();
+SHOW CREATE TRIGGER tr1;
+Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
+tr1 CREATE DEFINER=`root`@`localhost` TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo() latin1 latin1_swedish_ci latin1_swedish_ci
+DROP TRIGGER tr1;
+DROP TABLE t1, t2, t3;
End of 5.1 tests
=== modified file 'mysql-test/r/mysqlbinlog_row_trans.result'
--- a/mysql-test/r/mysqlbinlog_row_trans.result 2009-02-10 21:26:37 +0000
+++ b/mysql-test/r/mysqlbinlog_row_trans.result 2009-08-27 09:32:27 +0000
@@ -215,14 +215,30 @@ COMMIT/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
TRUNCATE TABLE t1
/*!*/;
# at #
+#010909 4:46:40 server id 1 end_log_pos # Xid = #
+COMMIT/*!*/;
+# at #
+#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
TRUNCATE TABLE t1
/*!*/;
# at #
+#010909 4:46:40 server id 1 end_log_pos # Xid = #
+COMMIT/*!*/;
+# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
BEGIN
@@ -331,9 +347,17 @@ COMMIT/*!*/;
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
TRUNCATE TABLE t1
/*!*/;
# at #
+#010909 4:46:40 server id 1 end_log_pos # Xid = #
+COMMIT/*!*/;
+# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
TRUNCATE TABLE t2
@@ -449,9 +473,17 @@ ROLLBACK
# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
TRUNCATE TABLE t1
/*!*/;
# at #
+#010909 4:46:40 server id 1 end_log_pos # Xid = #
+COMMIT/*!*/;
+# at #
#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0
SET TIMESTAMP=1000000000/*!*/;
TRUNCATE TABLE t2
=== modified file 'mysql-test/r/not_partition.result'
--- a/mysql-test/r/not_partition.result 2006-10-26 17:11:09 +0000
+++ b/mysql-test/r/not_partition.result 2009-01-08 14:16:44 +0000
@@ -1,3 +1,48 @@
+DROP TABLE IF EXISTS t1;
+FLUSH TABLES;
+SELECT * FROM t1;
+ERROR 42000: Unknown table engine 'partition'
+TRUNCATE TABLE t1;
+ERROR 42000: Unknown table engine 'partition'
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze Error Unknown table engine 'partition'
+test.t1 analyze error Corrupt
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check Error Unknown table engine 'partition'
+test.t1 check error Corrupt
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize Error Unknown table engine 'partition'
+test.t1 optimize error Corrupt
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair Error Unknown table engine 'partition'
+test.t1 repair error Corrupt
+ALTER TABLE t1 REPAIR PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 repair Error Unknown table engine 'partition'
+test.t1 repair error Corrupt
+ALTER TABLE t1 CHECK PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 check Error Unknown table engine 'partition'
+test.t1 check error Corrupt
+ALTER TABLE t1 OPTIMIZE PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 optimize Error Unknown table engine 'partition'
+test.t1 optimize error Corrupt
+ALTER TABLE t1 ANALYZE PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 analyze Error Unknown table engine 'partition'
+test.t1 analyze error Corrupt
+ALTER TABLE t1 REBUILD PARTITION ALL;
+ERROR 42000: Unknown table engine 'partition'
+ALTER TABLE t1 ENGINE Memory;
+ERROR 42000: Unknown table engine 'partition'
+ALTER TABLE t1 ADD (new INT);
+ERROR 42000: Unknown table engine 'partition'
+DROP TABLE t1;
CREATE TABLE t1 (
firstname VARCHAR(25) NOT NULL,
lastname VARCHAR(25) NOT NULL,
=== modified file 'mysql-test/r/partition.result'
--- a/mysql-test/r/partition.result 2009-09-07 20:50:10 +0000
+++ b/mysql-test/r/partition.result 2009-10-15 21:38:29 +0000
@@ -1,4 +1,55 @@
drop table if exists t1, t2;
+CREATE TABLE t1 (
+a int NOT NULL,
+b int NOT NULL);
+CREATE TABLE t2 (
+a int NOT NULL,
+b int NOT NULL,
+INDEX(b)
+)
+PARTITION BY HASH(a) PARTITIONS 2;
+INSERT INTO t1 VALUES (399, 22);
+INSERT INTO t2 VALUES (1, 22), (1, 42);
+INSERT INTO t2 SELECT 1, 399 FROM t2, t1
+WHERE t1.b = t2.b;
+DROP TABLE t1, t2;
+CREATE TABLE t1 (
+a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+b varchar(10),
+PRIMARY KEY (a)
+)
+PARTITION BY RANGE (to_days(a)) (
+PARTITION p1 VALUES LESS THAN (733407),
+PARTITION pmax VALUES LESS THAN MAXVALUE
+);
+INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1');
+INSERT INTO t1 VALUES ('2009-07-14 17:35:55', 'pmax');
+INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax');
+SELECT * FROM t1;
+a b
+2007-07-30 17:35:48 p1
+2009-07-14 17:35:55 pmax
+2009-09-21 17:31:42 pmax
+ALTER TABLE t1 REORGANIZE PARTITION pmax INTO (
+PARTITION p3 VALUES LESS THAN (733969),
+PARTITION pmax VALUES LESS THAN MAXVALUE);
+SELECT * FROM t1;
+a b
+2007-07-30 17:35:48 p1
+2009-07-14 17:35:55 pmax
+2009-09-21 17:31:42 pmax
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `b` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (to_days(a))
+(PARTITION p1 VALUES LESS THAN (733407) ENGINE = MyISAM,
+ PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM,
+ PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
+DROP TABLE t1;
CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a))
ENGINE=MyISAM
PARTITION BY HASH (a);
=== added file 'mysql-test/r/partition_disabled.result'
--- a/mysql-test/r/partition_disabled.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/partition_disabled.result 2009-01-08 14:16:44 +0000
@@ -0,0 +1,93 @@
+DROP TABLE IF EXISTS t1;
+FLUSH TABLES;
+SELECT * FROM t1;
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+TRUNCATE TABLE t1;
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 analyze error Corrupt
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 check error Corrupt
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 optimize error Corrupt
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 repair error Corrupt
+ALTER TABLE t1 REPAIR PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 repair Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 repair error Corrupt
+ALTER TABLE t1 CHECK PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 check Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 check error Corrupt
+ALTER TABLE t1 OPTIMIZE PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 optimize Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 optimize error Corrupt
+ALTER TABLE t1 ANALYZE PARTITION ALL;
+Table Op Msg_type Msg_text
+test.t1 analyze Error The MySQL server is running with the --skip-partition option so it cannot execute this statement
+test.t1 analyze error Corrupt
+ALTER TABLE t1 REBUILD PARTITION ALL;
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+ALTER TABLE t1 ENGINE Memory;
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+ALTER TABLE t1 ADD (new INT);
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+DROP TABLE t1;
+CREATE TABLE t1 (
+firstname VARCHAR(25) NOT NULL,
+lastname VARCHAR(25) NOT NULL,
+username VARCHAR(16) NOT NULL,
+email VARCHAR(35),
+joined DATE NOT NULL
+)
+PARTITION BY KEY(joined)
+PARTITIONS 6;
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+ALTER TABLE t1 PARTITION BY KEY(joined) PARTITIONS 2;
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+drop table t1;
+ERROR 42S02: Unknown table 't1'
+CREATE TABLE t1 (
+firstname VARCHAR(25) NOT NULL,
+lastname VARCHAR(25) NOT NULL,
+username VARCHAR(16) NOT NULL,
+email VARCHAR(35),
+joined DATE NOT NULL
+)
+PARTITION BY RANGE( YEAR(joined) ) (
+PARTITION p0 VALUES LESS THAN (1960),
+PARTITION p1 VALUES LESS THAN (1970),
+PARTITION p2 VALUES LESS THAN (1980),
+PARTITION p3 VALUES LESS THAN (1990),
+PARTITION p4 VALUES LESS THAN MAXVALUE
+);
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+drop table t1;
+ERROR 42S02: Unknown table 't1'
+CREATE TABLE t1 (id INT, purchased DATE)
+PARTITION BY RANGE( YEAR(purchased) )
+SUBPARTITION BY HASH( TO_DAYS(purchased) )
+SUBPARTITIONS 2 (
+PARTITION p0 VALUES LESS THAN (1990),
+PARTITION p1 VALUES LESS THAN (2000),
+PARTITION p2 VALUES LESS THAN MAXVALUE
+);
+ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement
+drop table t1;
+ERROR 42S02: Unknown table 't1'
+create table t1 (a varchar(10) charset latin1 collate latin1_bin);
+insert into t1 values (''),(' '),('a'),('a '),('a ');
+explain partitions select * from t1 where a='a ' OR a='a';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 5 Using where
+drop table t1;
=== modified file 'mysql-test/r/partition_pruning.result'
--- a/mysql-test/r/partition_pruning.result 2008-12-28 11:33:49 +0000
+++ b/mysql-test/r/partition_pruning.result 2009-09-01 12:53:27 +0000
@@ -1,4 +1,1282 @@
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+# test of RANGE and index
+CREATE TABLE t1 (a DATE, KEY(a))
+PARTITION BY RANGE (TO_DAYS(a))
+(PARTITION `pNULL` VALUES LESS THAN (0),
+PARTITION `p0001-01-01` VALUES LESS THAN (366 + 1),
+PARTITION `p1001-01-01` VALUES LESS THAN (TO_DAYS('1001-01-01') + 1),
+PARTITION `p2001-01-01` VALUES LESS THAN (TO_DAYS('2001-01-01') + 1));
+INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
+('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
+SELECT * FROM t1 WHERE a < '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-01-01';
+a
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-01-01';
+a
+1001-01-01
+SELECT * FROM t1 WHERE a < '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-00-00';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-00-00';
+a
+1001-00-00
+# Disabling warnings for the invalid date
+SELECT * FROM t1 WHERE a < '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a > '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a = '1999-02-31';
+a
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+a
+0001-01-01
+1001-00-00
+1001-01-01
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p2001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1001-01-01 system a NULL NULL NULL 1
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
+# Disabling warnings for the invalid date
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p2001-01-01 range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p2001-01-01 range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+# test without index
+ALTER TABLE t1 DROP KEY a;
+SELECT * FROM t1 WHERE a < '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-01-01';
+a
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-01-01';
+a
+1001-01-01
+SELECT * FROM t1 WHERE a < '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-00-00';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-00-00';
+a
+1001-00-00
+# Disabling warnings for the invalid date
+SELECT * FROM t1 WHERE a < '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a > '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a = '1999-02-31';
+a
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+a
+0001-01-01
+1001-00-00
+1001-01-01
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1001-01-01 system NULL NULL NULL NULL 1
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
+# Disabling warnings for the invalid date
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+DROP TABLE t1;
+# test of LIST and index
+CREATE TABLE t1 (a DATE, KEY(a))
+PARTITION BY LIST (TO_DAYS(a))
+(PARTITION `p0001-01-01` VALUES IN (TO_DAYS('0001-01-01')),
+PARTITION `p2001-01-01` VALUES IN (TO_DAYS('2001-01-01')),
+PARTITION `pNULL` VALUES IN (NULL),
+PARTITION `p0000-01-02` VALUES IN (TO_DAYS('0000-01-02')),
+PARTITION `p1001-01-01` VALUES IN (TO_DAYS('1001-01-01')));
+INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
+('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
+SELECT * FROM t1 WHERE a < '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-01-01';
+a
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-01-01';
+a
+1001-01-01
+SELECT * FROM t1 WHERE a < '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-00-00';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-00-00';
+a
+1001-00-00
+# Disabling warnings for the invalid date
+SELECT * FROM t1 WHERE a < '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a > '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a = '1999-02-31';
+a
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+a
+0001-01-01
+1001-00-00
+1001-01-01
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1001-01-01 system a NULL NULL NULL 1
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
+# Disabling warnings for the invalid date
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01 range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+# test without index
+ALTER TABLE t1 DROP KEY a;
+SELECT * FROM t1 WHERE a < '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-01-01';
+a
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-01-01';
+a
+1001-01-01
+SELECT * FROM t1 WHERE a < '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-00-00';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-00-00';
+a
+1001-00-00
+# Disabling warnings for the invalid date
+SELECT * FROM t1 WHERE a < '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a > '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a = '1999-02-31';
+a
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+a
+0001-01-01
+1001-00-00
+1001-01-01
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1001-01-01 system NULL NULL NULL NULL 1
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
+# Disabling warnings for the invalid date
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+DROP TABLE t1;
+# Test with DATETIME column NOT NULL
+CREATE TABLE t1 (
+a int(10) unsigned NOT NULL,
+b DATETIME NOT NULL,
+PRIMARY KEY (a, b)
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'),
+(1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'),
+(1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 6 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 8 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 8 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index
+DROP TABLE t1;
+# Test with DATE column NOT NULL
+CREATE TABLE t1 (
+a int(10) unsigned NOT NULL,
+b DATE NOT NULL,
+PRIMARY KEY (a, b)
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'),
+(1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'),
+(1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 7 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 7 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index
+DROP TABLE t1;
+# Test with DATETIME column NULL
+CREATE TABLE t1 (
+a int(10) unsigned NOT NULL,
+b DATETIME NULL
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'),
+(1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'),
+(1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 8 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 8 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where
+DROP TABLE t1;
+# Test with DATE column NULL
+CREATE TABLE t1 (
+a int(10) unsigned NOT NULL,
+b DATE NULL
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'),
+(1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'),
+(1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1
+WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where
+DROP TABLE t1;
+# For better code coverage of the patch
+CREATE TABLE t1 (
+a int(10) unsigned NOT NULL,
+b DATE
+) PARTITION BY RANGE ( TO_DAYS(b) )
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL);
+# test with an invalid date, which lead to item->null_value is set.
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME);
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p20090401 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Warning 1292 Incorrect datetime value: '2009-04-99'
+Warning 1292 Incorrect datetime value: '2009-04-99'
+DROP TABLE t1;
CREATE TABLE t1
(a INT NOT NULL AUTO_INCREMENT,
b DATETIME,
=== modified file 'mysql-test/r/partition_range.result'
--- a/mysql-test/r/partition_range.result 2008-11-04 07:43:21 +0000
+++ b/mysql-test/r/partition_range.result 2009-08-26 10:59:49 +0000
@@ -745,7 +745,7 @@ a
EXPLAIN PARTITIONS SELECT * FROM t1
WHERE a >= '2004-07-01' AND a <= '2004-09-30';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p3xx,p407,p408,p409 ALL NULL NULL NULL NULL 18 Using where
SELECT * from t1
WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR
(a >= '2005-07-01' AND a <= '2005-09-30');
@@ -772,7 +772,7 @@ EXPLAIN PARTITIONS SELECT * from t1
WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR
(a >= '2005-07-01' AND a <= '2005-09-30');
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t1 p3xx,p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 27 Using where
DROP TABLE t1;
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result 2009-09-15 10:46:35 +0000
+++ b/mysql-test/r/subselect.result 2009-10-15 21:38:29 +0000
@@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR HY000: Incorrect parameters to procedure 'ANALYSE'
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -4383,6 +4383,34 @@ id select_type table type possible_keys
1 PRIMARY C ALL NULL NULL NULL NULL 20 100.00 Using where
DROP TABLE C;
# End of test for bug#45061.
+#
+# Bug #46749: Segfault in add_key_fields() with outer subquery level
+# field references
+#
+CREATE TABLE t1 (
+a int,
+b int,
+UNIQUE (a), KEY (b)
+);
+INSERT INTO t1 VALUES (1,1), (2,1);
+CREATE TABLE st1 like t1;
+INSERT INTO st1 VALUES (1,1), (2,1);
+CREATE TABLE st2 like t1;
+INSERT INTO st2 VALUES (1,1), (2,1);
+EXPLAIN
+SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
+FROM t1
+WHERE a = 230;
+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 DEPENDENT SUBQUERY st1 index NULL a 5 NULL 2 Using index
+2 DEPENDENT SUBQUERY st2 index b b 5 NULL 2 Using where; Using index; Using join buffer
+SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
+FROM t1
+WHERE a = 230;
+MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
+NULL 0
+DROP TABLE t1, st1, st2;
End of 5.0 tests.
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
=== added file 'mysql-test/r/table_elim_debug.result'
--- a/mysql-test/r/table_elim_debug.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/table_elim_debug.result 2009-10-29 17:50:33 +0000
@@ -0,0 +1,22 @@
+drop table if exists t1, t2;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3);
+create table t2 (a int primary key, b int)
+as select a, a as b from t1 where a in (1,2);
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+set optimizer_switch='table_elimination=off';
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using index
+set optimizer_switch='table_elimination=on';
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+set optimizer_switch='table_elimination=default';
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
+drop table t1, t2;
=== modified file 'mysql-test/r/type_newdecimal.result'
--- a/mysql-test/r/type_newdecimal.result 2009-07-03 10:36:04 +0000
+++ b/mysql-test/r/type_newdecimal.result 2009-08-24 19:47:08 +0000
@@ -1495,9 +1495,9 @@ CREATE TABLE t1 (a int DEFAULT NULL, b i
INSERT INTO t1 VALUES (3,30), (1,10), (2,10);
SELECT a+CAST(1 AS decimal(65,30)) AS aa, SUM(b) FROM t1 GROUP BY aa;
aa SUM(b)
-2.000000000000000000000000000000 10
-3.000000000000000000000000000000 10
-4.000000000000000000000000000000 30
+2.00000000000000000000000000000 10
+3.00000000000000000000000000000 10
+4.00000000000000000000000000000 30
SELECT a+CAST(1 AS decimal(65,31)) AS aa, SUM(b) FROM t1 GROUP BY aa;
ERROR 42000: Too big scale 31 specified for column '1'. Maximum is 30.
DROP TABLE t1;
@@ -1521,13 +1521,13 @@ f1
DROP TABLE t1;
CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1;
Warnings:
-Warning 1264 Out of range value for column 'f1' at row 1
+Note 1265 Data truncated for column 'f1' at row 1
DESC t1;
Field Type Null Key Default Extra
-f1 decimal(65,30) NO 0.000000000000000000000000000000
+f1 decimal(65,20) NO 0.00000000000000000000
SELECT f1 FROM t1;
f1
-99999999999999999999999999999999999.999999999999999999999999999999
+123451234512345123451234512345123451234512345.67890678906789067891
DROP TABLE t1;
select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 *
1.01500000 * 1.01500000 * 0.99500000);
@@ -1595,7 +1595,7 @@ Warnings:
Note 1265 Data truncated for column 'my_col' at row 1
DESCRIBE t1;
Field Type Null Key Default Extra
-my_col decimal(65,30) NO 0.000000000000000000000000000000
+my_col decimal(32,30) NO 0.000000000000000000000000000000
SELECT my_col FROM t1;
my_col
1.123456789123456789123456789123
@@ -1625,8 +1625,212 @@ Warnings:
Note 1265 Data truncated for column 'my_col' at row 1
DESCRIBE t1;
Field Type Null Key Default Extra
-my_col decimal(65,30) YES NULL
+my_col decimal(30,30) YES NULL
SELECT my_col FROM t1;
my_col
0.012345687012345687012345687012
DROP TABLE t1;
+#
+# Bug#45261: Crash, stored procedure + decimal
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 SELECT
+/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001
+AS c1;
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,0) NO 0
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.
+AS c1;
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,0) NO 0
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */
+AS c1;
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,0) NO 0
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
+AS c1;
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,0) NO 0
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */
+AS c1;
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,25) NO 0.0000000000000000000000000
+SELECT * FROM t1;
+c1
+1000000000000000000000000000000000000001.1000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */
+AS c1;
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(31,30) NO 0.000000000000000000000000000000
+SELECT * FROM t1;
+c1
+1.100000000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+AS c1;
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(31,30) NO 0.000000000000000000000000000000
+SELECT * FROM t1;
+c1
+1.100000000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+AS c1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(30,30) NO 0.000000000000000000000000000000
+SELECT * FROM t1;
+c1
+0.100000000000000000000000000000
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */
+AS c1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,20) NO 0.00000000000000000000
+SELECT * FROM t1;
+c1
+123456789012345678901234567890123456789012345.12345678901234567890
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */
+AS c1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,0) NO 0
+SELECT * FROM t1;
+c1
+12345678901234567890123456789012345678901234567890123456789012345
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */
+AS c1;
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,0) NO 0
+SELECT * FROM t1;
+c1
+99999999999999999999999999999999999999999999999999999999999999999
+DROP TABLE t1;
+CREATE TABLE t1 SELECT
+.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */
+AS c1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(30,30) NO 0.000000000000000000000000000000
+SELECT * FROM t1;
+c1
+0.123456789012345678901234567890
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(33,30) NO 0.000000000000000000000000000000
+SELECT * FROM t1;
+c1
+123.123456789012345678901234567890
+DROP TABLE t1;
+CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1;
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,29) NO 0.00000000000000000000000000000
+SELECT * FROM t1;
+c1
+2.10000000000000000000000000000
+DROP TABLE t1;
+#
+# Test that the integer and decimal parts are properly calculated.
+#
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 3
+DESC t2;
+Field Type Null Key Default Extra
+c1 decimal(32,30) YES NULL
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+Note 1265 Data truncated for column 'c1' at row 2
+Note 1265 Data truncated for column 'c1' at row 3
+DESC t2;
+Field Type Null Key Default Extra
+c1 decimal(32,30) YES NULL
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1;
+Warnings:
+Note 1265 Data truncated for column 'c1' at row 1
+DESC t2;
+Field Type Null Key Default Extra
+c1 decimal(31,30) YES NULL
+DROP TABLE t1,t2;
+#
+# Test that variables get maximum precision.
+#
+SET @decimal= 1.1;
+CREATE TABLE t1 SELECT @decimal AS c1;
+DESC t1;
+Field Type Null Key Default Extra
+c1 decimal(65,30) YES NULL
+SELECT * FROM t1;
+c1
+1.100000000000000000000000000000
+DROP TABLE t1;
=== modified file 'mysql-test/r/view.result'
--- a/mysql-test/r/view.result 2009-09-07 20:50:10 +0000
+++ b/mysql-test/r/view.result 2009-10-15 21:38:29 +0000
@@ -3718,117 +3718,6 @@ DROP TABLE t1;
# -- End of test case for Bug#40825
-#
-# Bug #45806 crash when replacing into a view with a join!
-#
-CREATE TABLE t1(a INT UNIQUE);
-CREATE VIEW v1 AS SELECT t1.a FROM t1, t1 AS a;
-INSERT INTO t1 VALUES (1), (2);
-REPLACE INTO v1(a) SELECT 1 FROM t1,t1 AS c;
-SELECT * FROM v1;
-a
-1
-2
-1
-2
-REPLACE INTO v1(a) SELECT 3 FROM t1,t1 AS c;
-SELECT * FROM v1;
-a
-1
-2
-3
-1
-2
-3
-1
-2
-3
-DELETE FROM t1 WHERE a=3;
-INSERT INTO v1(a) SELECT 1 FROM t1,t1 AS c
-ON DUPLICATE KEY UPDATE `v1`.`a`= 1;
-SELECT * FROM v1;
-a
-1
-2
-1
-2
-CREATE VIEW v2 AS SELECT t1.a FROM t1, v1 AS a;
-REPLACE INTO v2(a) SELECT 1 FROM t1,t1 AS c;
-SELECT * FROM v2;
-a
-1
-2
-1
-2
-1
-2
-1
-2
-REPLACE INTO v2(a) SELECT 3 FROM t1,t1 AS c;
-SELECT * FROM v2;
-a
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-INSERT INTO v2(a) SELECT 1 FROM t1,t1 AS c
-ON DUPLICATE KEY UPDATE `v2`.`a`= 1;
-SELECT * FROM v2;
-a
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-1
-2
-3
-DROP VIEW v1;
-DROP VIEW v2;
-DROP TABLE t1;
-# -- End of test case for Bug#45806
# -----------------------------------------------------------------
# -- End of 5.0 tests.
# -----------------------------------------------------------------
=== added file 'mysql-test/std_data/loaddata_utf8.dat'
--- a/mysql-test/std_data/loaddata_utf8.dat 1970-01-01 00:00:00 +0000
+++ b/mysql-test/std_data/loaddata_utf8.dat 2009-08-12 03:54:05 +0000
@@ -0,0 +1,3 @@
+一二三
+四五六
+七八九
=== added file 'mysql-test/std_data/parts/t1.frm'
Files a/mysql-test/std_data/parts/t1.frm 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/parts/t1.frm 2009-01-08 14:16:44 +0000 differ
=== modified file 'mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result'
--- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result 2009-05-31 05:44:41 +0000
+++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result 2009-08-26 23:13:03 +0000
@@ -379,7 +379,9 @@ master-bin.000001 # Query # # BEGIN
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE table t2
+master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
@@ -838,8 +840,10 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1)
ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
master-bin.000001 # Intvar # # INSERT_ID=6
master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */
+master-bin.000001 # Query # # ROLLBACK
select count(*) from t1 /* must be 4 */;
count(*)
4
=== modified file 'mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result'
--- a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result 2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result 2009-08-28 09:45:57 +0000
@@ -17,5 +17,5 @@ master-bin.000001 # Query # # create dat
master-bin.000001 # Query # # use `drop-temp+table-test`; create temporary table shortn1 (a int)
master-bin.000001 # Query # # use `drop-temp+table-test`; create temporary table `table:name` (a int)
master-bin.000001 # Query # # use `drop-temp+table-test`; create temporary table shortn2 (a int)
-master-bin.000001 # Query # # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`,`drop-temp+table-test`.`table:name`,`drop-temp+table-test`.`shortn1`
+master-bin.000001 # Query # # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `shortn2`,`table:name`,`shortn1`
drop database `drop-temp+table-test`;
=== modified file 'mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result'
--- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result 2009-05-31 05:44:41 +0000
+++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result 2009-08-28 09:45:57 +0000
@@ -258,7 +258,7 @@ master-bin.000001 # Query # # use `test`
master-bin.000001 # Query # # use `test`; insert t0 select * from t1
master-bin.000001 # Query # # use `test`; insert into t0 select GET_LOCK("lock1",null)
master-bin.000001 # Query # # use `test`; create table t2 (n int) engine=innodb
-master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti`
+master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`,`ti`
do release_lock("lock1");
drop table t0,t2;
set autocommit=0;
@@ -346,7 +346,9 @@ master-bin.000001 # Query # # use `test`
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t2
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4,4)
+master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; TRUNCATE table t2
+master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (5,5)
master-bin.000001 # Query # # use `test`; DROP TABLE t2
master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (6,6)
@@ -545,8 +547,10 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1)
ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
master-bin.000001 # Intvar # # INSERT_ID=6
master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */
+master-bin.000001 # Query # # ROLLBACK
/* the output must denote there is the query */;
select count(*) from t1 /* must be 4 */;
count(*)
@@ -782,8 +786,10 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1)
ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
master-bin.000001 # Intvar # # INSERT_ID=6
master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */
+master-bin.000001 # Query # # ROLLBACK
select count(*) from t1 /* must be 4 */;
count(*)
4
=== modified file 'mysql-test/suite/federated/disabled.def'
--- a/mysql-test/suite/federated/disabled.def 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/federated/disabled.def 2009-10-30 18:50:56 +0000
@@ -9,4 +9,5 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-federated_transactions : Bug#29523 Transactions do not work
+federated_server : needs fixup
+
=== modified file 'mysql-test/suite/federated/federated.result'
--- a/mysql-test/suite/federated/federated.result 2009-03-19 08:49:51 +0000
+++ b/mysql-test/suite/federated/federated.result 2009-10-30 18:50:56 +0000
@@ -47,9 +47,10 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
-SELECT * FROM federated.t1;
-ERROR HY000: The foreign data source you are trying to reference does not exist. Data source error: error: 1146 'Table 'federated.t3' doesn't exist'
-DROP TABLE federated.t1;
+ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'root' hostname: '127.0.0.1'
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -59,9 +60,10 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
-SELECT * FROM federated.t1;
-ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES)
-DROP TABLE federated.t1;
+ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'user' hostname: '127.0.0.1'
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -1944,15 +1946,7 @@ Bug#18287 create federated table always
Test that self-references work
-create table federated.t1 (a int primary key);
-create table federated.t2 (a int primary key)
-ENGINE=FEDERATED
-connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
-insert into federated.t1 (a) values (1);
-select * from federated.t2;
-a
-1
-drop table federated.t1, federated.t2;
+fix LOCK_open before reenabling test for Bug#18287
CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8;
CREATE TABLE federated.t1 (a INT PRIMARY KEY)
ENGINE=FEDERATED
@@ -1960,13 +1954,11 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE
DEFAULT CHARSET=utf8;
SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED";
transactions
-NO
+YES
INSERT INTO federated.t1 VALUES (1);
SET autocommit=0;
INSERT INTO federated.t1 VALUES (2);
ROLLBACK;
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
SET autocommit=1;
SELECT * FROM federated.t1;
a
@@ -2157,6 +2149,6 @@ End of 5.1 tests
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated.test'
--- a/mysql-test/suite/federated/federated.test 2009-03-19 08:49:51 +0000
+++ b/mysql-test/suite/federated/federated.test 2009-10-30 18:50:56 +0000
@@ -57,6 +57,7 @@ CREATE TABLE federated.t1 (
# test non-existant table
--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_CANT_CREATE_FEDERATED_TABLE
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -66,12 +67,11 @@ eval CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3';
---error ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
-SELECT * FROM federated.t1;
-DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
# test bad user/password
--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_CANT_CREATE_FEDERATED_TABLE
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -81,9 +81,7 @@ eval CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1';
---error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
-SELECT * FROM federated.t1;
-DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
# # correct connection, same named tables
--replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -1806,6 +1804,8 @@ drop table federated.t1;
--echo
--echo Test that self-references work
--echo
+--echo fix LOCK_open before reenabling test for Bug#18287
+--disable_parsing
connection slave;
create table federated.t1 (a int primary key);
--replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -1815,7 +1815,7 @@ eval create table federated.t2 (a int pr
insert into federated.t1 (a) values (1);
select * from federated.t2;
drop table federated.t1, federated.t2;
-
+--enable_parsing
#
# BUG#29875 Disable support for transactions
#
=== modified file 'mysql-test/suite/federated/federated_archive.result'
--- a/mysql-test/suite/federated/federated_archive.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_archive.result 2009-10-30 18:50:56 +0000
@@ -34,6 +34,6 @@ id name
DROP TABLE federated.t1;
DROP TABLE federated.archive_table;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_bug_13118.result'
--- a/mysql-test/suite/federated/federated_bug_13118.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_bug_13118.result 2009-10-30 18:50:56 +0000
@@ -25,6 +25,6 @@ foo bar
DROP TABLE federated.t1;
DROP TABLE federated.bug_13118_table;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_bug_25714.result'
--- a/mysql-test/suite/federated/federated_bug_25714.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_bug_25714.result 2009-10-30 18:50:56 +0000
@@ -48,6 +48,6 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MAS
DROP TABLE federated.t1;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_cleanup.inc'
--- a/mysql-test/suite/federated/federated_cleanup.inc 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_cleanup.inc 2009-10-30 18:50:56 +0000
@@ -1,9 +1,9 @@
connection master;
--disable_warnings
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
connection slave;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
--enable_warnings
=== modified file 'mysql-test/suite/federated/federated_innodb.result'
--- a/mysql-test/suite/federated/federated_innodb.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_innodb.result 2009-10-30 18:50:56 +0000
@@ -20,6 +20,6 @@ a b
drop table federated.t1;
drop table federated.t1;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_server.result'
--- a/mysql-test/suite/federated/federated_server.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_server.result 2009-10-30 18:50:56 +0000
@@ -178,8 +178,8 @@ INSERT INTO db_bogus.t1 VALUES ('2','thi
create server 's1' foreign data wrapper 'mysql' options
(HOST '127.0.0.1',
DATABASE 'db_legitimate',
-USER 'root',
-PASSWORD '',
+USER 'test_fed',
+PASSWORD 'foo',
PORT SLAVE_PORT,
SOCKET '',
OWNER 'root');
=== modified file 'mysql-test/suite/federated/federated_server.test'
--- a/mysql-test/suite/federated/federated_server.test 2009-06-05 15:35:22 +0000
+++ b/mysql-test/suite/federated/federated_server.test 2009-10-30 18:50:56 +0000
@@ -3,6 +3,7 @@
# Slow test, don't run during staging part
-- source include/not_staging.inc
+-- source include/big_test.inc
-- source federated.inc
connection slave;
@@ -182,13 +183,17 @@ CREATE TABLE db_bogus.t1 (
;
INSERT INTO db_bogus.t1 VALUES ('2','this is bogus');
+connection slave;
+create user test_fed@localhost identified by 'foo';
+grant all on db_legitimate.* to test_fed@localhost;
+
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create server 's1' foreign data wrapper 'mysql' options
(HOST '127.0.0.1',
DATABASE 'db_legitimate',
- USER 'root',
- PASSWORD '',
+ USER 'test_fed',
+ PASSWORD 'foo',
PORT $SLAVE_MYPORT,
SOCKET '',
OWNER 'root');
=== modified file 'mysql-test/suite/federated/federated_transactions.result'
--- a/mysql-test/suite/federated/federated_transactions.result 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/federated/federated_transactions.result 2009-10-30 18:50:56 +0000
@@ -1,13 +1,4 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-stop slave;
-DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
-DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
DROP TABLE IF EXISTS federated.t1;
Warnings:
=== modified file 'mysql-test/suite/funcs_1/r/is_engines_federated.result'
--- a/mysql-test/suite/funcs_1/r/is_engines_federated.result 2008-03-07 19:18:14 +0000
+++ b/mysql-test/suite/funcs_1/r/is_engines_federated.result 2009-11-07 06:29:10 +0000
@@ -2,7 +2,7 @@ SELECT * FROM information_schema.engines
WHERE ENGINE = 'FEDERATED';
ENGINE FEDERATED
SUPPORT YES
-COMMENT Federated MySQL storage engine
-TRANSACTIONS NO
+COMMENT FederatedX pluggable storage engine
+TRANSACTIONS YES
XA NO
-SAVEPOINTS NO
+SAVEPOINTS YES
=== modified file 'mysql-test/suite/pbxt/r/partition_range.result'
--- a/mysql-test/suite/pbxt/r/partition_range.result 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/r/partition_range.result 2009-10-16 12:45:42 +0000
@@ -710,7 +710,7 @@ a
EXPLAIN PARTITIONS SELECT * FROM t1
WHERE a >= '2004-07-01' AND a <= '2004-09-30';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p3xx,p407,p408,p409 ALL NULL NULL NULL NULL 18 Using where
SELECT * from t1
WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR
(a >= '2005-07-01' AND a <= '2005-09-30');
@@ -737,5 +737,5 @@ EXPLAIN PARTITIONS SELECT * from t1
WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR
(a >= '2005-07-01' AND a <= '2005-09-30');
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t1 p3xx,p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 27 Using where
DROP TABLE t1;
=== modified file 'mysql-test/suite/pbxt/r/subselect.result'
--- a/mysql-test/suite/pbxt/r/subselect.result 2009-08-17 15:57:58 +0000
+++ b/mysql-test/suite/pbxt/r/subselect.result 2009-10-16 12:45:42 +0000
@@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR HY000: Incorrect parameters to procedure 'ANALYSE'
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
=== modified file 'mysql-test/suite/pbxt/t/subselect.test'
--- a/mysql-test/suite/pbxt/t/subselect.test 2009-10-26 11:35:42 +0000
+++ b/mysql-test/suite/pbxt/t/subselect.test 2009-11-06 17:22:32 +0000
@@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1);
SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
-- error 1221
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
--- error 1108
+-- error ER_WRONG_USAGE
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-- error ER_BAD_FIELD_ERROR
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
=== modified file 'mysql-test/suite/rpl/r/rpl_concurrency_error.result'
--- a/mysql-test/suite/rpl/r/rpl_concurrency_error.result 2009-07-18 20:07:56 +0000
+++ b/mysql-test/suite/rpl/r/rpl_concurrency_error.result 2009-08-13 16:21:01 +0000
@@ -101,6 +101,8 @@ master-bin.000001 # Query # # use `test`
master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (6 + (1 * 10),"brown")
master-bin.000001 # Query # # use `test`; INSERT INTO n VALUES (now(),"brown")
master-bin.000001 # Xid # # COMMIT /* XID */
+source include/diff_master_slave.inc;
+source include/diff_master_slave.inc;
########################################################################
# Cleanup
########################################################################
=== added file 'mysql-test/suite/rpl/r/rpl_create_if_not_exists.result'
--- a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result 2009-08-29 08:52:22 +0000
@@ -0,0 +1,33 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE IF NOT EXISTS mysqltest;
+USE mysqltest;
+CREATE TABLE IF NOT EXISTS t(c1 int);
+CREATE TABLE IF NOT EXISTS t1 LIKE t;
+CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
+CREATE EVENT IF NOT EXISTS e
+ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+DO SELECT now();
+DROP DATABASE mysqltest;
+CREATE DATABASE IF NOT EXISTS mysqltest;
+USE mysqltest;
+CREATE TABLE IF NOT EXISTS t(c1 int);
+CREATE TABLE IF NOT EXISTS t1 LIKE t;
+CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
+CREATE EVENT IF NOT EXISTS e
+ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+DO SELECT now();
+SHOW TABLES in mysqltest;
+Tables_in_mysqltest
+t
+t1
+t2
+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
+DROP DATABASE IF EXISTS mysqltest;
=== added file 'mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result'
--- a/mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result 2009-08-13 02:48:57 +0000
@@ -0,0 +1,22 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+DROP DATABASE IF EXISTS mysqltest;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int);
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int);
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # DROP DATABASE IF EXISTS mysqltest
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int)
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int)
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp
=== modified file 'mysql-test/suite/rpl/r/rpl_drop_if_exists.result'
--- a/mysql-test/suite/rpl/r/rpl_drop_if_exists.result 2009-02-11 17:46:43 +0000
+++ b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result 2009-08-29 08:52:22 +0000
@@ -43,7 +43,7 @@ master-bin.000001 # Query # # use `test`
master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684
master-bin.000001 # Query # # CREATE DATABASE db_bug_13684
master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int)
-master-bin.000001 # Query # # use `test`; CREATE EVENT db_bug_13684.e
+master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` EVENT db_bug_13684.e
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE db_bug_13684.t SET a = a + 1
@@ -75,7 +75,7 @@ master-bin.000001 # Query # # use `test`
master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684
master-bin.000001 # Query # # CREATE DATABASE db_bug_13684
master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int)
-master-bin.000001 # Query # # use `test`; CREATE EVENT db_bug_13684.e
+master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` EVENT db_bug_13684.e
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE db_bug_13684.t SET a = a + 1
=== modified file 'mysql-test/suite/rpl/r/rpl_drop_temp.result'
--- a/mysql-test/suite/rpl/r/rpl_drop_temp.result 2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl/r/rpl_drop_temp.result 2009-08-28 09:45:57 +0000
@@ -5,6 +5,7 @@ reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create database if not exists mysqltest;
+use mysqltest;
create temporary table mysqltest.t1 (n int)ENGINE=MyISAM;
create temporary table mysqltest.t2 (n int)ENGINE=MyISAM;
show status like 'Slave_open_temp_tables';
=== modified file 'mysql-test/suite/rpl/r/rpl_events.result'
--- a/mysql-test/suite/rpl/r/rpl_events.result 2009-02-19 09:01:25 +0000
+++ b/mysql-test/suite/rpl/r/rpl_events.result 2009-10-15 21:38:29 +0000
@@ -191,5 +191,63 @@ select * from t28953;
END;|
ALTER EVENT event1 RENAME TO event2;
DROP EVENT event2;
+CREATE TABLE test.t1(details CHAR(30));
+CREATE EVENT /*!50000 event44331_1 */
+ON SCHEDULE AT CURRENT_TIMESTAMP
+ON COMPLETION PRESERVE DISABLE
+DO INSERT INTO test.t1 VALUES('event event44331_1 fired - no definer');
+CREATE DEFINER=CURRENT_USER /*!50000 EVENT event44331_2 */
+ON SCHEDULE AT CURRENT_TIMESTAMP
+ON COMPLETION PRESERVE DISABLE
+DO INSERT INTO test.t1 VALUES('event event44331_2 fired - DEFINER=CURRENT_USER');
+CREATE DEFINER=CURRENT_USER() EVENT event44331_3
+ON SCHEDULE AT CURRENT_TIMESTAMP
+ON COMPLETION PRESERVE DISABLE
+DO INSERT INTO test.t1 VALUES('event event44331_3 fired - DEFINER=CURRENT_USER() function');
+CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4
+ON SCHEDULE AT CURRENT_TIMESTAMP
+ON COMPLETION PRESERVE DISABLE
+DO INSERT INTO test.t1 VALUES('event event44331_4 fired - DEFINER=user1');
+Warnings:
+Note 1449 The user specified as a definer ('user44331'@'%') does not exist
+#on master
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_1';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_1 root@localhost
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_2';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_2 root@localhost
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_3';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_3 root@localhost
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_4';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_4 user44331@%
+#on slave
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_1';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_1 root@localhost
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_2';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_2 root@localhost
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_3';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_3 root@localhost
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+where EVENT_NAME='event44331_4';
+EVENT_SCHEMA EVENT_NAME DEFINER
+test event44331_4 user44331@%
SET @@global.event_scheduler= @old_event_scheduler;
DROP TABLE t28953;
+DROP TABLE t1;
+DROP EVENT event44331_1;
+DROP EVENT event44331_2;
+DROP EVENT event44331_3;
+DROP EVENT event44331_4;
=== modified file 'mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result'
--- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result 2009-05-31 05:44:41 +0000
+++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result 2009-08-29 08:52:22 +0000
@@ -690,7 +690,7 @@ test_rpl e1 root@localhost SYSTEM RECURR
USE test_rpl;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
-test_rpl e1 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
+test_rpl e1 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
==========MASTER==========
SELECT COUNT(*) FROM t1;
COUNT(*)
@@ -963,7 +963,9 @@ master-bin.000001 # Xid 1 # #
master-bin.000001 # Query 1 # BEGIN
master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 't1, text 1')
master-bin.000001 # Xid 1 # #
+master-bin.000001 # Query 1 # BEGIN
master-bin.000001 # Query 1 # use `test_rpl`; TRUNCATE t1
+master-bin.000001 # Xid 1 # #
master-bin.000001 # Query 1 # BEGIN
master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t1
master-bin.000001 # Xid 1 # #
@@ -1076,7 +1078,7 @@ master-bin.000001 # Query 1 # use `test_
master-bin.000001 # Query 1 # BEGIN
master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1')
master-bin.000001 # Xid 1 # #
-master-bin.000001 # Query 1 # use `test_rpl`; CREATE EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1
+master-bin.000001 # Query 1 # use `test_rpl`; CREATE DEFINER=`root`@`localhost` EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1
master-bin.000001 # Query 1 # use `test_rpl`; ALTER EVENT e1 RENAME TO e2
master-bin.000001 # Query 1 # use `test_rpl`; DROP EVENT e2
master-bin.000001 # Query 1 # BEGIN
=== modified file 'mysql-test/suite/rpl/r/rpl_loaddata_charset.result'
--- a/mysql-test/suite/rpl/r/rpl_loaddata_charset.result 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/rpl/r/rpl_loaddata_charset.result 2009-08-12 05:31:56 +0000
@@ -35,3 +35,44 @@ C3BF
D0AA
D0AA
drop table t1;
+-------------test bug#45516------------------
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest CHARSET UTF8;
+USE mysqltest;
+CREATE TABLE t (cl varchar(100)) CHARSET UTF8;
+LOAD DATA LOCAL INFILE './std_data/loaddata_utf8.dat' INTO TABLE t
+FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
+----------content on master----------
+SELECT hex(cl) FROM t;
+hex(cl)
+E4B880E4BA8CE4B889
+E59B9BE4BA94E585AD
+E4B883E585ABE4B99D
+----------content on slave----------
+USE mysqltest;
+SELECT hex(cl) FROM t;
+hex(cl)
+E4B880E4BA8CE4B889
+E59B9BE4BA94E585AD
+E4B883E585ABE4B99D
+DROP DATABASE mysqltest;
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest CHARSET UTF8;
+USE mysqltest;
+CREATE TABLE t (cl varchar(100)) CHARSET UTF8;
+LOAD DATA INFILE '../../std_data/loaddata_utf8.dat' INTO TABLE t
+FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
+----------content on master----------
+SELECT hex(cl) FROM t;
+hex(cl)
+E4B880E4BA8CE4B889
+E59B9BE4BA94E585AD
+E4B883E585ABE4B99D
+----------content on slave----------
+USE mysqltest;
+SELECT hex(cl) FROM t;
+hex(cl)
+E4B880E4BA8CE4B889
+E59B9BE4BA94E585AD
+E4B883E585ABE4B99D
+DROP DATABASE mysqltest;
=== modified file 'mysql-test/suite/rpl/r/rpl_rewrt_db.result'
--- a/mysql-test/suite/rpl/r/rpl_rewrt_db.result 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/rpl/r/rpl_rewrt_db.result 2009-08-28 09:45:57 +0000
@@ -90,5 +90,132 @@ a b
2 row 2
3 row 3
0
+set sql_log_bin= 0;
drop database rewrite;
+set sql_log_bin= 1;
+set sql_log_bin= 0;
drop table t1;
+set sql_log_bin= 1;
+
+****
+**** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db
+****
+
+****
+**** Preparing the environment
+****
+SET sql_log_bin= 0;
+CREATE DATABASE database_master_temp_01;
+CREATE DATABASE database_master_temp_02;
+CREATE DATABASE database_master_temp_03;
+SET sql_log_bin= 1;
+SET sql_log_bin= 0;
+CREATE DATABASE database_slave_temp_01;
+CREATE DATABASE database_slave_temp_02;
+CREATE DATABASE database_slave_temp_03;
+SET sql_log_bin= 1;
+
+****
+**** Creating temporary tables on different databases with different connections
+****
+**** con_temp_01 --> creates
+**** t_01_01_temp on database_master_temp_01
+****
+**** con_temp_02 --> creates
+**** t_01_01_temp on database_master_temp_01
+**** t_02_01_temp, t_02_02_temp on database_master_temp_02
+****
+**** con_temp_02 --> creates
+**** t_01_01_temp on database_master_temp_01
+**** t_02_01_temp, t_02_02_temp on database_master_temp_02
+**** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03
+****
+
+con_temp_01
+
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+
+con_temp_02
+
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+USE database_master_temp_02;
+CREATE TEMPORARY TABLE t_02_01_temp(a int);
+INSERT INTO t_02_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_02_02_temp(a int);
+INSERT INTO t_02_02_temp VALUES(1);
+
+con_temp_03
+
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+USE database_master_temp_02;
+CREATE TEMPORARY TABLE t_02_01_temp(a int);
+INSERT INTO t_02_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_02_02_temp(a int);
+INSERT INTO t_02_02_temp VALUES(1);
+USE database_master_temp_03;
+CREATE TEMPORARY TABLE t_03_01_temp(a int);
+INSERT INTO t_03_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_03_02_temp(a int);
+INSERT INTO t_03_02_temp VALUES(1);
+CREATE TEMPORARY TABLE t_03_03_temp(a int);
+INSERT INTO t_03_03_temp VALUES(1);
+
+**** Dropping the connections
+**** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no
+**** guarantee that logging of the terminated con1 has been done yet.a To be
+**** sure that logging has been done, we use a user lock.
+
+show status like 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 10
+select get_lock("con_01",10);
+get_lock("con_01",10)
+1
+select get_lock("con_01",10);
+get_lock("con_01",10)
+1
+select get_lock("con_02",10);
+get_lock("con_02",10)
+1
+select get_lock("con_02",10);
+get_lock("con_02",10)
+1
+select get_lock("con_03",10);
+get_lock("con_03",10)
+1
+select get_lock("con_03",10);
+get_lock("con_03",10)
+1
+
+**** Checking the binary log and temporary tables
+
+show status like 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 0
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp`
+master-bin.000001 # Query # # use `database_master_temp_02`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_02_02_temp`,`t_02_01_temp`
+master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp`
+master-bin.000001 # Query # # use `database_master_temp_03`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_03_03_temp`,`t_03_02_temp`,`t_03_01_temp`
+master-bin.000001 # Query # # use `database_master_temp_02`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_02_02_temp`,`t_02_01_temp`
+master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp`
+****
+**** Cleaning up the test case
+****
+SET sql_log_bin= 0;
+DROP DATABASE database_master_temp_01;
+DROP DATABASE database_master_temp_02;
+DROP DATABASE database_master_temp_03;
+SET sql_log_bin= 1;
+SET sql_log_bin= 0;
+DROP DATABASE database_slave_temp_01;
+DROP DATABASE database_slave_temp_02;
+DROP DATABASE database_slave_temp_03;
+SET sql_log_bin= 1;
=== added file 'mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result'
--- a/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result 2009-08-27 12:46:29 +0000
@@ -0,0 +1,870 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+###################################################################################
+# CONFIGURATION
+###################################################################################
+SET SQL_LOG_BIN=0;
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb;
+SET SQL_LOG_BIN=1;
+CREATE FUNCTION f1 () RETURNS VARCHAR(64)
+BEGIN
+RETURN "Testing...";
+END|
+CREATE FUNCTION f2 () RETURNS VARCHAR(64)
+BEGIN
+RETURN f1();
+END|
+CREATE PROCEDURE pc_i_tt_3 (IN x INT, IN y VARCHAR(64))
+BEGIN
+INSERT INTO tt_3 VALUES (y,x,x);
+END|
+CREATE TRIGGER tr_i_tt_3_to_nt_3 BEFORE INSERT ON tt_3 FOR EACH ROW
+BEGIN
+INSERT INTO nt_3 VALUES (NEW.a, NEW.b, NEW.c);
+END|
+CREATE TRIGGER tr_i_nt_4_to_tt_4 BEFORE INSERT ON nt_4 FOR EACH ROW
+BEGIN
+INSERT INTO tt_4 VALUES (NEW.a, NEW.b, NEW.c);
+END|
+###################################################################################
+# MIXING TRANSACTIONAL and NON-TRANSACTIONAL TABLES
+###################################################################################
+#
+#1) "B T T C" generates in binlog the "B T T C" entries.
+#
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 4", 4, "new text 4");
+INSERT INTO tt_2 VALUES ("new text 4", 4, "new text 4");
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 4", 4, "new text 4")
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 4", 4, "new text 4")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#1.e) "B T T C" with error in T generates in binlog the "B T T C" entries.
+#
+INSERT INTO tt_1 VALUES ("new text -2", -2, "new text -2");
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -2", -2, "new text -2");
+ERROR 23000: Duplicate entry '-2' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text -3", -3, "new text -3");
+COMMIT;
+BEGIN;
+INSERT INTO tt_2 VALUES ("new text -5", -5, "new text -5");
+INSERT INTO tt_2 VALUES ("new text -4", -4, "new text -4"), ("new text -5", -5, "new text -5");
+ERROR 23000: Duplicate entry '-5' for key 'PRIMARY'
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -2", -2, "new text -2")
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text -3", -3, "new text -3")
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text -5", -5, "new text -5")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#2) "B T T R" generates in binlog an "empty" entry.
+#
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 5", 5, "new text 5");
+INSERT INTO tt_2 VALUES ("new text 5", 5, "new text 5");
+ROLLBACK;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+
+
+
+
+#
+#2.e) "B T T R" with error in T generates in binlog an "empty" entry.
+#
+INSERT INTO tt_1 VALUES ("new text -7", -7, "new text -7");
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -6", -6, "new text -6"), ("new text -7", -7, "new text -7");
+ERROR 23000: Duplicate entry '-7' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text -8", -8, "new text -8");
+ROLLBACK;
+BEGIN;
+INSERT INTO tt_2 VALUES ("new text -10", -10, "new text -10");
+INSERT INTO tt_2 VALUES ("new text -9", -9, "new text -9"), ("new text -10", -10, "new text -10");
+ERROR 23000: Duplicate entry '-10' for key 'PRIMARY'
+ROLLBACK;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -7", -7, "new text -7")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#3) "B T N C" generates in binlog the "B T N C" entries.
+#
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 6", 6, "new text 6");
+INSERT INTO nt_1 VALUES ("new text 6", 6, "new text 6");
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 6", 6, "new text 6")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 6", 6, "new text 6")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#3.e) "B T N C" with error in either T or N generates in binlog the "B T N C" entries.
+#
+INSERT INTO tt_1 VALUES ("new text -12", -12, "new text -12");
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -11", -11, "new text -11"), ("new text -12", -12, "new text -12");
+ERROR 23000: Duplicate entry '-12' for key 'PRIMARY'
+INSERT INTO nt_1 VALUES ("new text -13", -13, "new text -13");
+COMMIT;
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -14", -14, "new text -14");
+INSERT INTO nt_1 VALUES ("new text -16", -16, "new text -16");
+INSERT INTO nt_1 VALUES ("new text -15", -15, "new text -15"), ("new text -16", -16, "new text -16");
+ERROR 23000: Duplicate entry '-16' for key 'PRIMARY'
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -12", -12, "new text -12")
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -13", -13, "new text -13")
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -14", -14, "new text -14")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -16", -16, "new text -16")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -15", -15, "new text -15"), ("new text -16", -16, "new text -16")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#4) "B T N R" generates in binlog the "B T N R" entries.
+#
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 7", 7, "new text 7");
+INSERT INTO nt_1 VALUES ("new text 7", 7, "new text 7");
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 7", 7, "new text 7")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 7", 7, "new text 7")
+master-bin.000001 # Query # # ROLLBACK
+
+
+
+
+#
+#4.e) "B T N R" with error in either T or N generates in binlog the "B T N R" entries.
+#
+INSERT INTO tt_1 VALUES ("new text -17", -17, "new text -17");
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -16", -16, "new text -16"), ("new text -17", -17, "new text -17");
+ERROR 23000: Duplicate entry '-17' for key 'PRIMARY'
+INSERT INTO nt_1 VALUES ("new text -18", -18, "new text -18");
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text -19", -19, "new text -19");
+INSERT INTO nt_1 VALUES ("new text -21", -21, "new text -21");
+INSERT INTO nt_1 VALUES ("new text -20", -20, "new text -20"), ("new text -21", -21, "new text -21");
+ERROR 23000: Duplicate entry '-21' for key 'PRIMARY'
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -17", -17, "new text -17")
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -18", -18, "new text -18")
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -19", -19, "new text -19")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -21", -21, "new text -21")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -20", -20, "new text -20"), ("new text -21", -21, "new text -21")
+master-bin.000001 # Query # # ROLLBACK
+
+
+
+
+#
+#5) "T" generates in binlog the "B T C" entry.
+#
+INSERT INTO tt_1 VALUES ("new text 8", 8, "new text 8");
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 8", 8, "new text 8")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#5.e) "T" with error in T generates in binlog an "empty" entry.
+#
+INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1");
+INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -22", -22, "new text -22");
+ERROR 23000: Duplicate entry '-1' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text -23", -23, "new text -23"), ("new text -1", -1, "new text -1");
+ERROR 23000: Duplicate entry '-1' for key 'PRIMARY'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#6) "N" generates in binlog the "N" entry.
+#
+INSERT INTO nt_1 VALUES ("new text 9", 9, "new text 9");
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 9", 9, "new text 9")
+
+
+
+
+#
+#6.e) "N" with error in N generates in binlog an empty entry if the error
+# happens in the first tuple. Otherwise, generates the "N" entry and
+# the error is appended.
+#
+INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1");
+INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1");
+ERROR 23000: Duplicate entry '-1' for key 'PRIMARY'
+INSERT INTO nt_1 VALUES ("new text -24", -24, "new text -24"), ("new text -1", -1, "new text -1");
+ERROR 23000: Duplicate entry '-1' for key 'PRIMARY'
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -24", -24, "new text -24"), ("new text -1", -1, "new text -1")
+
+
+
+
+#
+#7) "M" generates in binglog the "B M C" entries.
+#
+DELETE FROM nt_1;
+INSERT INTO nt_1 SELECT * FROM tt_1;
+DELETE FROM tt_1;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+INSERT INTO tt_3 VALUES ("new text 000", 000, '');
+INSERT INTO tt_3 VALUES("new text 100", 100, f1());
+INSERT INTO nt_4 VALUES("new text 100", 100, f1());
+INSERT INTO tt_3 VALUES("new text 200", 200, f2());
+INSERT INTO nt_4 VALUES ("new text 300", 300, '');
+INSERT INTO nt_4 VALUES ("new text 400", 400, f1());
+INSERT INTO nt_4 VALUES ("new text 500", 500, f2());
+CALL pc_i_tt_3(600, "Testing...");
+UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 1", nt_4.a= "new text 1", tt_3.a= "new text 1", tt_4.a= "new text 1" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 2", tt_4.a= "new text 2", nt_3.a= "new text 2", nt_4.a = "new text 2" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 3", nt_3.a= "new text 3", nt_4.a= "new text 3", tt_4.a = "new text 3" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 4", nt_3.a= "new text 4", nt_4.a= "new text 4", tt_4.a = "new text 4" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; DELETE FROM nt_1
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 SELECT * FROM tt_1
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; DELETE FROM tt_1
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 SELECT * FROM nt_1
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text 000", 000, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 100", 100, f1())
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 100", 100, f1())
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 200", 200, f2())
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 300", 300, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 400", 400, f1())
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 500", 500, f2())
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ( NAME_CONST('y',_latin1'Testing...' COLLATE 'latin1_swedish_ci'), NAME_CONST('x',600), NAME_CONST('x',600))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 1", nt_4.a= "new text 1", tt_3.a= "new text 1", tt_4.a= "new text 1" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 2", tt_4.a= "new text 2", nt_3.a= "new text 2", nt_4.a = "new text 2" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 3", nt_3.a= "new text 3", nt_4.a= "new text 3", tt_4.a = "new text 3" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 4", nt_3.a= "new text 4", nt_4.a= "new text 4", tt_4.a = "new text 4" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#7.e) "M" with error in M generates in binglog the "B M R" entries.
+#
+INSERT INTO nt_3 VALUES ("new text -26", -26, '');
+SELECT * FROM tt_3;
+a b c
+new text 000 0
+new text 4 100 Testing...
+new text 200 200 Testing...
+Testing... 600 600
+INSERT INTO tt_3 VALUES ("new text -25", -25, ''), ("new text -26", -26, '');
+ERROR 23000: Duplicate entry '-26' for key 'PRIMARY'
+SELECT * FROM tt_3;
+a b c
+new text 000 0
+new text 4 100 Testing...
+new text 200 200 Testing...
+Testing... 600 600
+INSERT INTO tt_4 VALUES ("new text -26", -26, '');
+SELECT * FROM nt_4;
+a b c
+new text 4 100 Testing...
+new text 300 300
+new text 400 400 Testing...
+new text 500 500 Testing...
+INSERT INTO nt_4 VALUES ("new text -25", -25, ''), ("new text -26", -26, '');
+ERROR 23000: Duplicate entry '-26' for key 'PRIMARY'
+SELECT * FROM nt_4;
+a b c
+new text 4 100 Testing...
+new text 300 300
+new text 400 400 Testing...
+new text 500 500 Testing...
+new text -25 -25
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_3 VALUES ("new text -26", -26, '')
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text -25", -25, ''), ("new text -26", -26, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -26", -26, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -25", -25, ''), ("new text -26", -26, '')
+master-bin.000001 # Query # # ROLLBACK
+
+
+
+
+#
+#8) "B N N T C" generates in binglog the "N N B T C" entries.
+#
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 10", 10, "new text 10");
+INSERT INTO nt_2 VALUES ("new text 10", 10, "new text 10");
+INSERT INTO tt_1 VALUES ("new text 10", 10, "new text 10");
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 10", 10, "new text 10")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 10", 10, "new text 10")
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 10", 10, "new text 10")
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#8.e) "B N N T R" See 6.e and 9.e.
+#
+
+
+
+
+#
+#9) "B N N T R" generates in binlog the "N N B T R" entries.
+#
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 11", 11, "new text 11");
+INSERT INTO nt_2 VALUES ("new text 11", 11, "new text 11");
+INSERT INTO tt_1 VALUES ("new text 11", 11, "new text 11");
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 11", 11, "new text 11")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 11", 11, "new text 11")
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 11", 11, "new text 11")
+master-bin.000001 # Query # # ROLLBACK
+
+
+
+
+#
+#9.e) "B N N T R" with error in N generates in binlog the "N N B T R" entries.
+#
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text -25", -25, "new text -25");
+INSERT INTO nt_2 VALUES ("new text -25", -25, "new text -25");
+INSERT INTO nt_2 VALUES ("new text -26", -26, "new text -26"), ("new text -25", -25, "new text -25");
+ERROR 23000: Duplicate entry '-25' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text -27", -27, "new text -27");
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -25", -25, "new text -25")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text -25", -25, "new text -25")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text -26", -26, "new text -26"), ("new text -25", -25, "new text -25")
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -27", -27, "new text -27")
+master-bin.000001 # Query # # ROLLBACK
+
+
+
+
+#
+#10) "B N N C" generates in binglog the "N N" entries.
+#
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 12", 12, "new text 12");
+INSERT INTO nt_2 VALUES ("new text 12", 12, "new text 12");
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 12", 12, "new text 12")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 12", 12, "new text 12")
+
+
+
+
+#
+#10.e) "B N N C" See 6.e and 9.e.
+#
+
+
+
+
+#
+#11) "B N N R" generates in binlog the "N N" entries.
+#
+BEGIN;
+INSERT INTO nt_1 VALUES ("new text 13", 13, "new text 13");
+INSERT INTO nt_2 VALUES ("new text 13", 13, "new text 13");
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 13", 13, "new text 13")
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 13", 13, "new text 13")
+
+
+
+
+#
+#11.e) "B N N R" See 6.e and 9.e.
+#
+
+
+
+
+#
+#12) "B M T C" generates in the binlog the "B M T C" entries.
+#
+DELETE FROM nt_1;
+BEGIN;
+INSERT INTO nt_1 SELECT * FROM tt_1;
+INSERT INTO tt_2 VALUES ("new text 14", 14, "new text 14");
+COMMIT;
+DELETE FROM tt_1;
+BEGIN;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+INSERT INTO tt_2 VALUES ("new text 15", 15, "new text 15");
+COMMIT;
+BEGIN;
+INSERT INTO tt_3 VALUES ("new text 700", 700, '');
+INSERT INTO tt_1 VALUES ("new text 800", 800, '');
+COMMIT;
+BEGIN;
+INSERT INTO tt_3 VALUES("new text 900", 900, f1());
+INSERT INTO tt_1 VALUES ("new text 1000", 1000, '');
+COMMIT;
+BEGIN;
+INSERT INTO tt_3 VALUES(1100, 1100, f2());
+INSERT INTO tt_1 VALUES ("new text 1200", 1200, '');
+COMMIT;
+BEGIN;
+INSERT INTO nt_4 VALUES ("new text 1300", 1300, '');
+INSERT INTO tt_1 VALUES ("new text 1400", 1400, '');
+COMMIT;
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 1500", 1500, f1());
+INSERT INTO tt_1 VALUES ("new text 1600", 1600, '');
+COMMIT;
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 1700", 1700, f2());
+INSERT INTO tt_1 VALUES ("new text 1800", 1800, '');
+COMMIT;
+BEGIN;
+CALL pc_i_tt_3(1900, "Testing...");
+INSERT INTO tt_1 VALUES ("new text 2000", 2000, '');
+COMMIT;
+BEGIN;
+UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 5", nt_4.a= "new text 5", tt_3.a= "new text 5", tt_4.a= "new text 5" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2100", 2100, '');
+COMMIT;
+BEGIN;
+UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 6", tt_4.a= "new text 6", nt_3.a= "new text 6", nt_4.a = "new text 6" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2200", 2200, '');
+COMMIT;
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 7", nt_3.a= "new text 7", nt_4.a= "new text 7", tt_4.a = "new text 7" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2300", 2300, '');
+COMMIT;
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 8", nt_3.a= "new text 8", nt_4.a= "new text 8", tt_4.a = "new text 8" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 2400", 2400, '');
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; DELETE FROM nt_1
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 SELECT * FROM tt_1
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 14", 14, "new text 14")
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; DELETE FROM tt_1
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 SELECT * FROM nt_1
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 15", 15, "new text 15")
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text 700", 700, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 800", 800, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 900", 900, f1())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1000", 1000, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES(1100, 1100, f2())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1200", 1200, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 1300", 1300, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1400", 1400, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 1500", 1500, f1())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1600", 1600, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 1700", 1700, f2())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1800", 1800, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ( NAME_CONST('y',_latin1'Testing...' COLLATE 'latin1_swedish_ci'), NAME_CONST('x',1900), NAME_CONST('x',1900))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2000", 2000, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 5", nt_4.a= "new text 5", tt_3.a= "new text 5", tt_4.a= "new text 5" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2100", 2100, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 6", tt_4.a= "new text 6", nt_3.a= "new text 6", nt_4.a = "new text 6" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2200", 2200, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 7", nt_3.a= "new text 7", nt_4.a= "new text 7", tt_4.a = "new text 7" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2300", 2300, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 8", nt_3.a= "new text 8", nt_4.a= "new text 8", tt_4.a = "new text 8" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2400", 2400, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#12.e) "B M T C" with error in M generates in the binlog the "B M T C" entries.
+#
+# There is a bug in the slave that needs to be fixed before enabling
+# this part of the test. A bug report will be filed referencing this
+# test case.
+BEGIN;
+INSERT INTO nt_3 VALUES ("new text -28", -28, '');
+INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, '');
+ERROR 23000: Duplicate entry '-28' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text -27", -27, '');
+COMMIT;
+BEGIN;
+INSERT INTO tt_4 VALUES ("new text -28", -28, '');
+INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, '');
+ERROR 23000: Duplicate entry '-28' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text -28", -28, '');
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_3 VALUES ("new text -28", -28, '')
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -27", -27, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -28", -28, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -28", -28, '')
+master-bin.000001 # Xid # # COMMIT /* XID */
+
+
+
+
+#
+#13) "B M T R" generates in the binlog the "B M T R" entries
+#
+DELETE FROM nt_1;
+BEGIN;
+INSERT INTO nt_1 SELECT * FROM tt_1;
+INSERT INTO tt_2 VALUES ("new text 17", 17, "new text 17");
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+DELETE FROM tt_1;
+BEGIN;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+INSERT INTO tt_2 VALUES ("new text 18", 18, "new text 18");
+ROLLBACK;
+INSERT INTO tt_1 SELECT * FROM nt_1;
+BEGIN;
+INSERT INTO tt_3 VALUES ("new text 2500", 2500, '');
+INSERT INTO tt_1 VALUES ("new text 2600", 2600, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO tt_3 VALUES("new text 2700", 2700, f1());
+INSERT INTO tt_1 VALUES ("new text 2800", 2800, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO tt_3 VALUES(2900, 2900, f2());
+INSERT INTO tt_1 VALUES ("new text 3000", 3000, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO nt_4 VALUES ("new text 3100", 3100, '');
+INSERT INTO tt_1 VALUES ("new text 3200", 3200, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 3300", 3300, f1());
+INSERT INTO tt_1 VALUES ("new text 3400", 3400, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO nt_4 VALUES("new text 3500", 3500, f2());
+INSERT INTO tt_1 VALUES ("new text 3600", 3600, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+CALL pc_i_tt_3(3700, "Testing...");
+INSERT INTO tt_1 VALUES ("new text 3700", 3700, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 9", nt_4.a= "new text 9", tt_3.a= "new text 9", tt_4.a= "new text 9" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 3800", 3800, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 10", tt_4.a= "new text 10", nt_3.a= "new text 10", nt_4.a = "new text 10" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 3900", 3900, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 11", nt_3.a= "new text 11", nt_4.a= "new text 11", tt_4.a = "new text 11" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 4000", 4000, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 12", nt_3.a= "new text 12", nt_4.a= "new text 12", tt_4.a = "new text 12" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100;
+INSERT INTO tt_1 VALUES ("new text 4100", 4100, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; DELETE FROM nt_1
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 SELECT * FROM tt_1
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 17", 17, "new text 17")
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; DELETE FROM tt_1
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 SELECT * FROM nt_1
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text 2500", 2500, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2600", 2600, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 2700", 2700, f1())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2800", 2800, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES(2900, 2900, f2())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3000", 3000, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 3100", 3100, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3200", 3200, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 3300", 3300, f1())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3400", 3400, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 3500", 3500, f2())
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3600", 3600, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ( NAME_CONST('y',_latin1'Testing...' COLLATE 'latin1_swedish_ci'), NAME_CONST('x',3700), NAME_CONST('x',3700))
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3700", 3700, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 9", nt_4.a= "new text 9", tt_3.a= "new text 9", tt_4.a= "new text 9" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3800", 3800, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 10", tt_4.a= "new text 10", nt_3.a= "new text 10", nt_4.a = "new text 10" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3900", 3900, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 11", nt_3.a= "new text 11", nt_4.a= "new text 11", tt_4.a = "new text 11" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 4000", 4000, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 12", nt_3.a= "new text 12", nt_4.a= "new text 12", tt_4.a = "new text 12" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 4100", 4100, '')
+master-bin.000001 # Query # # ROLLBACK
+
+
+
+
+#
+#13.e) "B M T R" with error in M generates in the binlog the "B M T R" entries.
+#
+BEGIN;
+INSERT INTO nt_3 VALUES ("new text -30", -30, '');
+INSERT INTO tt_3 VALUES ("new text -29", -29, ''), ("new text -30", -30, '');
+ERROR 23000: Duplicate entry '-30' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text -30", -30, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+BEGIN;
+INSERT INTO tt_4 VALUES ("new text -30", -30, '');
+INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, '');
+ERROR 23000: Duplicate entry '-30' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text -31", -31, '');
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_3 VALUES ("new text -30", -30, '')
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text -29", -29, ''), ("new text -30", -30, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -30", -30, '')
+master-bin.000001 # Query # # ROLLBACK
+master-bin.000001 # Query # # BEGIN
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -30", -30, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, '')
+master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -31", -31, '')
+master-bin.000001 # Query # # ROLLBACK
+###################################################################################
+# CLEAN
+###################################################################################
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE tt_3;
+DROP TABLE tt_4;
+DROP TABLE nt_1;
+DROP TABLE nt_2;
+DROP TABLE nt_3;
+DROP TABLE nt_4;
+DROP PROCEDURE pc_i_tt_3;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
=== modified file 'mysql-test/suite/rpl/t/rpl_concurrency_error.test'
--- a/mysql-test/suite/rpl/t/rpl_concurrency_error.test 2009-07-18 20:07:56 +0000
+++ b/mysql-test/suite/rpl/t/rpl_concurrency_error.test 2009-08-13 16:21:01 +0000
@@ -125,14 +125,13 @@ while ($type)
connection master;
sync_slave_with_master;
-# Re-enable this after fixing BUG#46130
-#connection master;
-#let $diff_statement= SELECT * FROM t order by i;
-#source include/diff_master_slave.inc;
-
-#connection master;
-#let $diff_statement= SELECT * FROM n order by d, f;
-#source include/diff_master_slave.inc;
+connection master;
+let $diff_statement= SELECT * FROM t order by i;
+source include/diff_master_slave.inc;
+
+connection master;
+let $diff_statement= SELECT * FROM n order by d, f;
+source include/diff_master_slave.inc;
--echo ########################################################################
--echo # Cleanup
=== added file 'mysql-test/suite/rpl/t/rpl_create_if_not_exists.test'
--- a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test 2009-08-13 02:48:57 +0000
@@ -0,0 +1,70 @@
+# BUG#45574:
+# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists.
+#
+# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and
+# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are
+# binlogged even if either the DB, TABLE or EVENT does not exist. In
+# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT
+# exists.
+#
+# This problem caused some of the tests to fail randomly on PB or PB2.
+#
+# Description:
+# Fixed this bug by adding calls to write_bin_log in:
+# mysql_create_db
+# mysql_create_table_no_lock
+# mysql_create_like_table
+# create_table_from_items
+#
+# Test is implemented as follows:
+# i) test each "CREATE IF NOT EXISTS" (DDL), found in MySQL 5.1 manual
+# exclude CREATE TEMPORARY TABLE, on existent objects;
+#
+# Note:
+# rpl_create_tmp_table_if_not_exists.test tests CREATE TEMPORARY TABLE cases.
+#
+# References:
+# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html
+#
+
+source include/master-slave.inc;
+disable_warnings;
+DROP DATABASE IF EXISTS mysqltest;
+
+CREATE DATABASE IF NOT EXISTS mysqltest;
+USE mysqltest;
+CREATE TABLE IF NOT EXISTS t(c1 int);
+CREATE TABLE IF NOT EXISTS t1 LIKE t;
+CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
+CREATE EVENT IF NOT EXISTS e
+ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+DO SELECT now();
+sync_slave_with_master;
+
+connection slave;
+#DROP database from slave.
+#The database and all tables can be recreated in slave
+#if binlog of the second CREATE command is recorded and sent from master to slave.
+DROP DATABASE mysqltest;
+
+connection master;
+CREATE DATABASE IF NOT EXISTS mysqltest;
+USE mysqltest;
+CREATE TABLE IF NOT EXISTS t(c1 int);
+CREATE TABLE IF NOT EXISTS t1 LIKE t;
+CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
+CREATE EVENT IF NOT EXISTS e
+ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
+DO SELECT now();
+sync_slave_with_master;
+
+connection slave;
+SHOW TABLES in mysqltest;
+#Execution time changes in each run. So we disregard it by calling replace_column.
+replace_column 6 #;
+SHOW EVENTS in mysqltest;
+
+
+connection master;
+DROP DATABASE IF EXISTS mysqltest;
+source include/master-slave-end.inc;
=== added file 'mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test'
--- a/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test 2009-08-13 02:48:57 +0000
@@ -0,0 +1,41 @@
+# BUG#45574:
+# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists.
+#
+# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and
+# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are
+# binlogged even if either the DB, TABLE or EVENT does not exist. In
+# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT
+# exists.
+#
+# This problem caused some of the tests to fail randomly on PB or PB2.
+#
+# Test is implemented as follows:
+#
+# i) test each "CREATE TEMPORARY TABLE IF EXISTS" (DDL), found in MySQL
+# 5.1 manual, on existent objects;
+# ii) show binlog events;
+#
+# Note:
+# rpl_create_if_not_exists.test tests other cases.
+#
+# References:
+# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html
+#
+
+source include/master-slave.inc;
+#CREATE TEMPORARY TABLE statements are not binlogged in row mode,
+#So it must be test by itself.
+source include/have_binlog_format_mixed_or_statement.inc;
+disable_warnings;
+
+DROP DATABASE IF EXISTS mysqltest;
+
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int);
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int);
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp;
+source include/show_binlog_events.inc;
+
+source include/master-slave-end.inc;
=== modified file 'mysql-test/suite/rpl/t/rpl_drop_temp.test'
--- a/mysql-test/suite/rpl/t/rpl_drop_temp.test 2008-02-29 21:05:23 +0000
+++ b/mysql-test/suite/rpl/t/rpl_drop_temp.test 2009-08-28 09:45:57 +0000
@@ -12,21 +12,23 @@ source include/have_binlog_format_mixed_
create database if not exists mysqltest;
--enable_warnings
+connect (con_temp,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+connection con_temp;
+use mysqltest;
create temporary table mysqltest.t1 (n int)ENGINE=MyISAM;
create temporary table mysqltest.t2 (n int)ENGINE=MyISAM;
-connection master;
-disconnect master;
-
-connection master1;
-# Wait until drop of temp tables appears in binlog
-let $wait_binlog_event= DROP;
-source include/wait_for_binlog_event.inc;
+disconnect con_temp;
+--source include/wait_until_disconnected.inc
+connection master;
sync_slave_with_master;
+
+connection slave;
show status like 'Slave_open_temp_tables';
# Cleanup
-connection default;
+connection master;
drop database mysqltest;
sync_slave_with_master;
=== modified file 'mysql-test/suite/rpl/t/rpl_events.test'
--- a/mysql-test/suite/rpl/t/rpl_events.test 2009-01-30 13:44:49 +0000
+++ b/mysql-test/suite/rpl/t/rpl_events.test 2009-08-31 02:26:01 +0000
@@ -46,12 +46,62 @@ connection master;
DROP EVENT event2;
-sync_slave_with_master;
+#
+# BUG#44331
+# This test verifies if the definer is consistent between master and slave,
+# when the event is created without the DEFINER clause set explicitly or the
+# DEFINER is set to CURRENT_USER
+#
+CREATE TABLE test.t1(details CHAR(30));
+
+CREATE EVENT /*!50000 event44331_1 */
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_1 fired - no definer');
+
+CREATE DEFINER=CURRENT_USER /*!50000 EVENT event44331_2 */
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_2 fired - DEFINER=CURRENT_USER');
+
+CREATE DEFINER=CURRENT_USER() EVENT event44331_3
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_3 fired - DEFINER=CURRENT_USER() function');
-# Doing cleanup of the table referred to in the event to guarantee
-# that there is no bad timing cauing it to try to access the table.
+CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4
+ ON SCHEDULE AT CURRENT_TIMESTAMP
+ ON COMPLETION PRESERVE DISABLE
+ DO INSERT INTO test.t1 VALUES('event event44331_4 fired - DEFINER=user1');
+
+--echo #on master
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_1';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_2';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_3';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_4';
+
+sync_slave_with_master;
+connection slave;
+--echo #on slave
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_1';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_2';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_3';
+select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events
+ where EVENT_NAME='event44331_4';
connection master;
SET @@global.event_scheduler= @old_event_scheduler;
DROP TABLE t28953;
+DROP TABLE t1;
+DROP EVENT event44331_1;
+DROP EVENT event44331_2;
+DROP EVENT event44331_3;
+DROP EVENT event44331_4;
sync_slave_with_master;
=== modified file 'mysql-test/suite/rpl/t/rpl_loaddata_charset.test'
--- a/mysql-test/suite/rpl/t/rpl_loaddata_charset.test 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/rpl/t/rpl_loaddata_charset.test 2009-08-12 05:31:56 +0000
@@ -31,3 +31,20 @@ select hex(a) from t1;
connection master;
drop table t1;
sync_slave_with_master;
+
+#
+# Bug#45516
+# When slave SQL thread executing LOAD DATA command, the
+# thd->variables.collation_database was not set properly to the default
+# database charset
+#
+
+echo -------------test bug#45516------------------;
+
+# LOAD DATA INFILE
+let $LOAD_LOCAL=1;
+source include/rpl_loaddata_charset.inc;
+
+# LOAD DATA LOCAL INFILE
+let $LOAD_LOCAL=0;
+source include/rpl_loaddata_charset.inc;
=== modified file 'mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt'
--- a/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt 2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt 2009-08-28 09:45:57 +0000
@@ -1 +1 @@
-"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test"
+"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test" "--replicate-rewrite-db=database_master_temp_01->database_slave_temp_01" "--replicate-rewrite-db=database_master_temp_02->database_slave_temp_02" "--replicate-rewrite-db=database_master_temp_03->database_slave_temp_03"
=== modified file 'mysql-test/suite/rpl/t/rpl_rewrt_db.test'
--- a/mysql-test/suite/rpl/t/rpl_rewrt_db.test 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/rpl/t/rpl_rewrt_db.test 2009-08-28 09:45:57 +0000
@@ -76,9 +76,164 @@ connection slave;
# The empty line last comes from the end line field in the file
select * from rewrite.t1;
+set sql_log_bin= 0;
drop database rewrite;
+set sql_log_bin= 1;
connection master;
+set sql_log_bin= 0;
drop table t1;
+set sql_log_bin= 1;
# End of 4.1 tests
+
+--echo
+--echo ****
+--echo **** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db
+--echo ****
+--echo
+
+--echo ****
+--echo **** Preparing the environment
+--echo ****
+connection master;
+
+connect (con_temp_03,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (con_temp_02,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (con_temp_01,127.0.0.1,root,,test,$MASTER_MYPORT,);
+
+connection master;
+SET sql_log_bin= 0;
+CREATE DATABASE database_master_temp_01;
+CREATE DATABASE database_master_temp_02;
+CREATE DATABASE database_master_temp_03;
+SET sql_log_bin= 1;
+
+connection slave;
+SET sql_log_bin= 0;
+CREATE DATABASE database_slave_temp_01;
+CREATE DATABASE database_slave_temp_02;
+CREATE DATABASE database_slave_temp_03;
+SET sql_log_bin= 1;
+
+--echo
+--echo ****
+--echo **** Creating temporary tables on different databases with different connections
+--echo ****
+--echo **** con_temp_01 --> creates
+--echo **** t_01_01_temp on database_master_temp_01
+--echo ****
+--echo **** con_temp_02 --> creates
+--echo **** t_01_01_temp on database_master_temp_01
+--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02
+--echo ****
+--echo **** con_temp_02 --> creates
+--echo **** t_01_01_temp on database_master_temp_01
+--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02
+--echo **** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03
+--echo ****
+
+--echo
+--echo con_temp_01
+--echo
+connection con_temp_01;
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+
+--echo
+--echo con_temp_02
+--echo
+connection con_temp_02;
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+USE database_master_temp_02;
+CREATE TEMPORARY TABLE t_02_01_temp(a int);
+INSERT INTO t_02_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_02_02_temp(a int);
+INSERT INTO t_02_02_temp VALUES(1);
+
+--echo
+--echo con_temp_03
+--echo
+connection con_temp_03;
+USE database_master_temp_01;
+CREATE TEMPORARY TABLE t_01_01_temp(a int);
+INSERT INTO t_01_01_temp VALUES(1);
+USE database_master_temp_02;
+CREATE TEMPORARY TABLE t_02_01_temp(a int);
+INSERT INTO t_02_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_02_02_temp(a int);
+INSERT INTO t_02_02_temp VALUES(1);
+USE database_master_temp_03;
+CREATE TEMPORARY TABLE t_03_01_temp(a int);
+INSERT INTO t_03_01_temp VALUES(1);
+CREATE TEMPORARY TABLE t_03_02_temp(a int);
+INSERT INTO t_03_02_temp VALUES(1);
+CREATE TEMPORARY TABLE t_03_03_temp(a int);
+INSERT INTO t_03_03_temp VALUES(1);
+
+--echo
+--echo **** Dropping the connections
+--echo **** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no
+--echo **** guarantee that logging of the terminated con1 has been done yet.a To be
+--echo **** sure that logging has been done, we use a user lock.
+--echo
+connection master;
+sync_slave_with_master;
+connection slave;
+show status like 'Slave_open_temp_tables';
+
+connection master;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+connection con_temp_01;
+select get_lock("con_01",10);
+connection master;
+disconnect con_temp_01;
+select get_lock("con_01",10);
+
+connection con_temp_02;
+select get_lock("con_02",10);
+connection master;
+disconnect con_temp_02;
+select get_lock("con_02",10);
+
+connection con_temp_03;
+select get_lock("con_03",10);
+connection master;
+disconnect con_temp_03;
+select get_lock("con_03",10);
+
+--echo
+--echo **** Checking the binary log and temporary tables
+--echo
+connection master;
+sync_slave_with_master;
+connection slave;
+show status like 'Slave_open_temp_tables';
+
+connection master;
+--source include/show_binlog_events.inc
+
+--echo ****
+--echo **** Cleaning up the test case
+--echo ****
+connection master;
+SET sql_log_bin= 0;
+DROP DATABASE database_master_temp_01;
+DROP DATABASE database_master_temp_02;
+DROP DATABASE database_master_temp_03;
+SET sql_log_bin= 1;
+
+connection slave;
+SET sql_log_bin= 0;
+DROP DATABASE database_slave_temp_01;
+DROP DATABASE database_slave_temp_02;
+DROP DATABASE database_slave_temp_03;
+SET sql_log_bin= 1;
+
+connection master;
+sync_slave_with_master;
+
+# end of 5.0 tests
=== added file 'mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test'
--- a/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test 2009-08-26 23:13:03 +0000
@@ -0,0 +1,5 @@
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+--source include/have_innodb.inc
+
+--source extra/rpl_tests/rpl_mixing_engines.test
=== added directory 'mysql-test/suite/vcol'
=== added directory 'mysql-test/suite/vcol/inc'
=== added file 'mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc'
--- a/mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,344 @@
+################################################################################
+# inc/vcol_blocked_sql_funcs_main.inc #
+# #
+# Purpose: #
+# Tests around sql functions #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: All SQL functions should be rejected, otherwise BUG.
+#
+
+--echo # RAND()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (b double as (rand()));
+
+--echo # LOAD_FILE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(64), b varchar(1024) as (load_file(a)));
+
+--echo # CURDATE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (curdate()));
+
+--echo # CURRENT_DATE(), CURRENT_DATE
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_date));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_date()));
+
+--echo # CURRENT_TIME(), CURRENT_TIME
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_time));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_time()));
+
+--echo # CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_timestamp()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_timestamp));
+
+--echo # CURTIME()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (curtime()));
+
+--echo # LOCALTIME(), LOCALTIME
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtime()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtime));
+
+--echo # LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6)
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtimestamp()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtimestamp));
+
+--echo # NOW()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (now()));
+
+--echo # SYSDATE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b varchar(10) as (sysdate()));
+
+--echo # UNIX_TIMESTAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (unix_timestamp()));
+
+--echo # UTC_DATE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (utc_date()));
+
+--echo # UTC_TIME()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (utc_time()));
+
+--echo # UTC_TIMESTAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (utc_timestamp()));
+
+--echo # MATCH()
+if (!$skip_full_text_checks)
+{
+ -- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+ create table t1 (a varchar(32), b bool as (match a against ('sample text')));
+}
+
+--echo # BENCHMARK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (benchmark(a,3)));
+
+--echo # CONNECTION_ID()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (connection_id()));
+
+--echo # CURRENT_USER(), CURRENT_USER
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (current_user()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (current_user));
+
+--echo # DATABASE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (database()));
+
+--echo # FOUND_ROWS()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (found_rows()));
+
+--echo # GET_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (get_lock(a,10)));
+
+--echo # IS_FREE_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (is_free_lock(a)));
+
+--echo # IS_USED_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (is_used_lock(a)));
+
+--echo # LAST_INSERT_ID()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (last_insert_id()));
+
+--echo # MASTER_POS_WAIT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32), b int as (master_pos_wait(a,0,2)));
+
+--echo # NAME_CONST()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (name_const('test',1)));
+
+--echo # RELEASE_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32), b int as (release_lock(a)));
+
+--echo # ROW_COUNT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (row_count()));
+
+--echo # SCHEMA()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (schema()));
+
+--echo # SESSION_USER()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (session_user()));
+
+--echo # SLEEP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (sleep(a)));
+
+--echo # SYSTEM_USER()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (system_user()));
+
+--echo # USER()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (user()));
+
+--echo # UUID_SHORT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024) as (uuid_short()));
+
+--echo # UUID()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024) as (uuid()));
+
+--echo # VALUES()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (values(a)));
+
+--echo # VERSION()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (version()));
+
+--echo # ENCRYPT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (encrypt(a)));
+
+--echo # Stored procedures
+
+delimiter //;
+create procedure p1()
+begin
+ select current_user();
+end //
+
+create function f1()
+returns int
+begin
+ return 1;
+end //
+
+delimiter ;//
+
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (p1()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (f1()));
+
+drop procedure p1;
+drop function f1;
+
+--echo # Unknown functions
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (f1()));
+
+--echo #
+--echo # GROUP BY FUNCTIONS
+--echo #
+
+--echo # AVG()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (avg(a)));
+
+--echo # BIT_AND()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (bit_and(a)));
+
+--echo # BIT_OR()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (bit_or(a)));
+
+--echo # BIT_XOR()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (bit_xor(a)));
+
+--echo # COUNT(DISTINCT)
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (count(distinct a)));
+
+--echo # COUNT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (count(a)));
+
+--echo # GROUP_CONCAT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32), b int as (group_concat(a,'')));
+
+--echo # MAX()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (max(a)));
+
+--echo # MIN()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (min(a)));
+
+--echo # STD()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (std(a)));
+
+--echo # STDDEV_POP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (stddev_pop(a)));
+
+--echo # STDDEV_SAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (stddev_samp(a)));
+
+--echo # STDDEV()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (stddev(a)));
+
+--echo # SUM()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (sum(a)));
+
+--echo # VAR_POP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (var_pop(a)));
+
+--echo # VAR_SAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (var_samp(a)));
+
+--echo # VARIANCE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (variance(a)));
+
+--echo #
+--echo # XML FUNCTIONS
+--echo #
+
+--echo # ExtractValue()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (ExtractValue(a,'//b[$@j]')));
+
+--echo # UpdateXML()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (UpdateXML(a,'/a','<e>fff</e>')));
+
+--echo #
+--echo # Sub-selects
+--echo #
+
+create table t1 (a int);
+-- error ER_PARSE_ERROR
+create table t2 (a int, b int as (select count(*) from t1));
+drop table t1;
+
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as ((select 1)));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (a+(select 1)));
+
+--echo #
+--echo # SP functions
+--echo #
+
+--disable_warnings
+drop function if exists sub1;
+--enable_warnings
+create function sub1(i int) returns int deterministic
+ return i+1;
+select sub1(1);
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (a+sub3(1)));
+drop function sub1;
+
+--echo #
+--echo # Long expression
+
+let $tmp_long_string = `SELECT repeat('a',240)`;
+eval create table t1 (a int, b varchar(300) as (concat(a,'$tmp_long_string')));
+drop table t1;
+let $tmp_long_string = `SELECT repeat('a',243)`;
+--error ER_WRONG_STRING_LENGTH
+eval create table t1 (a int, b varchar(300) as (concat(a,'$tmp_long_string')));
+
+--echo #
+--echo # Constant expression
+--error ER_CONST_EXPR_IN_VCOL
+create table t1 (a int as (PI()));
=== added file 'mysql-test/suite/vcol/inc/vcol_cleanup.inc'
--- a/mysql-test/suite/vcol/inc/vcol_cleanup.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_cleanup.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,25 @@
+################################################################################
+# inc/vcol_cleanup.inc #
+# #
+# Purpose: #
+# Removal of the objects created by the t/<test_name>.test #
+# scripts. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+--disable_warnings
+--disable_query_log
+DROP VIEW IF EXISTS v1,v2;
+DROP TABLE IF EXISTS t1,t2,t3;
+DROP PROCEDURE IF EXISTS p1;
+DROP FUNCTION IF EXISTS f1;
+DROP TRIGGER IF EXISTS trg1;
+DROP TRIGGER IF EXISTS trg2;
+--enable_query_log
+--enable_warnings
=== added file 'mysql-test/suite/vcol/inc/vcol_column_def_options.inc'
--- a/mysql-test/suite/vcol/inc/vcol_column_def_options.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_column_def_options.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,113 @@
+################################################################################
+# inc/vcol_column_def_options.inc #
+# #
+# Purpose: #
+# Testing different optional parameters specified when defining #
+# a virtual column. #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo #
+--echo # Section 1. Wrong column definition options
+--echo # - NOT NULL
+--echo # - NULL
+--echo # - DEFAULT <value>
+--echo # - AUTO_INCREMENT
+--echo # - [PRIMARY] KEY
+
+--echo # NOT NULL
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) not null);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) not null;
+drop table t1;
+
+--echo # NULL
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) null);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) null;
+drop table t1;
+
+--echo # DEFAULT
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) default 0);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) default 0;
+drop table t1;
+
+--echo # AUTO_INCREMENT
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) AUTO_INCREMENT);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) AUTO_INCREMENT;
+drop table t1;
+
+--echo # [PRIMARY] KEY
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) key);
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) primary key);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) key;
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) primary key;
+drop table t1;
+
+--echo # Section 2. Other column definition options
+--echo # - COMMENT
+--echo # - REFERENCES (only syntax testing here)
+--echo # - STORED (only systax testing here)
+create table t1 (a int, b int as (a % 2) comment 'my comment');
+show create table t1;
+describe t1;
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) comment 'my comment';
+show create table t1;
+describe t1;
+insert into t1 (a) values (1);
+select * from t1;
+insert into t1 values (2,default);
+select a,b from t1;
+create table t2 like t1;
+show create table t2;
+describe t2;
+insert into t2 (a) values (1);
+select * from t2;
+insert into t2 values (2,default);
+select a,b from t2;
+drop table t2;
+drop table t1;
+
+create table t1 (a int, b int as (a % 2) persistent);
+show create table t1;
+describe t1;
+insert into t1 (a) values (1);
+select * from t1;
+insert into t1 values (2,default);
+select a,b from t1;
+drop table t1;
+
+
+create table t2 (a int);
+create table t1 (a int, b int as (a % 2) persistent references t2(a));
+show create table t1;
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+--error ER_PARSE_ERROR
+alter table t1 modify b int as (a % 2) persistent references t2(a);
+show create table t1;
+drop table t1;
=== added file 'mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc'
--- a/mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,43 @@
+################################################################################
+# inc/vcol_dependencies_on_vcol.inc #
+# #
+# Purpose: #
+# Testing scenarios when columns depend on virtual columns, i.e. such as #
+# - a virtual column is based on a virtual column #
+# - a "real" column on which a virtual one is renamed/dropped #
+# - a virtual column involved in partitioning is renamed/dropped #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo # Can't define a virtual column on another virtual column
+--error ER_VCOL_BASED_ON_VCOL
+create table t1 (a int, b int as (a+1), c int as (b+1));
+create table t1 (a int, b int as (a+1));
+--error ER_VCOL_BASED_ON_VCOL
+alter table t1 add column c int as (b+1);
+drop table t1;
+
+--echo # Can't rename or drop a column used in the function of a virtual column
+create table t1 (a int, b int as (a+1));
+--echo # On renaming/dropping a column on which a virtual field is
+--echo # defined the following error is displayed:
+--echo # "Unknown column 'a' in 'virtual column function'"
+--error ER_BAD_FIELD_ERROR
+alter table t1 drop column a;
+--error ER_BAD_FIELD_ERROR
+alter table t1 change a c int;
+drop table t1;
+
+--echo # Can't rename or drop a virtual column used by the paritition function
+create table t1 (a int, b int as (a+1)) partition by hash(b);
+--error ER_BAD_FIELD_ERROR
+alter table t1 drop b;
+--error ER_BAD_FIELD_ERROR
+alter table t1 change b c int as (a+1);
+
=== added file 'mysql-test/suite/vcol/inc/vcol_handler.inc'
--- a/mysql-test/suite/vcol/inc/vcol_handler.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_handler.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,77 @@
+################################################################################
+# inc/vcol_handler.inc #
+# #
+# Purpose: #
+# Testing HANDLER. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent,
+ d char(1),
+ index (a),
+ index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+
+--echo # HANDLER tbl_name OPEN
+handler t1 open;
+
+--echo # HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+
+--echo # HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+
+--echo # HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+
+--echo # HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+
+--echo # HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+
+--echo # HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+
+--echo # HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+
+--echo # HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+
+--echo # HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+
+--echo # HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+
+--echo # HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+
+--echo # HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+
+--echo # HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+
+--echo # HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+
+--echo # HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+
+--echo # HANDLER tbl_name CLOSE
+handler t1 close;
+
+drop table t1;
=== added file 'mysql-test/suite/vcol/inc/vcol_init_vars.pre'
--- a/mysql-test/suite/vcol/inc/vcol_init_vars.pre 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_init_vars.pre 2009-10-16 22:57:48 +0000
@@ -0,0 +1,17 @@
+################################################################################
+# inc/vcol_init_vars.pre #
+# #
+# Purpose: #
+# Initialize variables used in t/<name> test cases. #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+let $skip_full_text_check = 0;
+let $skip_spatial_index_check = 0;
=== added file 'mysql-test/suite/vcol/inc/vcol_ins_upd.inc'
--- a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,289 @@
+################################################################################
+# inc/vcol_ins_upd.inc #
+# #
+# Purpose: #
+# Testing DDL operations such as INSERT, UPDATE, REPLACE and DELETE. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+let $create1 = create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+let $create2 = create table t1 (a int unique,
+ b int as (-a),
+ c int as (-a) persistent);
+let $create3 = create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent unique);
+let $create4 = create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent unique,
+ d varchar(16));
+eval $create1;
+set sql_warnings = 1;
+
+--echo #
+--echo # *** INSERT ***
+--echo #
+
+--echo # INSERT INTO tbl_name VALUES... DEFAULT is specified against vcols
+insert into t1 values (1,default,default);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name VALUES... NULL is specified against vcols
+insert into t1 values (1,null,null);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name VALUES... a non-NULL value is specified against vcols
+insert into t1 values (1,2,3);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<non_vcol_list>) VALUES...
+insert into t1 (a) values (1), (2);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<normal+vcols>) VALUES... DEFAULT is specified
+--echo # against vcols
+insert into t1 (a,b) values (1,default), (2,default);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<normal+vcols>) VALUES... NULL is specified against vcols
+insert into t1 (a,b) values (1,null), (2,null);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<normal+vcols>) VALUES... a non-NULL value is specified
+--echo # against vcols
+insert into t1 (a,b) values (1,3), (2,4);
+select * from t1;
+delete from t1;
+select * from t1;
+drop table t1;
+
+--echo # Table with UNIQUE non-vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+--echo # KEY UPDATE <non_vcol>=expr, <vcol>=expr
+eval $create2;
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+ on duplicate key update a=2, b=default;
+select a,b,c from t1;
+delete from t1 where b in (1,2);
+select * from t1;
+drop table t1;
+
+--echo # Table with UNIQUE vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+--echo # KEY UPDATE <non_vcol>=expr, <vcol>=expr
+eval $create3;
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+ on duplicate key update a=2, b=default;
+select a,b,c from t1;
+
+--echo # CREATE new_table ... LIKE old_table
+--echo # INSERT INTO new_table SELECT * from old_table
+create table t2 like t1;
+insert into t2 select * from t1;
+select * from t1;
+drop table t2;
+
+--echo # CREATE new_table ... LIKE old_table INSERT INTO new_table (<non-vcols>, <vcols>)
+--echo # SELECT <non-vcols>, <vcols> from old_table
+insert into t1 values (1,default,default);
+select * from t1;
+create table t2 like t1;
+insert into t2 (a,b) select a,b from t1;
+select * from t2;
+drop table t2;
+drop table t1;
+
+--echo #
+--echo # *** UPDATE ***
+--echo #
+
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE non-vcol=expr
+eval $create1;
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where a=2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # UPDATE tbl_name SET vcol=expr WHERE non-vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set c=3 where a=2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where b=-2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # UPDATE tbl_name SET vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set c=3 where b=-2;
+select * from t1;
+delete from t1;
+select * from t1;
+drop table t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=const
+eval $create3;
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where c=-2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where c between -3 and -2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # No INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where b between -3 and -2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE vcol=between const1 and const2 ORDER BY vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where c between -1 and 0
+ order by c;
+select * from t1;
+delete from t1 where c between -6 and 0;
+select * from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE vcol=between const1 and const2 ORDER BY vcol LIMIT 2
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where c between -1 and 0
+ order by c limit 2;
+select * from t1;
+delete from t1 where c between -2 and 0 order by c;
+select * from t1;
+delete from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where (c between -2 and 0) and (b=-1);
+select * from t1;
+delete from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+--echo # ORDER BY indexed vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where (c between -2 and 0) and (b=-1) order by c;
+select * from t1;
+delete from t1;
+drop table t1;
+
+let $innodb_engine = `SELECT @@session.storage_engine='innodb'`;
+if ($innodb_engine)
+{
+ --echo #
+ --echo # Verify ON UPDATE/DELETE actions of FOREIGN KEYs
+ create table t2 (a int primary key, name varchar(10));
+ create table t1 (a int primary key, b int as (a % 10) persistent);
+ insert into t2 values (1, 'value1'), (2,'value2'), (3,'value3');
+ insert into t1 (a) values (1),(2),(3);
+ select * from t1;
+ select * from t2;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+
+ --echo # - ON UPDATE RESTRICT
+ alter table t1 add foreign key (b) references t2(a) on update restrict;
+ --error ER_NO_REFERENCED_ROW_2
+ insert into t1 (a) values (4);
+ --error ER_ROW_IS_REFERENCED_2
+ update t2 set a=4 where a=3;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+ alter table t1 drop foreign key t1_ibfk_1;
+
+ --echo # - ON DELETE RESTRICT
+ alter table t1 add foreign key (b) references t2(a) on delete restrict;
+ --error ER_ROW_IS_REFERENCED_2
+ delete from t2 where a=3;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+ select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+ alter table t1 drop foreign key t1_ibfk_1;
+
+ --echo # - ON DELETE CASCADE
+ alter table t1 add foreign key (b) references t2(a) on delete cascade;
+ delete from t2 where a=3;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+ select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+ alter table t1 drop foreign key t1_ibfk_1;
+
+ drop table t1;
+ drop table t2;
+}
+
+--echo #
+--echo # *** REPLACE ***
+--echo #
+
+--echo # UNIQUE INDEX on vcol
+--echo # REPLACE tbl_name (non-vcols) VALUES (non-vcols);
+eval $create4;
+insert into t1 (a,d) values (1,'a'), (2,'b');
+select * from t1;
+replace t1 (a,d) values (1,'c');
+select * from t1;
+delete from t1;
+select * from t1;
+
+
+# *** DELETE
+# All required tests for DELETE are performed as part of the above testing
+# for INSERT, UPDATE and REPLACE.
+
+set sql_warnings = 0;
+drop table t1;
=== added file 'mysql-test/suite/vcol/inc/vcol_keys.inc'
--- a/mysql-test/suite/vcol/inc/vcol_keys.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_keys.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,163 @@
+################################################################################
+# inc/vcol_keys.inc #
+# #
+# Purpose: #
+# Testing keys, indexes defined upon virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+
+--echo # - UNIQUE KEY
+--echo # - INDEX
+--echo # - FULLTEXT INDEX
+--echo # - SPATIAL INDEX (not supported)
+--echo # - FOREIGN INDEX (partially supported)
+--echo # - CHECK (allowed but not used)
+
+--echo # UNIQUE
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2) unique);
+create table t1 (a int, b int as (a*2) persistent unique);
+show create table t1;
+describe t1;
+drop table t1;
+
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2), unique key (b));
+create table t1 (a int, b int as (a*2) persistent, unique (b));
+show create table t1;
+describe t1;
+drop table t1;
+
+create table t1 (a int, b int as (a*2));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add unique key (b);
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add unique key (b);
+drop table t1;
+
+--echo # Testing data manipulation operations involving UNIQUE keys
+--echo # on virtual columns can be found in:
+--echo # - vcol_ins_upd.inc
+--echo # - vcol_select.inc
+
+--echo #
+--echo # INDEX
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2), index (b));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2), index (a,b));
+
+create table t1 (a int, b int as (a*2) persistent, index (b));
+show create table t1;
+describe t1;
+drop table t1;
+
+create table t1 (a int, b int as (a*2) persistent, index (a,b));
+show create table t1;
+describe t1;
+drop table t1;
+
+create table t1 (a int, b int as (a*2));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add index (b);
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add index (a,b);
+drop table t1;
+
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (b);
+drop table t1;
+
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (a,b);
+create table t2 like t1;
+drop table t2;
+drop table t1;
+
+--echo # Testing data manipulation operations involving INDEX
+--echo # on virtual columns can be found in:
+--echo # - vcol_select.inc
+
+--echo #
+--echo # TODO: FULLTEXT INDEX
+
+--echo # SPATIAL INDEX
+if (!$skip_spatial_index_check)
+{
+ --echo # Error "All parts of a SPATIAL index must be NOT NULL"
+ --error ER_SPATIAL_CANT_HAVE_NULL
+ create table t1 (a int, b int as (a+1) persistent, spatial index (b));
+ create table t1 (a int, b int as (a+1) persistent);
+ --error ER_SPATIAL_CANT_HAVE_NULL
+ alter table t1 add spatial index (b);
+ drop table t1;
+}
+
+--echo # FOREIGN KEY
+
+--echo # Rejected FK options.
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1) persistent,
+ foreign key (b) references t2(a) on update set null);
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1) persistent,
+ foreign key (b) references t2(a) on update cascade);
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1) persistent,
+ foreign key (b) references t2(a) on delete set null);
+
+create table t1 (a int, b int as (a+1) persistent);
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a) on update set null;
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a) on update cascade;
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a) on delete set null;
+drop table t1;
+
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1),
+ foreign key (b) references t2(a));
+
+create table t1 (a int, b int as (a+1));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a);
+drop table t1;
+
+--echo # Allowed FK options.
+create table t2 (a int primary key, b char(5));
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on update restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on update no action);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on delete restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on delete cascade);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on delete no action);
+drop table t1;
+
+--echo
+--echo # Testing data manipulation operations involving FOREIGN KEY
+--echo # on virtual columns can be found in:
+--echo # - vcol_ins_upd.inc
+--echo # - vcol_select.inc
+
+--echo #
+--echo # TODO: CHECK
+
=== added file 'mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc'
--- a/mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,162 @@
+################################################################################
+# inc/vcol_non_stored_columns.inc #
+# #
+# Purpose: #
+# Ensure that MySQL behaviour is consistent irrelevant of #
+# - the place of a non-stored column among other columns, #
+# - the total number of non-stored fields. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo # Case 1. All non-stored columns.
+--echo # This scenario is currently impossible due to the fact that virtual columns
+--echo # with a constant expression are not allowed.
+
+--echo # Case 2. CREATE
+--echo # - Column1: "real"
+--echo # - Column 2: virtual non-stored
+create table t1 (a int, b int as (-a));
+insert into t1 values (1,default);
+select * from t1;
+insert into t1 values (2,default);
+select * from t1;
+drop table t1;
+
+--echo # Case 3. CREATE
+--echo # - Column1: "real"
+--echo # - Column 2: virtual stored
+create table t1 (a int, b int as (-a) persistent);
+insert into t1 values (1,default);
+select * from t1;
+insert into t1 values (2,default);
+select * from t1;
+drop table t1;
+
+--echo # Case 4. CREATE
+--echo # - Column1: virtual non-stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b), b int);
+insert into t1 values (default,1);
+select * from t1;
+insert into t1 values (default,2);
+select * from t1;
+drop table t1;
+
+--echo # Case 5. CREATE
+--echo # - Column1: virtual stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b) persistent, b int);
+insert into t1 values (default,1);
+select * from t1;
+insert into t1 values (default,2);
+select * from t1;
+drop table t1;
+
+--echo # Case 6. CREATE
+--echo # - Column1: "real"
+--echo # - Column2: virtual non-stored
+--echo # - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+insert into t1 values (1,default,default);
+select * from t1;
+insert into t1 values (2,default,default);
+select * from t1;
+drop table t1;
+
+--echo # Case 7. ALTER. Modify virtual stored -> virtual non-stored
+create table t1 (a int, b int as (a % 2) persistent);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 modify b int as (a % 2);
+show create table t1;
+drop table t1;
+
+--echo # Case 8. ALTER. Modify virtual non-stored -> virtual stored
+create table t1 (a int, b int as (a % 2));
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 modify b int as (a % 2) persistent;
+show create table t1;
+drop table t1;
+
+--echo # Case 9. CREATE LIKE
+--echo # - Column1: "real"
+--echo # - Column2: virtual non-stored
+--echo # - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+create table t2 like t1;
+insert into t2 values (1,default,default);
+select * from t2;
+insert into t2 values (2,default,default);
+select * from t2;
+drop table t2;
+drop table t1;
+
+--echo # Case 10. ALTER. Dropping a virtual non-stored column.
+--echo # - Column1: virtual non-stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b), b int, c varchar(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+alter table t1 drop column a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 11. ALTER. Dropping a virtual stored column.
+--echo # - Column1: virtual stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b) persistent, b int, c char(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+alter table t1 drop column a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 12. ALTER. Adding a new virtual non-stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+alter table t1 add column c int as (dayofyear(b)) after a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 13. ALTER. Adding a new virtual stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+alter table t1 add column c int as (dayofyear(b)) persistent after a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 14. ALTER. Changing the expression of a virtual stored column.
+create table t1 (a int, b datetime, c int as (week(b)) persistent);
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+alter table t1 change column c c int as (week(b,1)) persistent;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 15. ALTER. Changing the expression of a virtual non-stored column.
+create table t1 (a int, b datetime, c int as (week(b)));
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+alter table t1 change column c c int as (week(b,1));
+select * from t1;
+show create table t1;
+drop table t1;
+
=== added file 'mysql-test/suite/vcol/inc/vcol_partition.inc'
--- a/mysql-test/suite/vcol/inc/vcol_partition.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_partition.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,160 @@
+################################################################################
+# inc/vcol_partition.inc #
+# #
+# Purpose: #
+# Testing partitioning tables with virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--source include/have_partition.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+--echo # Case 1. Partitioning by RANGE based on a non-stored virtual column.
+
+CREATE TABLE t1 (
+ a DATE NOT NULL,
+ b int as (year(a))
+)
+PARTITION BY RANGE( b ) (
+ PARTITION p0 VALUES LESS THAN (2006),
+ PARTITION p2 VALUES LESS THAN (2008)
+);
+
+insert into t1 values ('2006-01-01',default);
+insert into t1 values ('2007-01-01',default);
+insert into t1 values ('2005-01-01',default);
+select * from t1;
+
+# Specifically for MyISAM, check that data is written into correct
+# $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD files
+let $myisam_engine = `select @@session.storage_engine='myisam'`;
+if ($myisam_engine)
+{
+ --echo # Check how data is physically partitioned.
+ --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ --exec du -b $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD
+}
+
+--echo # Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+
+select * from t1;
+
+if ($myisam_engine)
+{
+ --echo # Check how data is physically partitioned.
+ --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ --exec du -b $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD
+}
+
+drop table t1;
+
+--echo # Case 2. Partitioning by LIST based on a stored virtual column.
+
+CREATE TABLE t1 (a int, b int as (a % 3 ) persistent)
+PARTITION BY LIST (a+1)
+(PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
+
+insert into t1 values (1,default);
+if ($myisam_engine)
+{
+ --echo # Check how data is physically partitioned.
+ --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ --exec du -b $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD
+}
+select * from t1;
+
+#
+# NOTE: The following tests are currently failing due to a
+# [suspected] bug in the existing partition functionality.
+# Here is what was observed when using mysqld compiled prior
+# to adding the virtual column functionality.
+# mysql> create table t1 (a int) partition by list (a)
+# (partition p1 values in (1), partition p2 values in (2));
+# Query OK, 0 rows affected (0.00 sec)
+#
+# mysql> insert into t1 values (1), (1), (2);
+# Query OK, 3 rows affected (0.00 sec)
+# Records: 3 Duplicates: 0 Warnings: 0
+#
+# mysql> select * from t1;
+# +------+
+# | a |
+# +------+
+# | 1 |
+# | 1 |
+# | 2 |
+# +------+
+# 3 rows in set (0.00 sec)
+#
+# mysql> alter table t1 reorganize partition p1 into
+# (partition p1 values in (3));
+# Query OK, 2 rows affected (3.90 sec)
+# Records: 2 Duplicates: 2 Warnings: 0
+#
+# mysql> select * from t1;
+# +------+
+# | a |
+# +------+
+# | 2 | <- Two row have been lost!!!
+# +------+
+# 1 row in set (0.00 sec)
+
+#
+#alter table t1 change b b int as ((a % 3)+1) persistent;
+#--error ER_NO_PARTITION_FOR_GIVEN_VALUE
+#alter table t1 change b b int as (a % 2) persistent;
+#if ($myisam_engine)
+#{
+# --echo # Check how data is physically partitioned.
+# --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+# --exec du -b $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD
+#}
+
+select * from t1;
+
+drop table t1;
+
+--echo # Case 3. Partitioning by HASH based on a non-stored virtual column.
+
+CREATE TABLE t1 (
+ a DATE NOT NULL,
+ b int as (year(a))
+)
+PARTITION BY HASH( b % 3 ) PARTITIONS 3;
+
+insert into t1 values ('2005-01-01',default);
+insert into t1 values ('2006-01-01',default);
+select * from t1;
+
+if ($myisam_engine)
+{
+ --echo # Check how data is physically partitioned.
+ --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ --exec du -b $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD
+}
+
+--echo # Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+
+select * from t1;
+
+if ($myisam_engine)
+{
+ --echo # Check how data is physically partitioned.
+ --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+ --exec du -b $MYSQLTEST_VARDIR/mysqld.1/data/test/t1*p?.MYD
+}
+
+drop table t1;
=== added file 'mysql-test/suite/vcol/inc/vcol_select.inc'
--- a/mysql-test/suite/vcol/inc/vcol_select.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_select.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,216 @@
+################################################################################
+# inc/vcol_select.inc #
+# #
+# Purpose: #
+# Testing different SELECTs. #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-18 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+# Table t1 is used below to test:
+# - Join type of ALL (sequential scan of the entire table)
+# - Join type of Index
+# - Join type of Range
+# - Join type of Ref_or_null
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent,
+ index (c));
+insert into t1 (a) values (2), (1), (1), (3), (NULL);
+
+# Table t2 is used below to test:
+# - Join type of system and const
+create table t2 like t1;
+insert into t2 (a) values (1);
+
+# Table t3 is used below to test
+# - Join type of Eq_ref with a unique virtual column
+# - Join type of Const
+create table t3 (a int primary key,
+ b int as (-a),
+ c int as (-a) persistent unique);
+insert into t3 (a) values (2),(1),(3);
+
+
+--echo # select_type=SIMPLE, type=system
+let $s = select * from t2;
+eval $s;
+eval explain $s;
+
+let $s = select * from t2 where c=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=ALL
+let $s = select * from t1 where b=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=const
+let $s = select * from t3 where a=1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=range
+let $s = select * from t3 where c>=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=ref
+let $s = select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=PRIMARY, type=index,ALL
+let $s = select * from t1 where b in (select c from t3);
+eval $s;
+eval explain $s;
+
+--echo # select_type=PRIMARY, type=range,ref
+let $s = select * from t1 where c in (select c from t3 where c between -2 and -1);
+eval $s;
+eval explain $s;
+
+--echo # select_type=UNION, type=system
+--echo # select_type=UNION RESULT, type=<union1,2>
+let $s = select * from t1 union select * from t2;
+eval $s;
+eval explain $s;
+
+--echo # select_type=DERIVED, type=system
+let $s = select * from (select a,b,c from t1) as t11;
+eval $s;
+eval explain $s;
+
+--echo ###
+--echo ### Using aggregate functions with/without DISTINCT
+--echo ###
+--echo # SELECT COUNT(*) FROM tbl_name
+let $s = select count(*) from t1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT COUNT(DISTINCT <non-vcol>) FROM tbl_name
+let $s = select count(distinct a) from t1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT COUNT(DISTINCT <non-stored vcol>) FROM tbl_name
+let $s = select count(distinct b) from t1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT COUNT(DISTINCT <stored vcol>) FROM tbl_name
+let $s = select count(distinct c) from t1;
+eval $s;
+eval explain $s;
+
+--echo ###
+--echo ### filesort & range-based utils
+--echo ###
+--echo # SELECT * FROM tbl_name WHERE <vcol expr>
+let $s = select * from t3 where c >= -2;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-vcol expr>
+let $s = select * from t3 where a between 1 and 2;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
+let $s = select * from t3 where b between -2 and -1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <indexed vcol expr>
+let $s = select * from t3 where c between -2 and -1;
+eval $s;
+eval explain $s;
+
+#### Remove for MyISAM due to a bug
+#### when all the three records are returned (a=1,2,3)
+#### instead of just two (a=1,2).
+#### This bug is presumably in base SQL routines as the same happens
+#### with this table:
+#### create table t4 (a int primary key, b int, c int unique);
+let $myisam_engine = `SELECT @@session.storage_engine='myisam'`;
+if (!$myisam_engine)
+{
+ --echo # SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <non-indexed vcol>
+ let $s = select * from t3 where a between 1 and 2 order by b;
+ eval $s;
+ eval explain $s;
+}
+
+--echo # SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
+let $s = select * from t3 where a between 1 and 2 order by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
+let $s = select * from t3 where b between -2 and -1 order by a;
+eval $s;
+eval explain $s;
+
+#### Remove for MyISAM due to a bug
+#### when all the three records are returned (a=1,2,3)
+#### instead of just two (a=1,2).
+#### This bug is presumably in base SQL routines as the same happens
+#### with this table:
+#### create table t4 (a int primary key, b int, c int unique);
+let $innodb_engine = `SELECT @@session.storage_engine='innodb'`;
+if (!$innodb_engine)
+{
+ --echo # SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-vcol>
+ let $s = select * from t3 where c between -2 and -1 order by a;
+ eval $s;
+ eval explain $s;
+}
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
+let $s = select * from t3 where b between -2 and -1 order by b;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-indexed vcol>
+let $s = select * from t3 where c between -2 and -1 order by b;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
+let $s = select * from t3 where b between -2 and -1 order by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <indexed vcol>
+let $s = select * from t3 where c between -2 and -1 order by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+let $s = select sum(b) from t1 group by b;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+let $s = select sum(c) from t1 group by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+let $s = select sum(b) from t1 group by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+let $s = select sum(c) from t1 group by b;
+eval $s;
+eval explain $s;
+
=== added file 'mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc'
--- a/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,42 @@
+################################################################################
+# inc/vcol_supported_sql_funcs.inc #
+# #
+# Purpose: #
+# Tests frame for allowed sql functions #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+--enable_warnings
+set sql_warnings = 1;
+eval create table t1 ($cols);
+show create table t1;
+if ($rows)
+{
+ eval insert into t1 values ($values1);
+ dec $rows;
+}
+if ($rows)
+{
+ eval insert into t1 values ($values2);
+ dec $rows;
+}
+if ($rows)
+{
+ eval insert into t1 values ($values3);
+ dec $rows;
+}
+if ($rows)
+{
+ eval insert into t1 values ($values4);
+ dec $rows;
+}
+select * from t1;
+drop table t1;
+set sql_warnings = 0;
=== added file 'mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc'
--- a/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,1228 @@
+################################################################################
+# inc/vcol_supported_sql_funcs_main.inc #
+# #
+# Purpose: #
+# Tests frame for allowed sql functions #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo #
+--echo # NUMERIC FUNCTIONS
+--echo #
+
+--echo # ABS()
+let $cols = a int, b int as (abs(a));
+let $values1 = -1, default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ACOS()
+let $cols = a double, b double as (format(acos(a),6));
+let $values1 = 1, default;
+let $values2 = 1.0001,default;
+let $values3 = 0,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ASIN()
+let $cols = a double, b double as (format(asin(a),6));
+let $values1 = 0.2, default;
+let $values2 = 1.0001,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #ATAN
+let $cols = a double, b double, c double as (format(atan(a,b),6));
+let $values1 = -2,2,default;
+let $values2 = format(PI(),6),0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a double, c double as (format(atan(a),6));
+let $values1 = -2,default;
+let $values2 = format(PI(),6),default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ATAN2
+let $cols = a double, b double, c double as (format(atan2(a,b),6));
+let $values1 = -2,2,default;
+let $values2 = format(PI(),6),0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CEIL()
+let $cols = a double, b int as (ceil(a));
+let $values1 = 1.23,default;
+let $values2 = -1.23,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONV()
+let $cols = a varchar(10), b int, c int, d varchar(10) as (conv(a,b,c));
+let $values1 = 'a',16,2,default;
+let $values2 = '6e',18,8,default;
+let $values3 = -17,10,-18,default;
+let $values4 = 10+'10'+'10'+0xa,10,10,default;
+let $rows = 4;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COS()
+let $cols = a double, b double as (format(cos(a),6));
+let $values1 = format(PI(),6),default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COT()
+let $cols = a double, b double as (format(cot(a),6));
+let $values1 = 12,default;
+let $values2 = 0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CRC32()
+let $cols = a varchar(10), b long as (crc32(a));
+let $values1 = 'MySQL',default;
+let $values2 = 'mysql',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DEGREES()
+let $cols = a double, b double as (format(degrees(a),6));
+let $values1 = format(PI(),6),default;
+let $values2 = format(PI()/2,6),default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # /
+let $cols = a double, b double as (a/2);
+let $values1 = 2,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # EXP()
+let $cols = a double, b double as (format(exp(a),6));
+let $values1 = 2,default;
+let $values2 = -2,default;
+let $values3 = 0,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FLOOR()
+let $cols = a double, b long as (floor(a));
+let $values1 = 1.23,default;
+let $values2 = -1.23,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LN()
+let $cols = a double, b double as (format(ln(a),6));
+let $values1 = 2,default;
+let $values2 = -2,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOG()
+let $cols = a double, b double, c double as (format(log(a,b),6));
+let $values1 = 2,65536,default;
+let $values2 = 10,100,default;
+let $values3 = 1,100,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a double, b double as (format(log(a),6));
+let $values1 = 2,default;
+let $values2 = -2,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOG2()
+let $cols = a double, b double as (format(log2(a),6));
+let $values1 = 65536,default;
+let $values2 = -100,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOG10()
+let $cols = a double, b double as (format(log10(a),6));
+let $values1 = 2,default;
+let $values2 = 100,default;
+let $values3 = -100,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # -
+let $cols = a double, b double as (a-1);
+let $values1 = 2,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MOD()
+let $cols = a int, b int as (mod(a,10));
+let $values1 = 1,default;
+let $values2 = 11,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # %
+let $cols = a int, b int as (a % 10);
+let $values1 = 1,default;
+let $values2 = 11,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # OCT()
+let $cols = a double, b varchar(10) as (oct(a));
+let $values1 = 12,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PI()
+let $cols = a double, b double as (format(PI()*a*a,6));
+let $values1 = 1,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # +
+let $cols = a int, b int as (a+1);
+let $values1 = 1,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # POW, POWER
+let $cols = a int, b int as (pow(a,2)), c int as (power(a,2));
+let $values1 = 1,default,default;
+let $values2 = 2,default,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RADIANS()
+let $cols = a double, b double as (format(radians(a),6));
+let $values1 = 90,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ROUND()
+let $cols = a double, b int as (round(a));
+let $values1 = -1.23,default;
+let $values2 = -1.58,default;
+let $values3 = 1.58,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a double, b double, c int as (round(a,b));
+let $values1 = 1.298,1,default;
+let $values2 = 1.298,0,default;
+let $values3 = 23.298,-1,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SIGN()
+let $cols = a double, b int as (sign(a));
+let $values1 = -32,default;
+let $values2 = 0,default;
+let $values3 = 234,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SIN()
+let $cols = a double, b double as (format(sin(a),6));
+let $values1 = format(PI()/2,6),default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SQRT()
+let $cols = a double, b double as (format(sqrt(a),6));
+let $values1 = 4,default;
+let $values2 = 20,default;
+let $values3 = -16,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TAN()
+let $cols = a double, b double as (format(tan(a),6));
+let $values1 = format(PI(),6),default;
+let $values2 = format(PI()+1,6),default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # *
+let $cols = a double, b double as (a*3);
+let $values1 = 0,default;
+let $values2 = 1,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TRUNCATE()
+let $cols = a double, b double as (truncate(a,4));
+let $values1 = 1.223,default;
+let $values2 = 1.999,default;
+let $values3 = 1.999,default;
+let $values4 = 122,default;
+let $rows = 4;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # Unary -
+let $cols = a double, b double as (-a);
+let $values1 = 1,default;
+let $values2 = -1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # STRING FUNCTIONS
+--echo #
+
+--echo # ASCII()
+let $cols = a char(2), b int as (ascii(a));
+let $values1 = '2',default;
+let $values2 = 2,default;
+let $values3 = 'dx',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BIN()
+let $cols = a int, b varchar(10) as (bin(a));
+let $values1 = 12,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BIT_LENGTH()
+let $cols = a varchar(10), b long as (bit_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHAR_LENGTH()
+let $cols = a varchar(10), b long as (char_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHAR()
+let $cols = a int, b int, c varbinary(10) as (char(a,b));
+let $values1 = 77,121,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHARACTER_LENGTH()
+let $cols = a varchar(10), b long as (character_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONCAT_WS()
+let $cols = a varchar(10), b varchar(10), c varchar(20) as (concat_ws(',',a,b));
+let $values1 = 'value1','value2',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONCAT()
+let $cols = a varchar(10), b varchar(10), c varchar(20) as (concat(a,',',b));
+let $values1 = 'value1','value2',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ELT()
+let $cols = a varchar(10), b varchar(10), c int, d varchar(10) as (elt(c,a,b));
+let $values1 = 'value1','value2',1,default;
+let $values2 = 'value1','value2',2,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # EXPORT_SET()
+let $cols = a int, b varchar(10) as (export_set(a,'1','0','',10));
+let $values1 = 6,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FIELD()
+let $cols = a varchar(10), b varchar(10), c int as (field('aa',a,b));
+let $values1 = 'aa','bb',default;
+let $values2 = 'bb','aa',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FIND_IN_SET()
+let $cols = a varchar(10), b varchar(10), c int as (find_in_set(a,b));
+let $values1 = 'aa','aa,bb,cc',default;
+let $values2 = 'aa','bb,aa,cc',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FORMAT()
+let $cols = a double, b varchar(20) as (format(a,2));
+let $values1 = 12332.123456,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # HEX()
+let $cols = a int, b varchar(10) as (hex(a));
+let $values1 = 17,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a varchar(10), b varchar(10) as (hex(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # INSERT()
+let $cols = a varchar(10), b varchar(10), c varchar(20) as (insert(a,length(a),length(b),b));
+let $values1 = 'start,','end',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # INSTR()
+let $cols = a varchar(10), b varchar(10), c int as (instr(a,b));
+let $values1 = 'foobarbar,','bar',default;
+let $values2 = 'xbar,','foobar',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LCASE()
+let $cols = a varchar(10), b varchar(10) as (lcase(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LEFT()
+let $cols = a varchar(10), b varchar(5) as (left(a,5));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LENGTH()
+let $cols = a varchar(10), b int as (length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LIKE
+let $cols = a varchar(10), b bool as (a like 'H%o');
+let $values1 = 'Hello',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOCATE()
+let $cols = a varchar(10), b varchar(10) as (locate('bar',a));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOWER()
+let $cols = a varchar(10), b varchar(10) as (lower(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LPAD()
+let $cols = a varchar(10), b varchar(10) as (lpad(a,4,' '));
+let $values1 = 'MySQL',default;
+let $values2 = 'M',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LTRIM()
+let $cols = a varchar(10), b varchar(10) as (ltrim(a));
+let $values1 = ' MySQL',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MAKE_SET()
+let $cols = a varchar(10), b varchar(10), c int, d varchar(30) as (make_set(c,a,b));
+let $values1 = 'a','b',1,default;
+let $values2 = 'a','b',3,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MID()
+let $cols = a varchar(10), b varchar(10) as (mid(a,1,2));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NOT LIKE
+let $cols = a varchar(10), b bool as (a not like 'H%o');
+let $values1 = 'Hello',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NOT REGEXP
+let $cols = a varchar(10), b bool as (a not regexp 'H.+o');
+let $values1 = 'Hello',default;
+let $values2 = 'hello',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # OCTET_LENGTH()
+let $cols = a varchar(10), b int as (octet_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ORD()
+let $cols = a varchar(10), b long as (ord(a));
+let $values1 = '2',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # POSITION()
+let $cols = a varchar(10), b varchar(10) as (position('bar' in a));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # QUOTE()
+let $cols = a varchar(10), b varchar(10) as (quote(a));
+let $values1 = 'Don\'t',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REGEXP()
+let $cols = a varchar(10), b bool as (a regexp 'H.+o');
+let $values1 = 'Hello',default;
+let $values2 = 'hello',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REPEAT()
+let $cols = a varchar(10), b varchar(30) as (repeat(a,3));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REPLACE()
+let $cols = a varchar(10), b varchar(30) as (replace(a,'aa','bb'));
+let $values1 = 'maa',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REVERSE()
+let $cols = a varchar(10), b varchar(30) as (reverse(a));
+let $values1 = 'maa',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RIGHT()
+let $cols = a varchar(10), b varchar(10) as (right(a,4));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RLIKE()
+let $cols = a varchar(10), b bool as (a rlike 'H.+o');
+let $values1 = 'Hello',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RPAD()
+let $cols = a varchar(10), b varchar(10) as (rpad(a,4,'??'));
+let $values1 = 'He',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RTRIM();
+let $cols = a varchar(10), b varchar(10) as (rtrim(a));
+let $values1 = 'Hello ',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SOUNDEX()
+let $cols = a varchar(10), b varchar(20) as (soundex(a));
+let $values1 = 'Hello',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SOUNDS LIKE
+let $cols = a varchar(10), b varchar(10), c bool as (a sounds like b);
+let $values1 = 'Hello','Hello',default;
+let $values2 = 'Hello','MySQL',default;
+let $values3 = 'Hello','hello',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SPACE()
+let $cols = a varchar(5), b varchar(10) as (concat(a,space(5)));
+let $values1 = 'Hello', default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # STRCMP()
+let $cols = a varchar(9), b varchar(9), c tinyint(1) as (strcmp(a,b));
+let $values1 = 'Hello','Hello', default;
+let $values2 = 'Hello','Hello1', default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBSTR()
+let $cols = a varchar(5), b varchar(10) as (substr(a,2));
+let $values1 = 'Hello',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBSTRING_INDEX()
+let $cols = a varchar(15), b varchar(10) as (substring_index(a,'.',2));
+let $values1 = 'www.mysql.com',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBSTRING()
+let $cols = a varchar(5), b varchar(10) as (substring(a from 2 for 2));
+let $values1 = 'Hello',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TRIM()
+let $cols = a varchar(15), b varchar(10) as (trim(a));
+let $values1 = ' aa ',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UCASE()
+let $cols = a varchar(5), b varchar(10) as (ucase(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UNHEX()
+let $cols = a varchar(15), b varchar(10) as (unhex(a));
+let $values1 = '4D7953514C',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UPPER()
+let $cols = a varchar(5), b varchar(10) as (upper(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # CONTROL FLOW FUNCTIONS
+--echo #
+
+--echo # CASE
+let $cols = a varchar(10), b varchar(16) as (case a when NULL then 'asd' when 'b' then 'B' else a end);
+let $values1 = NULL,default;
+let $values2 = 'b',default;
+let $values3 = 'c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IF
+let $cols = a int, b int, c int as (if(a=1,a,b));
+let $values1 = 1,2,default;
+let $values2 = 3,4,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IFNULL
+let $cols = a varchar(10), b varchar(10), c varchar(10) as (ifnull(a,'DEFAULT'));
+let $values1 = NULL,'adf',default;
+let $values2 = 'a','adf',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NULLIF
+let $cols = a varchar(10), b varchar(10) as (nullif(a,'DEFAULT'));
+let $values1 = 'DEFAULT',default;
+let $values2 = 'a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # OPERATORS
+--echo #
+
+--echo # AND, &&
+let $cols = a int, b bool as (a>0 && a<2);
+let $values1 = -1,default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BETWEEN ... AND ...
+let $cols = a int, b bool as (a between 0 and 2);
+let $values1 = -1,default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BINARY
+let $cols = a varchar(10), b varbinary(10) as (binary a);
+let $values1 = '11',default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # &
+let $cols = a int, b int as (a & 5);
+let $values1 = 1,default;
+let $values2 = 0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ~
+let $cols = a int, b int as (~a);
+let $values1 = 1,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # |
+let $cols = a int, b int as (a | 5);
+let $values1 = 1,default;
+let $values2 = 0,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ^
+let $cols = a int, b int as (a ^ 5);
+let $values1 = 1,default;
+let $values2 = 0,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DIV
+let $cols = a int, b int as (a div 5);
+let $values1 = 1,default;
+let $values2 = 7,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <=>
+let $cols = a int, b int, c bool as (a <=> b);
+let $values1 = 1,1,default;
+let $values2 = NULL,NULL,default;
+let $values3 = 1,NULL,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # =
+let $cols = a varchar(10), b varchar(10), c bool as (a=b);
+let $values1 = 'a','b',default;
+let $values2 = 'a','a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # >=
+let $cols = a varchar(10), b varchar(10), c bool as (a >= b);
+let $values1 = 'a','b',default;
+let $values2 = 'a','a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # >
+let $cols = a varchar(10), b varchar(10), c bool as (a > b);
+let $values1 = 'a','b',default;
+let $values2 = 'a','a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IS NOT NULL
+let $cols = a int, b bool as (a is not null);
+let $values1 = 1,default;
+let $values2 = NULL,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IS NULL
+let $cols = a int, b bool as (a is null);
+let $values1 = 1,default;
+let $values2 = NULL,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <<
+let $cols = a int, b int as (a << 2);
+let $values1 = 1,default;
+let $values2 = 3,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <=
+let $cols = a varchar(10), b varchar(10), c bool as (a <= b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <
+let $cols = a varchar(10), b varchar(10), c bool as (a < b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NOT BETWEEN ... AND ...
+let $cols = a int, b bool as (a not between 0 and 2);
+let $values1 = -1,default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <>
+let $cols = a varchar(10), b varchar(10), c bool as (a <> b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # !=
+let $cols = a varchar(10), b varchar(10), c bool as (a != b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ||, OR
+let $cols = a int, b int as (a>5 || a<3);
+let $values1 = 1,default;
+let $values2 = 4,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # >>
+let $cols = a int, b int as (a >> 2);
+let $values1 = 8,default;
+let $values2 = 3,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # XOR
+let $cols = a int, b int as (a xor 5);
+let $values1 = 0,default;
+let $values2 = 1,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # DATE AND TIME FUNCTIONS
+--echo #
+
+--echo # ADDDATE()
+let $cols = a datetime, b datetime as (adddate(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ADDTIME()
+let $cols = a datetime, b datetime as (addtime(a,'02:00:00'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONVERT_TZ()
+let $cols = a datetime, b datetime as (convert_tz(a,'MET','UTC'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE_ADD()
+let $cols = a datetime, b datetime as (date_add(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE_FORMAT()
+let $cols = a datetime, b varchar(64) as (date_format(a,'%W %M %D'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE_SUB()
+let $cols = a datetime, b datetime as (date_sub(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE()
+let $cols = a datetime, b datetime as (date(a));
+let $values1 = '2008-08-31 02:00:00',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATEDIFF()
+let $cols = a datetime, b long as (datediff(a,'2000-01-01'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAY()
+let $cols = a datetime, b int as (day(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYNAME()
+let $cols = a datetime, b varchar(10) as (dayname(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYOFMONTH()
+let $cols = a datetime, b int as (dayofmonth(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYOFWEEK()
+let $cols = a datetime, b int as (dayofweek(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYOFYEAR()
+let $cols = a datetime, b int as (dayofyear(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # EXTRACT
+let $cols = a datetime, b int as (extract(year from a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FROM_DAYS()
+let $cols = a long, b datetime as (from_days(a));
+let $values1 = 730669,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FROM_UNIXTIME()
+let $cols = a long, b datetime as (from_unixtime(a));
+let $values1 = 1196440219,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # GET_FORMAT()
+let $cols = a datetime, b varchar(32) as (date_format(a,get_format(DATE,'EUR')));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # HOUR()
+let $cols = a time, b long as (hour(a));
+let $values1 = '10:05:03',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LAST_DAY()
+let $cols = a datetime, b datetime as (last_day(a));
+let $values1 = '2003-02-05',default;
+let $values2 = '2003-02-32',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MAKEDATE()
+let $cols = a int, b datetime as (makedate(a,1));
+let $values1 = 2001,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MAKETIME()
+let $cols = a int, b time as (maketime(a,1,3));
+let $values1 = 12,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MICROSECOND()
+let $cols = a datetime, b long as (microsecond(a));
+let $values1 = '2009-12-31 12:00:00.123456',default;
+let $values2 = '2009-12-31 23:59:59.000010',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MINUTE()
+let $cols = a datetime, b int as (minute(a));
+let $values1 = '2009-12-31 23:59:59.000010',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MONTH()
+let $cols = a datetime, b int as (month(a));
+let $values1 = '2009-12-31 23:59:59.000010',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MONTHNAME()
+let $cols = a datetime, b varchar(16) as (monthname(a));
+let $values1 = '2009-12-31 23:59:59.000010',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PERIOD_ADD()
+let $cols = a int, b int as (period_add(a,2));
+let $values1 = 200801,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PERIOD_DIFF()
+let $cols = a int, b int, c int as (period_diff(a,b));
+let $values1 = 200802,200703,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # QUARTER()
+let $cols = a datetime, b int as (quarter(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SEC_TO_TIME()
+let $cols = a long, b time as (sec_to_time(a));
+let $values1 = 2378,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SECOND()
+let $cols = a datetime, b int as (second(a));
+let $values1 = '10:05:03',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # STR_TO_DATE()
+let $cols = a varchar(64), b datetime as (str_to_date(a,'%m/%d/%Y'));
+let $values1 = '04/30/2004',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBDATE()
+let $cols = a datetime, b datetime as (subdate(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBTIME()
+let $cols = a datetime, b datetime as (subtime(a,'02:00:00'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIME_FORMAT()
+let $cols = a datetime, b varchar(32) as (time_format(a,'%r'));
+let $values1 = '2008-08-31 02:03:04',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIME_TO_SEC()
+let $cols = a time, b long as (time_to_sec(a));
+let $values1 = '22:23:00',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIME()
+let $cols = a datetime, b time as (time(a));
+let $values1 = '2008-08-31 02:03:04',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMEDIFF()
+let $cols = a datetime, b datetime, c long as (timediff(a,b));
+let $values1 = '2008-12-31 23:59:59.000001','2008-12-30 01:01:01.000002',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMESTAMP()
+let $cols = a datetime, b timestamp as (timestamp(a));
+let $values1 = '2008-12-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMESTAMPADD()
+let $cols = a datetime, b timestamp as (timestampadd(minute,1,a));
+let $values1 = '2003-01-02',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMESTAMPDIFF()
+let $cols = a timestamp, b timestamp, c long as (timestampdiff(MONTH, a,b));
+let $values1 = '2003-02-01','2003-05-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TO_DAYS()
+let $cols = a datetime, b long as (to_days(a));
+let $values1 = '2007-10-07',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # WEEK()
+let $cols = a datetime, b int as (week(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # WEEKDAY()
+let $cols = a datetime, b int as (weekday(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # WEEKOFYEAR()
+let $cols = a datetime, b int as (weekofyear(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # YEAR()
+let $cols = a datetime, b int as (year(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # YEARWEEK()
+let $cols = a datetime, b int as (yearweek(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # FULL TEXT SEARCH FUNCTIONS
+--echo #
+--echo # None.
+
+--echo #
+--echo # CAST FUNCTIONS AND OPERATORS
+--echo #
+
+--echo # CAST()
+let $cols = a int, b long as (cast(a as unsigned));
+let $values1 = 1,default;
+let $values2 = -1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # Convert()
+let $cols = a int, b long as (convert(a,unsigned));
+let $values1 = 1,default;
+let $values2 = -1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # XML FUNCTIONS
+--echo #
+--echo # None.
+
+
+--echo #
+--echo # OTHER FUNCTIONS
+--echo #
+
+--echo # AES_DECRYPT(), AES_ENCRYPT()
+let $cols = a varchar(1024), b varchar(1024) as (aes_encrypt(aes_decrypt(a,'adf'),'adf'));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BIT_COUNT()
+let $cols = a int, b int as (bit_count(a));
+let $values1 = 5,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHARSET()
+let $cols = a varchar(1024), b varchar(1024) as (charset(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COERCIBILITY()
+let $cols = a varchar(1024), b int as (coercibility(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COLLATION()
+let $cols = a varchar(1024), b varchar(1024) as (collation(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COMPRESS(), UNCOMPRESS()
+let $cols = a varchar(1024), b varchar(1024) as (uncompress(compress(a)));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ENCODE(), DECODE()
+let $cols = a varchar(1024), b varchar(1024) as (decode(encode(a,'abc'),'abc'));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DEFAULT()
+let $cols = a varchar(1024) default 'aaa', b varchar(1024) as (ifnull(a,default(a)));
+let $values1 = 'any value',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+#--echo # DES_ENCRYPT(), DES_DECRYPT()
+#--source include/have_ssl.inc
+#let $cols = a varchar(1024), b varchar(1024) as (des_encrypt(des_decrypt(a,'adf'),'adf'));
+#let $values1 = 'MySQL',default;
+#let $rows = 1;
+#--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # INET_ATON(), INET_NTOA()
+let $cols = a varchar(1024), b varchar(1024) as (inet_ntoa(inet_aton(a)));
+let $values1 = '127.0.0.1',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MD5()
+let $cols = a varchar(1024), b varbinary(32) as (md5(a));
+let $values1 = 'testing',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # OLD_PASSWORD()
+let $cols = a varchar(1024), b varchar(1024) as (old_password(a));
+let $values1 = 'badpwd',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PASSWORD()
+let $cols = a varchar(1024), b varchar(1024) as (password(a));
+let $values1 = 'badpwd',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SHA1()
+let $cols = a varchar(1024), b varchar(1024) as (sha1(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SHA()
+let $cols = a varchar(1024), b varchar(1024) as (sha(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UNCOMPRESSED_LENGTH()
+let $cols = a char, b varchar(1024) as (uncompressed_length(compress(repeat(a,30))));
+let $values1 = 'a',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
=== added file 'mysql-test/suite/vcol/inc/vcol_trigger_sp.inc'
--- a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,110 @@
+################################################################################
+# inc/vcol_trigger_sp.inc #
+# #
+# Purpose: #
+# Testing triggers, stored procedures and functions #
+# defined on tables with virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+create table t1 (a int,
+ b int as (a/10),
+ c int as (a/10) persistent);
+
+create table t2 (a timestamp);
+
+delimiter |;
+
+create trigger trg1 before insert on t1 for each row
+begin
+ if (new.b < 10) then
+ set new.a:= 100;
+ set new.b:= 9;
+ set new.c:= 9;
+ end if;
+
+ if (new.c > 50) then
+ set new.a:= 500;
+ end if;
+end|
+
+create trigger trg2 after insert on t1 for each row
+begin
+ if (new.b >= 60) then
+ insert into t2 values (now());
+ end if;
+end|
+
+create function f1()
+returns int
+begin
+ declare sum1 int default '0';
+ declare cur1 cursor for select sum(b) from t1;
+ open cur1;
+ fetch cur1 into sum1;
+ close cur1;
+ return sum1;
+end|
+
+delimiter ;|
+
+set sql_warnings = 1;
+
+insert into t1 (a) values (200);
+select * from t1;
+select * from t2;
+
+insert into t1 (a) values (10);
+select * from t1;
+select * from t2;
+
+insert into t1 (a) values (600);
+select * from t1;
+--replace_column 1 <timestamp>
+select * from t2;
+
+select f1();
+
+set sql_warnings = 0;
+
+drop trigger trg1;
+drop trigger trg2;
+drop table t2;
+
+delimiter |;
+
+create procedure p1()
+begin
+ declare i int default '0';
+ create table t2 like t1;
+ insert into t2 (a) values (100), (200);
+ begin
+ declare cur1 cursor for select sum(c) from t2;
+ open cur1;
+ fetch cur1 into i;
+ close cur1;
+ if (i=30) then
+ insert into t1 values (300,default,default);
+ end if;
+ end;
+end|
+
+delimiter ;|
+
+delete from t1;
+
+call p1();
+
+select * from t2;
+select * from t1;
+
+drop table t1,t2;
+drop procedure p1;
=== added file 'mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc'
--- a/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,21 @@
+################################################################################
+# inc/vcol_unsupported_storage_engines.inc #
+# #
+# Purpose: #
+# Ensure that defining a virtual column for an unsupported table type #
+# results in a graceful error. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1));
+create table t1 (a int);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 add column b int as (a+1);
+drop table t1;
=== added file 'mysql-test/suite/vcol/inc/vcol_view.inc'
--- a/mysql-test/suite/vcol/inc/vcol_view.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/inc/vcol_view.inc 2009-10-16 22:57:48 +0000
@@ -0,0 +1,201 @@
+################################################################################
+# inc/vcol_view.inc #
+# #
+# Purpose: #
+# Testing views defined on tables with virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+
+
+create table t1 (a int not null,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1), (1), (2), (2), (3);
+
+# simple view
+create view v1 (d,e) as select abs(b), abs(c) from t1;
+select d,e from v1;
+select is_updatable from information_schema.views where table_name='v1';
+
+# view with different algorithms (explain output differs)
+explain extended select d,e from v1;
+create algorithm=temptable view v2 (d,e) as select abs(b), abs(c) from t1;
+show create view v2;
+select d,e from v2;
+explain extended select d,e from v2;
+
+# VIEW on VIEW test
+create view v3 (d,e) as select d*2, e*2 from v1;
+select * from v3;
+explain extended select * from v3;
+
+drop view v1,v2,v3;
+drop table t1;
+
+#
+# DISTINCT option for VIEW
+#
+create table t1 (a int not null,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct b from t1;
+select * from v1;
+explain select * from v1;
+select * from t1;
+drop view v1;
+create view v1 as select distinct c from t1;
+select * from v1;
+explain select * from v1;
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# LIMIT clause test
+#
+create table t1 (a int not null,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (4);
+create view v1 as select b+1 from t1 order by 1 desc limit 2;
+select * from v1;
+explain select * from v1;
+drop view v1;
+create view v1 as select c+1 from t1 order by 1 desc limit 2;
+select * from v1;
+explain select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# simple view + simple update, insert and delete
+#
+create table t1 (a int,
+ b int,
+ c int as (-a),
+ d int as (-a) persistent,
+ primary key(a));
+insert into t1 (a,b) values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,e,f,g) as select a, b+1,c+1,d+1 from t1;
+# updatable field of updateable view
+update v1 set a=a+e;
+select * from v1;
+select * from t1;
+delete from v1;
+select * from v1;
+select * from t1;
+--error ER_NON_INSERTABLE_TABLE
+insert into v1 (a,e) values (60,15);
+drop table t1;
+drop view v1;
+
+#
+# outer join based on VIEW with WHERE clause
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent,
+ primary key(a));
+insert into t1 (a) values (1), (2), (3);
+create view v1 (x,y,z) as select a,b,c from t1 where b < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.b= v1.y);
+drop view v1;
+create view v1 (x,y,z) as select a,b,c from t1 where c < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.c= v1.z);
+drop view v1;
+drop table t1;
+
+#
+# VIEW built over UNION
+#
+create table t1 (a1 int,
+ b1 int as (-a1),
+ c1 int as (-a1) persistent);
+create table t2 (a2 int,
+ b2 int as (-a2),
+ c2 int as (-a2) persistent);
+insert into t1 (a1) values (1), (2);
+insert into t2 (a2) values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+drop view v1;
+drop table t1, t2;
+
+#
+# Showing VIEW with VIEWs in subquery
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+create table t2 like t1;
+create view v1 as select a,b,c from t1;
+create view v2 as select a,b,c from t2 where b in (select b from v1);
+show create view v2;
+drop view v2, v1;
+drop table t1, t2;
+
+#
+# TODO: VIEW with full text
+#
+#CREATE TABLE t1 (c1 int not null auto_increment primary key, c2 varchar(20), fulltext(c2));
+#insert into t1 (c2) VALUES ('real Beer'),('Water'),('Kossu'),('Coca-Cola'),('Vodka'),('Wine'),('almost real Beer');
+#select * from t1 WHERE match (c2) against ('Beer');
+#CREATE VIEW v1 AS SELECT * from t1 WHERE match (c2) against ('Beer');
+#select * from v1;
+#drop view v1;
+#drop table t1;
+
+#
+# distinct in temporary table with a VIEW
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1),(1),(2),(2),(3),(3);
+create view v1 as select b from t1;
+select distinct b from v1;
+select distinct b from v1 limit 2;
+select distinct b from t1 limit 2;
+prepare stmt1 from "select distinct b from v1 limit 2";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v1;
+create view v1 as select c from t1;
+select distinct c from v1;
+select distinct c from v1 limit 2;
+select distinct c from t1 limit 2;
+prepare stmt1 from "select distinct c from v1 limit 2";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+
+#
+# WITH CHECK OPTION insert/update test
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+create view v1 as select * from t1 where b > -2 && c >-2 with check option;
+# simple insert
+insert into v1 (a) values (1);
+-- error 1369
+insert into v1 (a) values (3);
+# simple insert with ignore
+insert ignore into v1 (a) values (2),(3),(0);
+select * from t1;
+drop view v1;
+drop table t1;
+
=== added directory 'mysql-test/suite/vcol/r'
=== added file 'mysql-test/suite/vcol/r/rpl_vcol.result'
--- a/mysql-test/suite/vcol/r/rpl_vcol.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/rpl_vcol.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,25 @@
+SET @@session.storage_engine = 'InnoDB';
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 2
+2 3
+select * from t1;
+a b
+1 2
+2 3
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_archive.result'
--- a/mysql-test/suite/vcol/r/vcol_archive.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_archive.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'archive';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+create table t1 (a int);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_blackhole.result'
--- a/mysql-test/suite/vcol/r/vcol_blackhole.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_blackhole.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'blackhole';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+create table t1 (a int);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,243 @@
+SET @@session.storage_engine = 'InnoDB';
+# RAND()
+create table t1 (b double as (rand()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# LOAD_FILE()
+create table t1 (a varchar(64), b varchar(1024) as (load_file(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# CURDATE()
+create table t1 (a datetime as (curdate()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_DATE(), CURRENT_DATE
+create table t1 (a datetime as (current_date));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a datetime as (current_date()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_TIME(), CURRENT_TIME
+create table t1 (a datetime as (current_time));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a datetime as (current_time()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP
+create table t1 (a datetime as (current_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a datetime as (current_timestamp));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURTIME()
+create table t1 (a datetime as (curtime()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# LOCALTIME(), LOCALTIME
+create table t1 (a datetime, b varchar(10) as (localtime()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+create table t1 (a datetime, b varchar(10) as (localtime));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6)
+create table t1 (a datetime, b varchar(10) as (localtimestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+create table t1 (a datetime, b varchar(10) as (localtimestamp));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# NOW()
+create table t1 (a datetime, b varchar(10) as (now()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# SYSDATE()
+create table t1 (a int, b varchar(10) as (sysdate()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UNIX_TIMESTAMP()
+create table t1 (a datetime, b datetime as (unix_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UTC_DATE()
+create table t1 (a datetime, b datetime as (utc_date()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UTC_TIME()
+create table t1 (a datetime, b datetime as (utc_time()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UTC_TIMESTAMP()
+create table t1 (a datetime, b datetime as (utc_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# MATCH()
+# BENCHMARK()
+create table t1 (a varchar(1024), b varchar(1024) as (benchmark(a,3)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# CONNECTION_ID()
+create table t1 (a int as (connection_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_USER(), CURRENT_USER
+create table t1 (a varchar(32) as (current_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a varchar(32) as (current_user));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# DATABASE()
+create table t1 (a varchar(1024), b varchar(1024) as (database()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# FOUND_ROWS()
+create table t1 (a varchar(1024), b varchar(1024) as (found_rows()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# GET_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (get_lock(a,10)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# IS_FREE_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_free_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# IS_USED_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_used_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# LAST_INSERT_ID()
+create table t1 (a int as (last_insert_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# MASTER_POS_WAIT()
+create table t1 (a varchar(32), b int as (master_pos_wait(a,0,2)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# NAME_CONST()
+create table t1 (a varchar(32) as (name_const('test',1)));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# RELEASE_LOCK()
+create table t1 (a varchar(32), b int as (release_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# ROW_COUNT()
+create table t1 (a int as (row_count()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# SCHEMA()
+create table t1 (a varchar(32) as (schema()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# SESSION_USER()
+create table t1 (a varchar(32) as (session_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# SLEEP()
+create table t1 (a int, b int as (sleep(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# SYSTEM_USER()
+create table t1 (a varchar(32) as (system_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# USER()
+create table t1 (a varchar(1024), b varchar(1024) as (user()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UUID_SHORT()
+create table t1 (a varchar(1024) as (uuid_short()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# UUID()
+create table t1 (a varchar(1024) as (uuid()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# VALUES()
+create table t1 (a varchar(1024), b varchar(1024) as (values(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VERSION()
+create table t1 (a varchar(1024), b varchar(1024) as (version()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# ENCRYPT()
+create table t1 (a varchar(1024), b varchar(1024) as (encrypt(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# Stored procedures
+create procedure p1()
+begin
+select current_user();
+end //
+create function f1()
+returns int
+begin
+return 1;
+end //
+create table t1 (a int as (p1()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+drop procedure p1;
+drop function f1;
+# Unknown functions
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+#
+# GROUP BY FUNCTIONS
+#
+# AVG()
+create table t1 (a int, b int as (avg(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BIT_AND()
+create table t1 (a int, b int as (bit_and(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BIT_OR()
+create table t1 (a int, b int as (bit_or(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BIT_XOR()
+create table t1 (a int, b int as (bit_xor(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# COUNT(DISTINCT)
+create table t1 (a int, b int as (count(distinct a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# COUNT()
+create table t1 (a int, b int as (count(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# GROUP_CONCAT()
+create table t1 (a varchar(32), b int as (group_concat(a,'')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# MAX()
+create table t1 (a int, b int as (max(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# MIN()
+create table t1 (a int, b int as (min(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STD()
+create table t1 (a int, b int as (std(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STDDEV_POP()
+create table t1 (a int, b int as (stddev_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STDDEV_SAMP()
+create table t1 (a int, b int as (stddev_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STDDEV()
+create table t1 (a int, b int as (stddev(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# SUM()
+create table t1 (a int, b int as (sum(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VAR_POP()
+create table t1 (a int, b int as (var_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VAR_SAMP()
+create table t1 (a int, b int as (var_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VARIANCE()
+create table t1 (a int, b int as (variance(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+#
+# XML FUNCTIONS
+#
+# ExtractValue()
+create table t1 (a varchar(1024), b varchar(1024) as (ExtractValue(a,'//b[$@j]')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UpdateXML()
+create table t1 (a varchar(1024), b varchar(1024) as (UpdateXML(a,'/a','<e>fff</e>')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+#
+# Sub-selects
+#
+create table t1 (a int);
+create table t2 (a int, b int as (select count(*) from t1));
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from t1))' at line 1
+drop table t1;
+create table t1 (a int, b int as ((select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+create table t1 (a int, b int as (a+(select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+#
+# SP functions
+#
+drop function if exists sub1;
+create function sub1(i int) returns int deterministic
+return i+1;
+select sub1(1);
+sub1(1)
+2
+create table t1 (a int, b int as (a+sub3(1)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+drop function sub1;
+#
+# Long expression
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+drop table t1;
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+ERROR HY000: String 'concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long for VIRTUAL COLUMN EXPRESSION (should be no longer than 252)
+#
+# Constant expression
+create table t1 (a int as (PI()));
+ERROR HY000: Constant expression in computed column function is not allowed.
=== added file 'mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,245 @@
+SET @@session.storage_engine = 'MyISAM';
+# RAND()
+create table t1 (b double as (rand()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# LOAD_FILE()
+create table t1 (a varchar(64), b varchar(1024) as (load_file(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# CURDATE()
+create table t1 (a datetime as (curdate()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_DATE(), CURRENT_DATE
+create table t1 (a datetime as (current_date));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a datetime as (current_date()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_TIME(), CURRENT_TIME
+create table t1 (a datetime as (current_time));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a datetime as (current_time()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP
+create table t1 (a datetime as (current_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a datetime as (current_timestamp));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURTIME()
+create table t1 (a datetime as (curtime()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# LOCALTIME(), LOCALTIME
+create table t1 (a datetime, b varchar(10) as (localtime()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+create table t1 (a datetime, b varchar(10) as (localtime));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6)
+create table t1 (a datetime, b varchar(10) as (localtimestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+create table t1 (a datetime, b varchar(10) as (localtimestamp));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# NOW()
+create table t1 (a datetime, b varchar(10) as (now()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# SYSDATE()
+create table t1 (a int, b varchar(10) as (sysdate()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UNIX_TIMESTAMP()
+create table t1 (a datetime, b datetime as (unix_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UTC_DATE()
+create table t1 (a datetime, b datetime as (utc_date()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UTC_TIME()
+create table t1 (a datetime, b datetime as (utc_time()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UTC_TIMESTAMP()
+create table t1 (a datetime, b datetime as (utc_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# MATCH()
+create table t1 (a varchar(32), b bool as (match a against ('sample text')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BENCHMARK()
+create table t1 (a varchar(1024), b varchar(1024) as (benchmark(a,3)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# CONNECTION_ID()
+create table t1 (a int as (connection_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# CURRENT_USER(), CURRENT_USER
+create table t1 (a varchar(32) as (current_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a varchar(32) as (current_user));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# DATABASE()
+create table t1 (a varchar(1024), b varchar(1024) as (database()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# FOUND_ROWS()
+create table t1 (a varchar(1024), b varchar(1024) as (found_rows()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# GET_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (get_lock(a,10)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# IS_FREE_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_free_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# IS_USED_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_used_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# LAST_INSERT_ID()
+create table t1 (a int as (last_insert_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# MASTER_POS_WAIT()
+create table t1 (a varchar(32), b int as (master_pos_wait(a,0,2)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# NAME_CONST()
+create table t1 (a varchar(32) as (name_const('test',1)));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# RELEASE_LOCK()
+create table t1 (a varchar(32), b int as (release_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# ROW_COUNT()
+create table t1 (a int as (row_count()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# SCHEMA()
+create table t1 (a varchar(32) as (schema()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# SESSION_USER()
+create table t1 (a varchar(32) as (session_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# SLEEP()
+create table t1 (a int, b int as (sleep(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# SYSTEM_USER()
+create table t1 (a varchar(32) as (system_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# USER()
+create table t1 (a varchar(1024), b varchar(1024) as (user()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UUID_SHORT()
+create table t1 (a varchar(1024) as (uuid_short()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# UUID()
+create table t1 (a varchar(1024) as (uuid()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+# VALUES()
+create table t1 (a varchar(1024), b varchar(1024) as (values(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VERSION()
+create table t1 (a varchar(1024), b varchar(1024) as (version()));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# ENCRYPT()
+create table t1 (a varchar(1024), b varchar(1024) as (encrypt(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# Stored procedures
+create procedure p1()
+begin
+select current_user();
+end //
+create function f1()
+returns int
+begin
+return 1;
+end //
+create table t1 (a int as (p1()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+drop procedure p1;
+drop function f1;
+# Unknown functions
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'.
+#
+# GROUP BY FUNCTIONS
+#
+# AVG()
+create table t1 (a int, b int as (avg(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BIT_AND()
+create table t1 (a int, b int as (bit_and(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BIT_OR()
+create table t1 (a int, b int as (bit_or(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# BIT_XOR()
+create table t1 (a int, b int as (bit_xor(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# COUNT(DISTINCT)
+create table t1 (a int, b int as (count(distinct a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# COUNT()
+create table t1 (a int, b int as (count(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# GROUP_CONCAT()
+create table t1 (a varchar(32), b int as (group_concat(a,'')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# MAX()
+create table t1 (a int, b int as (max(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# MIN()
+create table t1 (a int, b int as (min(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STD()
+create table t1 (a int, b int as (std(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STDDEV_POP()
+create table t1 (a int, b int as (stddev_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STDDEV_SAMP()
+create table t1 (a int, b int as (stddev_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# STDDEV()
+create table t1 (a int, b int as (stddev(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# SUM()
+create table t1 (a int, b int as (sum(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VAR_POP()
+create table t1 (a int, b int as (var_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VAR_SAMP()
+create table t1 (a int, b int as (var_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# VARIANCE()
+create table t1 (a int, b int as (variance(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+#
+# XML FUNCTIONS
+#
+# ExtractValue()
+create table t1 (a varchar(1024), b varchar(1024) as (ExtractValue(a,'//b[$@j]')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+# UpdateXML()
+create table t1 (a varchar(1024), b varchar(1024) as (UpdateXML(a,'/a','<e>fff</e>')));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+#
+# Sub-selects
+#
+create table t1 (a int);
+create table t2 (a int, b int as (select count(*) from t1));
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from t1))' at line 1
+drop table t1;
+create table t1 (a int, b int as ((select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+create table t1 (a int, b int as (a+(select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+#
+# SP functions
+#
+drop function if exists sub1;
+create function sub1(i int) returns int deterministic
+return i+1;
+select sub1(1);
+sub1(1)
+2
+create table t1 (a int, b int as (a+sub3(1)));
+ERROR HY000: Function or expression is not allowed for column 'b'.
+drop function sub1;
+#
+# Long expression
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+drop table t1;
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+ERROR HY000: String 'concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long for VIRTUAL COLUMN EXPRESSION (should be no longer than 252)
+#
+# Constant expression
+create table t1 (a int as (PI()));
+ERROR HY000: Constant expression in computed column function is not allowed.
=== added file 'mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,146 @@
+SET @@session.storage_engine = 'InnoDB';
+#
+# Section 1. Wrong column definition options
+# - NOT NULL
+# - NULL
+# - DEFAULT <value>
+# - AUTO_INCREMENT
+# - [PRIMARY] KEY
+# NOT NULL
+create table t1 (a int, b int as (a+1) not null);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) not null;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not null' at line 1
+drop table t1;
+# NULL
+create table t1 (a int, b int as (a+1) null);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) null;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null' at line 1
+drop table t1;
+# DEFAULT
+create table t1 (a int, b int as (a+1) default 0);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default 0)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) default 0;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default 0' at line 1
+drop table t1;
+# AUTO_INCREMENT
+create table t1 (a int, b int as (a+1) AUTO_INCREMENT);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AUTO_INCREMENT)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) AUTO_INCREMENT;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AUTO_INCREMENT' at line 1
+drop table t1;
+# [PRIMARY] KEY
+create table t1 (a int, b int as (a+1) key);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key)' at line 1
+create table t1 (a int, b int as (a+1) primary key);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'primary key)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) key;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key' at line 1
+alter table t1 add column b int as (a+1) primary key;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'primary key' at line 1
+drop table t1;
+# Section 2. Other column definition options
+# - COMMENT
+# - REFERENCES (only syntax testing here)
+# - STORED (only systax testing here)
+create table t1 (a int, b int as (a % 2) comment 'my comment');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) comment 'my comment';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t2;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t2 (a) values (1);
+select * from t2;
+a b
+1 1
+insert into t2 values (2,default);
+select a,b from t2;
+a b
+1 1
+2 0
+drop table t2;
+drop table t1;
+create table t1 (a int, b int as (a % 2) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+drop table t1;
+create table t2 (a int);
+create table t1 (a int, b int as (a % 2) persistent references t2(a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent references t2(a);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'references t2(a)' at line 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,146 @@
+SET @@session.storage_engine = 'MyISAM';
+#
+# Section 1. Wrong column definition options
+# - NOT NULL
+# - NULL
+# - DEFAULT <value>
+# - AUTO_INCREMENT
+# - [PRIMARY] KEY
+# NOT NULL
+create table t1 (a int, b int as (a+1) not null);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) not null;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not null' at line 1
+drop table t1;
+# NULL
+create table t1 (a int, b int as (a+1) null);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) null;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null' at line 1
+drop table t1;
+# DEFAULT
+create table t1 (a int, b int as (a+1) default 0);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default 0)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) default 0;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default 0' at line 1
+drop table t1;
+# AUTO_INCREMENT
+create table t1 (a int, b int as (a+1) AUTO_INCREMENT);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AUTO_INCREMENT)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) AUTO_INCREMENT;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AUTO_INCREMENT' at line 1
+drop table t1;
+# [PRIMARY] KEY
+create table t1 (a int, b int as (a+1) key);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key)' at line 1
+create table t1 (a int, b int as (a+1) primary key);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'primary key)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) key;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key' at line 1
+alter table t1 add column b int as (a+1) primary key;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'primary key' at line 1
+drop table t1;
+# Section 2. Other column definition options
+# - COMMENT
+# - REFERENCES (only syntax testing here)
+# - STORED (only systax testing here)
+create table t1 (a int, b int as (a % 2) comment 'my comment');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) comment 'my comment';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t2;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t2 (a) values (1);
+select * from t2;
+a b
+1 1
+insert into t2 values (2,default);
+select a,b from t2;
+a b
+1 1
+2 0
+drop table t2;
+drop table t1;
+create table t1 (a int, b int as (a % 2) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+drop table t1;
+create table t2 (a int);
+create table t1 (a int, b int as (a % 2) persistent references t2(a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent references t2(a);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'references t2(a)' at line 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_csv.result'
--- a/mysql-test/suite/vcol/r/vcol_csv.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_csv.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'CSV';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+create table t1 (a int not null);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_handler_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_handler_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_handler_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,76 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+d char(1),
+index (a),
+index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+a b c d
+4 -4 -4 a
+2 -2 -2 b
+1 -1 -1 c
+3 -3 -3 d
+# HANDLER tbl_name OPEN
+handler t1 open;
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+a b c d
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+a b c d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+a b c d
+# HANDLER tbl_name CLOSE
+handler t1 close;
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_handler_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_handler_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_handler_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,76 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+d char(1),
+index (a),
+index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+a b c d
+4 -4 -4 a
+2 -2 -2 b
+1 -1 -1 c
+3 -3 -3 d
+# HANDLER tbl_name OPEN
+handler t1 open;
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+a b c d
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+a b c d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+a b c d
+# HANDLER tbl_name CLOSE
+handler t1 close;
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,427 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+set sql_warnings = 1;
+#
+# *** INSERT ***
+#
+# INSERT INTO tbl_name VALUES... DEFAULT is specified against vcols
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... NULL is specified against vcols
+insert into t1 values (1,null,null);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... a non-NULL value is specified against vcols
+insert into t1 values (1,2,3);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored.
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<non_vcol_list>) VALUES...
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... DEFAULT is specified
+# against vcols
+insert into t1 (a,b) values (1,default), (2,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... NULL is specified against vcols
+insert into t1 (a,b) values (1,null), (2,null);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... a non-NULL value is specified
+# against vcols
+insert into t1 (a,b) values (1,3), (2,4);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored.
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# Table with UNIQUE non-vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int unique,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+delete from t1 where b in (1,2);
+select * from t1;
+a b c
+2 -2 -2
+drop table t1;
+# Table with UNIQUE vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+# CREATE new_table ... LIKE old_table
+# INSERT INTO new_table SELECT * from old_table
+create table t2 like t1;
+insert into t2 select * from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored.
+Warning 1645 The value specified for computed column 'c' in table 't2' ignored.
+select * from t1;
+a b c
+2 -2 -2
+drop table t2;
+# CREATE new_table ... LIKE old_table INSERT INTO new_table (<non-vcols>, <vcols>)
+# SELECT <non-vcols>, <vcols> from old_table
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+2 -2 -2
+1 -1 -1
+create table t2 like t1;
+insert into t2 (a,b) select a,b from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored.
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored.
+select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+drop table t2;
+drop table t1;
+#
+# *** UPDATE ***
+#
+# UPDATE tbl_name SET non-vcol=expr WHERE non-vcol=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where a=2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE non-vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where a=2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where b=-2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=const
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# No INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where c between -1 and 0
+order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1 where c between -6 and 0;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol LIMIT 2
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where c between -1 and 0
+order by c limit 2;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1 where c between -2 and 0 order by c;
+select * from t1;
+a b c
+6 -6 -6
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1);
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+# ORDER BY indexed vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1) order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+drop table t1;
+#
+# Verify ON UPDATE/DELETE actions of FOREIGN KEYs
+create table t2 (a int primary key, name varchar(10));
+create table t1 (a int primary key, b int as (a % 10) persistent);
+insert into t2 values (1, 'value1'), (2,'value2'), (3,'value3');
+insert into t1 (a) values (1),(2),(3);
+select * from t1;
+a b
+1 1
+2 2
+3 3
+select * from t2;
+a name
+1 value1
+2 value2
+3 value3
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+# - ON UPDATE RESTRICT
+alter table t1 add foreign key (b) references t2(a) on update restrict;
+insert into t1 (a) values (4);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+update t2 set a=4 where a=3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+alter table t1 drop foreign key t1_ibfk_1;
+# - ON DELETE RESTRICT
+alter table t1 add foreign key (b) references t2(a) on delete restrict;
+delete from t2 where a=3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+alter table t1 drop foreign key t1_ibfk_1;
+# - ON DELETE CASCADE
+alter table t1 add foreign key (b) references t2(a) on delete cascade;
+delete from t2 where a=3;
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+a b name
+1 1 value1
+2 2 value2
+alter table t1 drop foreign key t1_ibfk_1;
+drop table t1;
+drop table t2;
+#
+# *** REPLACE ***
+#
+# UNIQUE INDEX on vcol
+# REPLACE tbl_name (non-vcols) VALUES (non-vcols);
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique,
+d varchar(16));
+insert into t1 (a,d) values (1,'a'), (2,'b');
+select * from t1;
+a b c d
+1 -1 -1 a
+2 -2 -2 b
+replace t1 (a,d) values (1,'c');
+select * from t1;
+a b c d
+1 -1 -1 c
+2 -2 -2 b
+delete from t1;
+select * from t1;
+a b c d
+set sql_warnings = 0;
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,365 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+set sql_warnings = 1;
+#
+# *** INSERT ***
+#
+# INSERT INTO tbl_name VALUES... DEFAULT is specified against vcols
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... NULL is specified against vcols
+insert into t1 values (1,null,null);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... a non-NULL value is specified against vcols
+insert into t1 values (1,2,3);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored.
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<non_vcol_list>) VALUES...
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... DEFAULT is specified
+# against vcols
+insert into t1 (a,b) values (1,default), (2,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... NULL is specified against vcols
+insert into t1 (a,b) values (1,null), (2,null);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... a non-NULL value is specified
+# against vcols
+insert into t1 (a,b) values (1,3), (2,4);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored.
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# Table with UNIQUE non-vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int unique,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+delete from t1 where b in (1,2);
+select * from t1;
+a b c
+2 -2 -2
+drop table t1;
+# Table with UNIQUE vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+# CREATE new_table ... LIKE old_table
+# INSERT INTO new_table SELECT * from old_table
+create table t2 like t1;
+insert into t2 select * from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored.
+Warning 1645 The value specified for computed column 'c' in table 't2' ignored.
+select * from t1;
+a b c
+2 -2 -2
+drop table t2;
+# CREATE new_table ... LIKE old_table INSERT INTO new_table (<non-vcols>, <vcols>)
+# SELECT <non-vcols>, <vcols> from old_table
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+2 -2 -2
+1 -1 -1
+create table t2 like t1;
+insert into t2 (a,b) select a,b from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored.
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored.
+select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+drop table t2;
+drop table t1;
+#
+# *** UPDATE ***
+#
+# UPDATE tbl_name SET non-vcol=expr WHERE non-vcol=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where a=2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE non-vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where a=2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where b=-2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored.
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=const
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# No INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where c between -1 and 0
+order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1 where c between -6 and 0;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol LIMIT 2
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+5 -5 -5
+4 -4 -4
+3 -3 -3
+2 -2 -2
+1 -1 -1
+update t1 set a=6 where c between -1 and 0
+order by c limit 2;
+select * from t1;
+a b c
+5 -5 -5
+4 -4 -4
+3 -3 -3
+2 -2 -2
+6 -6 -6
+delete from t1 where c between -2 and 0 order by c;
+select * from t1;
+a b c
+5 -5 -5
+4 -4 -4
+3 -3 -3
+6 -6 -6
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1);
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+# ORDER BY indexed vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1) order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+drop table t1;
+#
+# *** REPLACE ***
+#
+# UNIQUE INDEX on vcol
+# REPLACE tbl_name (non-vcols) VALUES (non-vcols);
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique,
+d varchar(16));
+insert into t1 (a,d) values (1,'a'), (2,'b');
+select * from t1;
+a b c d
+1 -1 -1 a
+2 -2 -2 b
+replace t1 (a,d) values (1,'c');
+select * from t1;
+a b c d
+1 -1 -1 c
+2 -2 -2 b
+delete from t1;
+select * from t1;
+a b c d
+set sql_warnings = 0;
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_keys_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,151 @@
+SET @@session.storage_engine = 'InnoDB';
+# - UNIQUE KEY
+# - INDEX
+# - FULLTEXT INDEX
+# - SPATIAL INDEX (not supported)
+# - FOREIGN INDEX (partially supported)
+# - CHECK (allowed but not used)
+# UNIQUE
+create table t1 (a int, b int as (a*2) unique);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2) persistent unique);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2), unique key (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2) persistent, unique (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add unique key (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add unique key (b);
+drop table t1;
+# Testing data manipulation operations involving UNIQUE keys
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# INDEX
+create table t1 (a int, b int as (a*2), index (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2), index (a,b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2) persistent, index (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `b` (`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES MUL NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent, index (a,b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `a` (`a`,`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES MUL NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add index (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+alter table t1 add index (a,b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (b);
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (a,b);
+create table t2 like t1;
+drop table t2;
+drop table t1;
+# Testing data manipulation operations involving INDEX
+# on virtual columns can be found in:
+# - vcol_select.inc
+#
+# TODO: FULLTEXT INDEX
+# SPATIAL INDEX
+# FOREIGN KEY
+# Rejected FK options.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update set null);
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update cascade);
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on delete set null);
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column.
+create table t1 (a int, b int as (a+1) persistent);
+alter table t1 add foreign key (b) references t2(a) on update set null;
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column.
+alter table t1 add foreign key (b) references t2(a) on update cascade;
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column.
+alter table t1 add foreign key (b) references t2(a) on delete set null;
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column.
+drop table t1;
+create table t1 (a int, b int as (a+1),
+foreign key (b) references t2(a));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a+1));
+alter table t1 add foreign key (b) references t2(a);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+drop table t1;
+# Allowed FK options.
+create table t2 (a int primary key, b char(5));
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update no action);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete cascade);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete no action);
+drop table t1;
+
+# Testing data manipulation operations involving FOREIGN KEY
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# TODO: CHECK
=== added file 'mysql-test/suite/vcol/r/vcol_keys_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,158 @@
+SET @@session.storage_engine = 'MyISAM';
+# - UNIQUE KEY
+# - INDEX
+# - FULLTEXT INDEX
+# - SPATIAL INDEX (not supported)
+# - FOREIGN INDEX (partially supported)
+# - CHECK (allowed but not used)
+# UNIQUE
+create table t1 (a int, b int as (a*2) unique);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2) persistent unique);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2), unique key (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2) persistent, unique (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add unique key (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add unique key (b);
+drop table t1;
+# Testing data manipulation operations involving UNIQUE keys
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# INDEX
+create table t1 (a int, b int as (a*2), index (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2), index (a,b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a*2) persistent, index (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES MUL NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent, index (a,b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES MUL NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add index (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+alter table t1 add index (a,b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (b);
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (a,b);
+create table t2 like t1;
+drop table t2;
+drop table t1;
+# Testing data manipulation operations involving INDEX
+# on virtual columns can be found in:
+# - vcol_select.inc
+#
+# TODO: FULLTEXT INDEX
+# SPATIAL INDEX
+# Error "All parts of a SPATIAL index must be NOT NULL"
+create table t1 (a int, b int as (a+1) persistent, spatial index (b));
+ERROR 42000: All parts of a SPATIAL index must be NOT NULL
+create table t1 (a int, b int as (a+1) persistent);
+alter table t1 add spatial index (b);
+ERROR 42000: All parts of a SPATIAL index must be NOT NULL
+drop table t1;
+# FOREIGN KEY
+# Rejected FK options.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update set null);
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update cascade);
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on delete set null);
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column.
+create table t1 (a int, b int as (a+1) persistent);
+alter table t1 add foreign key (b) references t2(a) on update set null;
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column.
+alter table t1 add foreign key (b) references t2(a) on update cascade;
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column.
+alter table t1 add foreign key (b) references t2(a) on delete set null;
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column.
+drop table t1;
+create table t1 (a int, b int as (a+1),
+foreign key (b) references t2(a));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+create table t1 (a int, b int as (a+1));
+alter table t1 add foreign key (b) references t2(a);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column.
+drop table t1;
+# Allowed FK options.
+create table t2 (a int primary key, b char(5));
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update no action);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete cascade);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete no action);
+drop table t1;
+
+# Testing data manipulation operations involving FOREIGN KEY
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# TODO: CHECK
=== added file 'mysql-test/suite/vcol/r/vcol_memory.result'
--- a/mysql-test/suite/vcol/r/vcol_memory.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_memory.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'memory';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+create table t1 (a int);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_merge.result'
--- a/mysql-test/suite/vcol/r/vcol_merge.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_merge.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,8 @@
+drop table if exists t1, t2, t3;
+create table t1 (a int, b int as (a % 10));
+create table t2 (a int, b int as (a % 10));
+insert into t1 values (1,default);
+insert into t2 values (2,default);
+create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns.
+drop table t1,t2;
=== added file 'mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,242 @@
+SET @@session.storage_engine = 'InnoDB';
+# Case 1. All non-stored columns.
+# This scenario is currently impossible due to the fact that virtual columns
+# with a constant expression are not allowed.
+# Case 2. CREATE
+# - Column1: "real"
+# - Column 2: virtual non-stored
+create table t1 (a int, b int as (-a));
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 3. CREATE
+# - Column1: "real"
+# - Column 2: virtual stored
+create table t1 (a int, b int as (-a) persistent);
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 4. CREATE
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 5. CREATE
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 6. CREATE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t1;
+# Case 7. ALTER. Modify virtual stored -> virtual non-stored
+create table t1 (a int, b int as (a % 2) persistent);
+alter table t1 modify b int as (a % 2);
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns.
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 8. ALTER. Modify virtual non-stored -> virtual stored
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent;
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns.
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 9. CREATE LIKE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+create table t2 like t1;
+insert into t2 values (1,default,default);
+select * from t2;
+a b c
+1 -1 -1
+insert into t2 values (2,default,default);
+select * from t2;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t2;
+drop table t1;
+# Case 10. ALTER. Dropping a virtual non-stored column.
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int, c varchar(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(5) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 11. ALTER. Dropping a virtual stored column.
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int, c char(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` char(5) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 12. ALTER. Adding a new virtual non-stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) VIRTUAL,
+ `b` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 13. ALTER. Adding a new virtual stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) persistent after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) PERSISTENT,
+ `b` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 14. ALTER. Changing the expression of a virtual stored column.
+create table t1 (a int, b datetime, c int as (week(b)) persistent);
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1)) persistent;
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 15. ALTER. Changing the expression of a virtual non-stored column.
+create table t1 (a int, b datetime, c int as (week(b)));
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1));
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,242 @@
+SET @@session.storage_engine = 'MyISAM';
+# Case 1. All non-stored columns.
+# This scenario is currently impossible due to the fact that virtual columns
+# with a constant expression are not allowed.
+# Case 2. CREATE
+# - Column1: "real"
+# - Column 2: virtual non-stored
+create table t1 (a int, b int as (-a));
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 3. CREATE
+# - Column1: "real"
+# - Column 2: virtual stored
+create table t1 (a int, b int as (-a) persistent);
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 4. CREATE
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 5. CREATE
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 6. CREATE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t1;
+# Case 7. ALTER. Modify virtual stored -> virtual non-stored
+create table t1 (a int, b int as (a % 2) persistent);
+alter table t1 modify b int as (a % 2);
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns.
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 8. ALTER. Modify virtual non-stored -> virtual stored
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent;
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns.
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 9. CREATE LIKE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+create table t2 like t1;
+insert into t2 values (1,default,default);
+select * from t2;
+a b c
+1 -1 -1
+insert into t2 values (2,default,default);
+select * from t2;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t2;
+drop table t1;
+# Case 10. ALTER. Dropping a virtual non-stored column.
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int, c varchar(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 11. ALTER. Dropping a virtual stored column.
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int, c char(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` char(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 12. ALTER. Adding a new virtual non-stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) VIRTUAL,
+ `b` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 13. ALTER. Adding a new virtual stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) persistent after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) PERSISTENT,
+ `b` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 14. ALTER. Changing the expression of a virtual stored column.
+create table t1 (a int, b datetime, c int as (week(b)) persistent);
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1)) persistent;
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 15. ALTER. Changing the expression of a virtual non-stored column.
+create table t1 (a int, b datetime, c int as (week(b)));
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1));
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_partition_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_partition_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_partition_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,58 @@
+SET @@session.storage_engine = 'InnoDB';
+drop table if exists t1;
+# Case 1. Partitioning by RANGE based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY RANGE( b ) (
+PARTITION p0 VALUES LESS THAN (2006),
+PARTITION p2 VALUES LESS THAN (2008)
+);
+insert into t1 values ('2006-01-01',default);
+insert into t1 values ('2007-01-01',default);
+insert into t1 values ('2005-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+2007-01-01 2007
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+2007-01-01 2006
+drop table t1;
+# Case 2. Partitioning by LIST based on a stored virtual column.
+CREATE TABLE t1 (a int, b int as (a % 3 ) persistent)
+PARTITION BY LIST (a+1)
+(PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 1
+select * from t1;
+a b
+1 1
+drop table t1;
+# Case 3. Partitioning by HASH based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY HASH( b % 3 ) PARTITIONS 3;
+insert into t1 values ('2005-01-01',default);
+insert into t1 values ('2006-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_partition_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_partition_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_partition_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,75 @@
+SET @@session.storage_engine = 'MyISAM';
+drop table if exists t1;
+# Case 1. Partitioning by RANGE based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY RANGE( b ) (
+PARTITION p0 VALUES LESS THAN (2006),
+PARTITION p2 VALUES LESS THAN (2008)
+);
+insert into t1 values ('2006-01-01',default);
+insert into t1 values ('2007-01-01',default);
+insert into t1 values ('2005-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+2007-01-01 2007
+# Check how data is physically partitioned.
+7 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p0.MYD
+14 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p2.MYD
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+2007-01-01 2006
+# Check how data is physically partitioned.
+14 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p0.MYD
+7 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p2.MYD
+drop table t1;
+# Case 2. Partitioning by LIST based on a stored virtual column.
+CREATE TABLE t1 (a int, b int as (a % 3 ) persistent)
+PARTITION BY LIST (a+1)
+(PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
+insert into t1 values (1,default);
+# Check how data is physically partitioned.
+0 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p1.MYD
+9 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p2.MYD
+select * from t1;
+a b
+1 1
+select * from t1;
+a b
+1 1
+drop table t1;
+# Case 3. Partitioning by HASH based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY HASH( b % 3 ) PARTITIONS 3;
+insert into t1 values ('2005-01-01',default);
+insert into t1 values ('2006-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+# Check how data is physically partitioned.
+0 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p0.MYD
+7 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p1.MYD
+7 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p2.MYD
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+# Check how data is physically partitioned.
+7 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p0.MYD
+7 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p1.MYD
+0 MYSQLTEST_VARDIR/mysqld.1/data/test/t1#P#p2.MYD
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_select_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_select_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_select_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,264 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+index (c));
+insert into t1 (a) values (2), (1), (1), (3), (NULL);
+create table t2 like t1;
+insert into t2 (a) values (1);
+create table t3 (a int primary key,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t3 (a) values (2),(1),(3);
+# select_type=SIMPLE, type=system
+select * from t2;
+a b c
+1 -1 -1
+explain select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1
+select * from t2 where c=-1;
+a b c
+1 -1 -1
+explain select * from t2 where c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c c 5 const 1 Using where
+# select_type=SIMPLE, type=ALL
+select * from t1 where b=-1;
+a b c
+1 -1 -1
+1 -1 -1
+explain select * from t1 where b=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+# select_type=SIMPLE, type=const
+select * from t3 where a=1;
+a b c
+1 -1 -1
+explain select * from t3 where a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1
+# select_type=SIMPLE, type=range
+select * from t3 where c>=-1;
+a b c
+1 -1 -1
+explain select * from t3 where c>=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# select_type=SIMPLE, type=ref
+select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+a b c a b c
+1 -1 -1 1 -1 -1
+1 -1 -1 1 -1 -1
+explain select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const c c 5 const 1
+1 SIMPLE t1 ref c c 5 const 2 Using where
+# select_type=PRIMARY, type=index,ALL
+select * from t1 where b in (select c from t3);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+explain select * from t1 where b in (select c from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 1 Using index; Using where
+# select_type=PRIMARY, type=range,ref
+select * from t1 where c in (select c from t3 where c between -2 and -1);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+explain select * from t1 where c in (select c from t3 where c between -2 and -1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 1 Using index; Using where
+# select_type=UNION, type=system
+# select_type=UNION RESULT, type=<union1,2>
+select * from t1 union select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from t1 union select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+2 UNION t2 ALL NULL NULL NULL NULL 1
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
+# select_type=DERIVED, type=system
+select * from (select a,b,c from t1) as t11;
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from (select a,b,c from t1) as t11;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED t1 ALL NULL NULL NULL NULL 5
+###
+### Using aggregate functions with/without DISTINCT
+###
+# SELECT COUNT(*) FROM tbl_name
+select count(*) from t1;
+count(*)
+5
+explain select count(*) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+# SELECT COUNT(DISTINCT <non-vcol>) FROM tbl_name
+select count(distinct a) from t1;
+count(distinct a)
+3
+explain select count(distinct a) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <non-stored vcol>) FROM tbl_name
+select count(distinct b) from t1;
+count(distinct b)
+3
+explain select count(distinct b) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <stored vcol>) FROM tbl_name
+select count(distinct c) from t1;
+count(distinct c)
+3
+explain select count(distinct c) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+###
+### filesort & range-based utils
+###
+# SELECT * FROM tbl_name WHERE <vcol expr>
+select * from t3 where c >= -2;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c >= -2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr>
+select * from t3 where a between 1 and 2;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where a between 1 and 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
+select * from t3 where b between -2 and -1;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where b between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where
+# SELECT * FROM tbl_name WHERE <indexed vcol expr>
+select * from t3 where c between -2 and -1;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where a between 1 and 2 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where a between 1 and 2 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
+select * from t3 where a between 1 and 2 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where a between 1 and 2 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
+select * from t3 where b between -2 and -1 order by a;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where b between -2 and -1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index NULL PRIMARY 4 NULL 3 Using where
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where b between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where c between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where b between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where c between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(b) from t1 group by b;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(c) from t1 group by c;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(b) from t1 group by c;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(c) from t1 group by b;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
=== added file 'mysql-test/suite/vcol/r/vcol_select_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_select_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_select_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,264 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+index (c));
+insert into t1 (a) values (2), (1), (1), (3), (NULL);
+create table t2 like t1;
+insert into t2 (a) values (1);
+create table t3 (a int primary key,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t3 (a) values (2),(1),(3);
+# select_type=SIMPLE, type=system
+select * from t2;
+a b c
+1 -1 -1
+explain select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+select * from t2 where c=-1;
+a b c
+1 -1 -1
+explain select * from t2 where c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system c NULL NULL NULL 1
+# select_type=SIMPLE, type=ALL
+select * from t1 where b=-1;
+a b c
+1 -1 -1
+1 -1 -1
+explain select * from t1 where b=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+# select_type=SIMPLE, type=const
+select * from t3 where a=1;
+a b c
+1 -1 -1
+explain select * from t3 where a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1
+# select_type=SIMPLE, type=range
+select * from t3 where c>=-1;
+a b c
+1 -1 -1
+explain select * from t3 where c>=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 2 Using where
+# select_type=SIMPLE, type=ref
+select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+a b c a b c
+1 -1 -1 1 -1 -1
+1 -1 -1 1 -1 -1
+explain select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const c c 5 const 1
+1 SIMPLE t1 ref c c 5 const 2 Using where
+# select_type=PRIMARY, type=index,ALL
+select * from t1 where b in (select c from t3);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+explain select * from t1 where b in (select c from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 2 Using index; Using where
+# select_type=PRIMARY, type=range,ref
+select * from t1 where c in (select c from t3 where c between -2 and -1);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+explain select * from t1 where c in (select c from t3 where c between -2 and -1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 2 Using index; Using where
+# select_type=UNION, type=system
+# select_type=UNION RESULT, type=<union1,2>
+select * from t1 union select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from t1 union select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+2 UNION t2 system NULL NULL NULL NULL 1
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
+# select_type=DERIVED, type=system
+select * from (select a,b,c from t1) as t11;
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from (select a,b,c from t1) as t11;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED t1 ALL NULL NULL NULL NULL 5
+###
+### Using aggregate functions with/without DISTINCT
+###
+# SELECT COUNT(*) FROM tbl_name
+select count(*) from t1;
+count(*)
+5
+explain select count(*) from t1;
+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 COUNT(DISTINCT <non-vcol>) FROM tbl_name
+select count(distinct a) from t1;
+count(distinct a)
+3
+explain select count(distinct a) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <non-stored vcol>) FROM tbl_name
+select count(distinct b) from t1;
+count(distinct b)
+3
+explain select count(distinct b) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <stored vcol>) FROM tbl_name
+select count(distinct c) from t1;
+count(distinct c)
+3
+explain select count(distinct c) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+###
+### filesort & range-based utils
+###
+# SELECT * FROM tbl_name WHERE <vcol expr>
+select * from t3 where c >= -2;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c >= -2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 2 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr>
+select * from t3 where a between 1 and 2;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where a between 1 and 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
+select * from t3 where b between -2 and -1;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where
+# SELECT * FROM tbl_name WHERE <indexed vcol expr>
+select * from t3 where c between -2 and -1;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
+select * from t3 where a between 1 and 2 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where a between 1 and 2 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
+select * from t3 where b between -2 and -1 order by a;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where b between -2 and -1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-vcol>
+select * from t3 where c between -2 and -1 order by a;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where c between -2 and -1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where b between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where c between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where b between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where c between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(b) from t1 group by b;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(c) from t1 group by c;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(b) from t1 group by c;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(c) from t1 group by b;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
=== added file 'mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,2942 @@
+SET @@session.storage_engine = 'InnoDB';
+#
+# NUMERIC FUNCTIONS
+#
+# ABS()
+set sql_warnings = 1;
+create table t1 (a int, b int as (abs(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (abs(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1, default);
+select * from t1;
+a b
+-1 1
+drop table t1;
+set sql_warnings = 0;
+# ACOS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(acos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(acos(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1, default);
+insert into t1 values (1.0001,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 0
+1.0001 NULL
+0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ASIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(asin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(asin(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (0.2, default);
+insert into t1 values (1.0001,default);
+select * from t1;
+a b
+0.2 0.201358
+1.0001 NULL
+drop table t1;
+set sql_warnings = 0;
+#ATAN
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan(a,b),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, c double as (format(atan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `c` double AS (format(atan(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-2,default);
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a c
+-2 -1.107149
+3.141593 1.262627
+drop table t1;
+set sql_warnings = 0;
+# ATAN2
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan2(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan2(a,b),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# CEIL()
+set sql_warnings = 1;
+create table t1 (a double, b int as (ceil(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (ceil(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 2
+-1.23 -1
+drop table t1;
+set sql_warnings = 0;
+# CONV()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int, c int, d varchar(10) as (conv(a,b,c)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (conv(a,b,c)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a',16,2,default);
+insert into t1 values ('6e',18,8,default);
+insert into t1 values (-17,10,-18,default);
+insert into t1 values (10+'10'+'10'+0xa,10,10,default);
+select * from t1;
+a b c d
+a 16 2 1010
+6e 18 8 172
+-17 10 -18 -H
+40 10 10 40
+drop table t1;
+set sql_warnings = 0;
+# COS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cos(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a b
+3.141593 -1
+drop table t1;
+set sql_warnings = 0;
+# COT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cot(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cot(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+12 -1.572673
+0 NULL
+drop table t1;
+set sql_warnings = 0;
+# CRC32()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (crc32(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (crc32(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('mysql',default);
+select * from t1;
+a b
+MySQL 3259397556
+mysql 2501908538
+drop table t1;
+set sql_warnings = 0;
+# DEGREES()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(degrees(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(degrees(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+3.141593 180.00002
+1.570796 89.999981
+drop table t1;
+set sql_warnings = 0;
+# /
+set sql_warnings = 1;
+create table t1 (a double, b double as (a/2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a/2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# EXP()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(exp(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(exp(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+2 7.389056
+-2 0.135335
+0 1
+drop table t1;
+set sql_warnings = 0;
+# FLOOR()
+set sql_warnings = 1;
+create table t1 (a double, b long as (floor(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` mediumtext AS (floor(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 1
+-1.23 -2
+drop table t1;
+set sql_warnings = 0;
+# LN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(ln(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(ln(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG()
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(log(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(log(a,b),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,65536,default);
+insert into t1 values (10,100,default);
+insert into t1 values (1,100,default);
+select * from t1;
+a b c
+2 65536 16
+10 100 2
+1 100 NULL
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG2()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log2(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log2(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (65536,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+65536 16
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG10()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log10(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log10(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (100,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+2 0.30103
+100 2
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# -
+set sql_warnings = 1;
+create table t1 (a double, b double as (a-1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a-1) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# MOD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (mod(a,10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (mod(a,10)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# %
+set sql_warnings = 1;
+create table t1 (a int, b int as (a % 10));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 10) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# OCT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(10) as (oct(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(10) AS (oct(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 14
+drop table t1;
+set sql_warnings = 0;
+# PI()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(PI()*a*a,6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(PI()*a*a,6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 3.141593
+drop table t1;
+set sql_warnings = 0;
+# +
+set sql_warnings = 1;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 2
+drop table t1;
+set sql_warnings = 0;
+# POW, POWER
+set sql_warnings = 1;
+create table t1 (a int, b int as (pow(a,2)), c int as (power(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (pow(a,2)) VIRTUAL,
+ `c` int(11) AS (power(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default,default);
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 1 1
+2 4 4
+drop table t1;
+set sql_warnings = 0;
+# RADIANS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(radians(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(radians(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (90,default);
+select * from t1;
+a b
+90 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ROUND()
+set sql_warnings = 1;
+create table t1 (a double, b int as (round(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (round(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1.23,default);
+insert into t1 values (-1.58,default);
+insert into t1 values (1.58,default);
+select * from t1;
+a b
+-1.23 -1
+-1.58 -2
+1.58 2
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double, c int as (round(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` int(11) AS (round(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.298,1,default);
+insert into t1 values (1.298,0,default);
+insert into t1 values (23.298,-1,default);
+select * from t1;
+a b c
+1.298 1 1
+1.298 0 1
+23.298 -1 20
+drop table t1;
+set sql_warnings = 0;
+# SIGN()
+set sql_warnings = 1;
+create table t1 (a double, b int as (sign(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (sign(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-32,default);
+insert into t1 values (0,default);
+insert into t1 values (234,default);
+select * from t1;
+a b
+-32 -1
+0 0
+234 1
+drop table t1;
+set sql_warnings = 0;
+# SIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sin(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+1.570796 1
+drop table t1;
+set sql_warnings = 0;
+# SQRT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sqrt(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sqrt(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (4,default);
+insert into t1 values (20,default);
+insert into t1 values (-16,default);
+select * from t1;
+a b
+4 2
+20 4.472136
+-16 NULL
+drop table t1;
+set sql_warnings = 0;
+# TAN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(tan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(tan(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()+1,6),default);
+select * from t1;
+a b
+3.141593 0
+4.141593 1.557409
+drop table t1;
+set sql_warnings = 0;
+# *
+set sql_warnings = 1;
+create table t1 (a double, b double as (a*3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a*3) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 0
+1 3
+2 6
+drop table t1;
+set sql_warnings = 0;
+# TRUNCATE()
+set sql_warnings = 1;
+create table t1 (a double, b double as (truncate(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (truncate(a,4)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.223,default);
+insert into t1 values (1.999,default);
+insert into t1 values (1.999,default);
+insert into t1 values (122,default);
+select * from t1;
+a b
+1.223 1.223
+1.999 1.999
+1.999 1.999
+122 122
+drop table t1;
+set sql_warnings = 0;
+# Unary -
+set sql_warnings = 1;
+create table t1 (a double, b double as (-a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (-a) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 -1
+-1 1
+drop table t1;
+set sql_warnings = 0;
+#
+# STRING FUNCTIONS
+#
+# ASCII()
+set sql_warnings = 1;
+create table t1 (a char(2), b int as (ascii(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(2) DEFAULT NULL,
+ `b` int(11) AS (ascii(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+insert into t1 values (2,default);
+insert into t1 values ('dx',default);
+select * from t1;
+a b
+2 50
+2 50
+dx 100
+drop table t1;
+set sql_warnings = 0;
+# BIN()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (bin(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (bin(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 1100
+drop table t1;
+set sql_warnings = 0;
+# BIT_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (bit_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (bit_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 32
+drop table t1;
+set sql_warnings = 0;
+# CHAR_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (char_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (char_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CHAR()
+set sql_warnings = 1;
+create table t1 (a int, b int, c varbinary(10) as (char(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` varbinary(10) AS (char(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (77,121,default);
+select * from t1;
+a b c
+77 121 My
+drop table t1;
+set sql_warnings = 0;
+# CHARACTER_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (character_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (character_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CONCAT_WS()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat_ws(',',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat_ws(',',a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# CONCAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat(a,',',b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat(a,',',b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# ELT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(10) as (elt(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (elt(c,a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',1,default);
+insert into t1 values ('value1','value2',2,default);
+select * from t1;
+a b c d
+value1 value2 1 value1
+value1 value2 2 value2
+drop table t1;
+set sql_warnings = 0;
+# EXPORT_SET()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (export_set(a,'1','0','',10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (export_set(a,'1','0','',10)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (6,default);
+select * from t1;
+a b
+6 0110000000
+drop table t1;
+set sql_warnings = 0;
+# FIELD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (field('aa',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (field('aa',a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('aa','bb',default);
+insert into t1 values ('bb','aa',default);
+select * from t1;
+a b c
+aa bb 1
+bb aa 2
+drop table t1;
+set sql_warnings = 0;
+# FIND_IN_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (find_in_set(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (find_in_set(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('aa','aa,bb,cc',default);
+insert into t1 values ('aa','bb,aa,cc',default);
+select * from t1;
+a b c
+aa aa,bb,cc 1
+aa bb,aa,cc 2
+drop table t1;
+set sql_warnings = 0;
+# FORMAT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(20) as (format(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(20) AS (format(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12332.123456,default);
+select * from t1;
+a b
+12332.123456 12,332.12
+drop table t1;
+set sql_warnings = 0;
+# HEX()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (17,default);
+select * from t1;
+a b
+17 11
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 616263
+drop table t1;
+set sql_warnings = 0;
+# INSERT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (insert(a,length(a),length(b),b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (insert(a,length(a),length(b),b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('start,','end',default);
+select * from t1;
+a b c
+start, end startend
+drop table t1;
+set sql_warnings = 0;
+# INSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (instr(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (instr(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar,','bar',default);
+insert into t1 values ('xbar,','foobar',default);
+select * from t1;
+a b c
+foobarbar, bar 4
+xbar, foobar 0
+drop table t1;
+set sql_warnings = 0;
+# LCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lcase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lcase(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LEFT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(5) as (left(a,5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(5) AS (left(a,5)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fooba
+drop table t1;
+set sql_warnings = 0;
+# LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a like 'H%o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# LOCATE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (locate('bar',a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (locate('bar',a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# LOWER()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lower(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lower(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lpad(a,4,' ')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lpad(a,4,' ')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('M',default);
+select * from t1;
+a b
+MySQL MySQ
+M M
+drop table t1;
+set sql_warnings = 0;
+# LTRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (ltrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (ltrim(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (' MySQL',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+ MySQL MySQL
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# MAKE_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(30) as (make_set(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(30) AS (make_set(c,a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',1,default);
+insert into t1 values ('a','b',3,default);
+select * from t1;
+a b c d
+a b 1 a
+a b 3 a,b
+drop table t1;
+set sql_warnings = 0;
+# MID()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (mid(a,1,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (mid(a,1,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fo
+drop table t1;
+set sql_warnings = 0;
+# NOT LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not like 'H%o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 0
+MySQL 1
+drop table t1;
+set sql_warnings = 0;
+# NOT REGEXP
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not regexp 'H.+o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 0
+hello 0
+drop table t1;
+set sql_warnings = 0;
+# OCTET_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (octet_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (octet_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# ORD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (ord(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (ord(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+select * from t1;
+a b
+2 50
+drop table t1;
+set sql_warnings = 0;
+# POSITION()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (position('bar' in a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (position('bar' in a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# QUOTE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (quote(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (quote(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Don\'t',default);
+select * from t1;
+a b
+Don't 'Don\'t'
+drop table t1;
+set sql_warnings = 0;
+# REGEXP()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a regexp 'H.+o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 1
+hello 1
+drop table t1;
+set sql_warnings = 0;
+# REPEAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (repeat(a,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (repeat(a,3)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQLMySQLMySQL
+drop table t1;
+set sql_warnings = 0;
+# REPLACE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (replace(a,'aa','bb')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (replace(a,'aa','bb')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa mbb
+drop table t1;
+set sql_warnings = 0;
+# REVERSE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (reverse(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (reverse(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa aam
+drop table t1;
+set sql_warnings = 0;
+# RIGHT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (right(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (right(a,4)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar rbar
+drop table t1;
+set sql_warnings = 0;
+# RLIKE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a rlike 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a rlike 'H.+o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# RPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rpad(a,4,'??')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rpad(a,4,'??')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('He',default);
+select * from t1;
+a b
+He He??
+drop table t1;
+set sql_warnings = 0;
+# RTRIM();
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rtrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rtrim(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello ',default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# SOUNDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(20) as (soundex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(20) AS (soundex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello H400
+drop table t1;
+set sql_warnings = 0;
+# SOUNDS LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a sounds like b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a sounds like b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello',default);
+insert into t1 values ('Hello','MySQL',default);
+insert into t1 values ('Hello','hello',default);
+select * from t1;
+a b c
+Hello Hello 1
+Hello MySQL 0
+Hello hello 1
+drop table t1;
+set sql_warnings = 0;
+# SPACE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (concat(a,space(5))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (concat(a,space(5))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello', default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# STRCMP()
+set sql_warnings = 1;
+create table t1 (a varchar(9), b varchar(9), c tinyint(1) as (strcmp(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(9) DEFAULT NULL,
+ `b` varchar(9) DEFAULT NULL,
+ `c` tinyint(1) AS (strcmp(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello', default);
+insert into t1 values ('Hello','Hello1', default);
+select * from t1;
+a b c
+Hello Hello 0
+Hello Hello1 -1
+drop table t1;
+set sql_warnings = 0;
+# SUBSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substr(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substr(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello ello
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING_INDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (substring_index(a,'.',2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (substring_index(a,'.',2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('www.mysql.com',default);
+select * from t1;
+a b
+www.mysql.com www.mysql
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substring(a from 2 for 2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substring(a from 2 for 2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello el
+drop table t1;
+set sql_warnings = 0;
+# TRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (trim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (trim(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (' aa ',default);
+select * from t1;
+a b
+ aa aa
+drop table t1;
+set sql_warnings = 0;
+# UCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (ucase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (ucase(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+# UNHEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (unhex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (unhex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('4D7953514C',default);
+select * from t1;
+a b
+4D7953514C MySQL
+drop table t1;
+set sql_warnings = 0;
+# UPPER()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (upper(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (upper(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+#
+# CONTROL FLOW FUNCTIONS
+#
+# CASE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(16) as (case a when NULL then 'asd' when 'b' then 'B' else a end));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(16) AS (case a when NULL then 'asd' when 'b' then 'B' else a end) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (NULL,default);
+insert into t1 values ('b',default);
+insert into t1 values ('c',default);
+select * from t1;
+a b
+NULL NULL
+b B
+c c
+drop table t1;
+set sql_warnings = 0;
+# IF
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (if(a=1,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (if(a=1,a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,2,default);
+insert into t1 values (3,4,default);
+select * from t1;
+a b c
+1 2 1
+3 4 4
+drop table t1;
+set sql_warnings = 0;
+# IFNULL
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(10) as (ifnull(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(10) AS (ifnull(a,'DEFAULT')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (NULL,'adf',default);
+insert into t1 values ('a','adf',default);
+select * from t1;
+a b c
+NULL adf DEFAULT
+a adf a
+drop table t1;
+set sql_warnings = 0;
+# NULLIF
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (nullif(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (nullif(a,'DEFAULT')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('DEFAULT',default);
+insert into t1 values ('a',default);
+select * from t1;
+a b
+DEFAULT NULL
+a a
+drop table t1;
+set sql_warnings = 0;
+#
+# OPERATORS
+#
+# AND, &&
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a>0 && a<2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a>0 && a<2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a between 0 and 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BINARY
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varbinary(10) as (binary a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varbinary(10) AS (binary a) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('11',default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+11 11
+1 1
+drop table t1;
+set sql_warnings = 0;
+# &
+set sql_warnings = 1;
+create table t1 (a int, b int as (a & 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a & 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 1
+0 0
+drop table t1;
+set sql_warnings = 0;
+# ~
+set sql_warnings = 1;
+create table t1 (a int, b int as (~a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (~a) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+Warnings:
+Warning 1264 Out of range value for column 'b' at row 1
+select * from t1;
+a b
+1 2147483647
+drop table t1;
+set sql_warnings = 0;
+# |
+set sql_warnings = 1;
+create table t1 (a int, b int as (a | 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a | 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 5
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# ^
+set sql_warnings = 1;
+create table t1 (a int, b int as (a ^ 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a ^ 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 4
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# DIV
+set sql_warnings = 1;
+create table t1 (a int, b int as (a div 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a div 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (7,default);
+select * from t1;
+a b
+1 0
+7 1
+drop table t1;
+set sql_warnings = 0;
+# <=>
+set sql_warnings = 1;
+create table t1 (a int, b int, c bool as (a <=> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` tinyint(1) AS (a <=> b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,1,default);
+insert into t1 values (NULL,NULL,default);
+insert into t1 values (1,NULL,default);
+select * from t1;
+a b c
+1 1 1
+NULL NULL 1
+1 NULL 0
+drop table t1;
+set sql_warnings = 0;
+# =
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a=b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a=b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a >= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a >= b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a > b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a > b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 0
+drop table t1;
+set sql_warnings = 0;
+# IS NOT NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is not null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is not null) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 1
+NULL 0
+drop table t1;
+set sql_warnings = 0;
+# IS NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is null) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 0
+NULL 1
+drop table t1;
+set sql_warnings = 0;
+# <<
+set sql_warnings = 1;
+create table t1 (a int, b int as (a << 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a << 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+1 4
+3 12
+drop table t1;
+set sql_warnings = 0;
+# <=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <= b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 1
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# <
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a < b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a < b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# NOT BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a not between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a not between 0 and 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 1
+1 0
+drop table t1;
+set sql_warnings = 0;
+# <>
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <> b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# !=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a != b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a != b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# ||, OR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a>5 || a<3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a>5 || a<3) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (4,default);
+select * from t1;
+a b
+1 1
+4 0
+drop table t1;
+set sql_warnings = 0;
+# >>
+set sql_warnings = 1;
+create table t1 (a int, b int as (a >> 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a >> 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (8,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+8 2
+3 0
+drop table t1;
+set sql_warnings = 0;
+# XOR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a xor 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a xor 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 1
+1 0
+2 0
+drop table t1;
+set sql_warnings = 0;
+#
+# DATE AND TIME FUNCTIONS
+#
+# ADDDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (adddate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (adddate(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# ADDTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (addtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (addtime(a,'02:00:00')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-31 02:00:00
+drop table t1;
+set sql_warnings = 0;
+# CONVERT_TZ()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (convert_tz(a,'MET','UTC')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (convert_tz(a,'MET','UTC')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_ADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_add(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_add(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(64) as (date_format(a,'%W %M %D')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(64) AS (date_format(a,'%W %M %D')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday August 31st
+drop table t1;
+set sql_warnings = 0;
+# DATE_SUB()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_sub(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_sub(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:00:00',default);
+select * from t1;
+a b
+2008-08-31 02:00:00 2008-08-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (datediff(a,'2000-01-01')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (datediff(a,'2000-01-01')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3165
+drop table t1;
+set sql_warnings = 0;
+# DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (day(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(10) as (dayname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(10) AS (dayname(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday
+drop table t1;
+set sql_warnings = 0;
+# DAYOFMONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofmonth(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofmonth(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYOFWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofweek(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 1
+drop table t1;
+set sql_warnings = 0;
+# DAYOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofyear(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 244
+drop table t1;
+set sql_warnings = 0;
+# EXTRACT
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (extract(year from a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (extract(year from a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# FROM_DAYS()
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_days(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (730669,default);
+select * from t1;
+a b
+730669 2000-07-03 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# FROM_UNIXTIME()
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_unixtime(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_unixtime(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1196440219,default);
+select * from t1;
+a b
+1196440219 2007-11-30 19:30:19
+drop table t1;
+set sql_warnings = 0;
+# GET_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (date_format(a,get_format(DATE,'EUR'))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (date_format(a,get_format(DATE,'EUR'))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31.08.2008
+drop table t1;
+set sql_warnings = 0;
+# HOUR()
+set sql_warnings = 1;
+create table t1 (a time, b long as (hour(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (hour(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+10:05:03 10
+drop table t1;
+set sql_warnings = 0;
+# LAST_DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (last_day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (last_day(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-05',default);
+insert into t1 values ('2003-02-32',default);
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+select * from t1;
+a b
+2003-02-05 00:00:00 2003-02-28 00:00:00
+0000-00-00 00:00:00 NULL
+drop table t1;
+set sql_warnings = 0;
+# MAKEDATE()
+set sql_warnings = 1;
+create table t1 (a int, b datetime as (makedate(a,1)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime AS (makedate(a,1)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2001,default);
+select * from t1;
+a b
+2001 2001-01-01 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# MAKETIME()
+set sql_warnings = 1;
+create table t1 (a int, b time as (maketime(a,1,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` time AS (maketime(a,1,3)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 12:01:03
+drop table t1;
+set sql_warnings = 0;
+# MICROSECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (microsecond(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (microsecond(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 12:00:00.123456',default);
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 12:00:00 0
+2009-12-31 23:59:59 0
+drop table t1;
+set sql_warnings = 0;
+# MINUTE()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (minute(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (minute(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 59
+drop table t1;
+set sql_warnings = 0;
+# MONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (month(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (month(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 12
+drop table t1;
+set sql_warnings = 0;
+# MONTHNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(16) as (monthname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(16) AS (monthname(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 December
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_ADD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (period_add(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (period_add(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (200801,default);
+select * from t1;
+a b
+200801 200803
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_DIFF()
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (period_diff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (period_diff(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (200802,200703,default);
+select * from t1;
+a b c
+200802 200703 11
+drop table t1;
+set sql_warnings = 0;
+# QUARTER()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (quarter(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (quarter(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# SEC_TO_TIME()
+set sql_warnings = 1;
+create table t1 (a long, b time as (sec_to_time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` time AS (sec_to_time(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2378,default);
+select * from t1;
+a b
+2378 00:39:38
+drop table t1;
+set sql_warnings = 0;
+# SECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (second(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (second(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+2010-05-03 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# STR_TO_DATE()
+set sql_warnings = 1;
+create table t1 (a varchar(64), b datetime as (str_to_date(a,'%m/%d/%Y')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(64) DEFAULT NULL,
+ `b` datetime AS (str_to_date(a,'%m/%d/%Y')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('04/30/2004',default);
+select * from t1;
+a b
+04/30/2004 2004-04-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subdate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subdate(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subtime(a,'02:00:00')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIME_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (time_format(a,'%r')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (time_format(a,'%r')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04 AM
+drop table t1;
+set sql_warnings = 0;
+# TIME_TO_SEC()
+set sql_warnings = 1;
+create table t1 (a time, b long as (time_to_sec(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (time_to_sec(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('22:23:00',default);
+select * from t1;
+a b
+22:23:00 80580
+drop table t1;
+set sql_warnings = 0;
+# TIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b time as (time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` time AS (time(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04
+drop table t1;
+set sql_warnings = 0;
+# TIMEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime, c long as (timediff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` mediumtext AS (timediff(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31 23:59:59.000001','2008-12-30 01:01:01.000002',default);
+select * from t1;
+a b c
+2008-12-31 23:59:59 2008-12-30 01:01:01 46:58:58
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMP()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestamp(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestamp(a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31',default);
+select * from t1;
+a b
+2008-12-31 00:00:00 2008-12-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestampadd(minute,1,a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2003-01-02',default);
+select * from t1;
+a b
+2003-01-02 00:00:00 2003-01-02 00:01:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPDIFF()
+set sql_warnings = 1;
+create table t1 (a timestamp, b timestamp, c long as (timestampdiff(MONTH, a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `c` mediumtext AS (timestampdiff(MONTH, a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-01','2003-05-01',default);
+select * from t1;
+a b c
+2003-02-01 00:00:00 2003-05-01 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# TO_DAYS()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (to_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (to_days(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2007-10-07',default);
+select * from t1;
+a b
+2007-10-07 00:00:00 733321
+drop table t1;
+set sql_warnings = 0;
+# WEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (week(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (week(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 35
+drop table t1;
+set sql_warnings = 0;
+# WEEKDAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekday(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekday(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# WEEKOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekofyear(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 36
+drop table t1;
+set sql_warnings = 0;
+# YEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (year(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (year(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# YEARWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (yearweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (yearweek(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 200835
+drop table t1;
+set sql_warnings = 0;
+#
+# FULL TEXT SEARCH FUNCTIONS
+#
+# None.
+#
+# CAST FUNCTIONS AND OPERATORS
+#
+# CAST()
+set sql_warnings = 1;
+create table t1 (a int, b long as (cast(a as unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (cast(a as unsigned)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+# Convert()
+set sql_warnings = 1;
+create table t1 (a int, b long as (convert(a,unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (convert(a,unsigned)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+#
+# XML FUNCTIONS
+#
+# None.
+#
+# OTHER FUNCTIONS
+#
+# AES_DECRYPT(), AES_ENCRYPT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (aes_encrypt(aes_decrypt(a,'adf'),'adf')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (aes_encrypt(aes_decrypt(a,'adf'),'adf')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL NULL
+drop table t1;
+set sql_warnings = 0;
+# BIT_COUNT()
+set sql_warnings = 1;
+create table t1 (a int, b int as (bit_count(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (bit_count(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (5,default);
+select * from t1;
+a b
+5 2
+drop table t1;
+set sql_warnings = 0;
+# CHARSET()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (charset(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (charset(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1
+drop table t1;
+set sql_warnings = 0;
+# COERCIBILITY()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b int as (coercibility(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` int(11) AS (coercibility(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 2
+drop table t1;
+set sql_warnings = 0;
+# COLLATION()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (collation(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (collation(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1_swedish_ci
+drop table t1;
+set sql_warnings = 0;
+# COMPRESS(), UNCOMPRESS()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (uncompress(compress(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompress(compress(a))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# ENCODE(), DECODE()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (decode(encode(a,'abc'),'abc')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (decode(encode(a,'abc'),'abc')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# DEFAULT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024) default 'aaa', b varchar(1024) as (ifnull(a,default(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT 'aaa',
+ `b` varchar(1024) AS (ifnull(a,default(a))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('any value',default);
+select * from t1;
+a b
+any value any value
+drop table t1;
+set sql_warnings = 0;
+# INET_ATON(), INET_NTOA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (inet_ntoa(inet_aton(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (inet_ntoa(inet_aton(a))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('127.0.0.1',default);
+select * from t1;
+a b
+127.0.0.1 127.0.0.1
+drop table t1;
+set sql_warnings = 0;
+# MD5()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varbinary(32) as (md5(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varbinary(32) AS (md5(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('testing',default);
+select * from t1;
+a b
+testing ae2b1fca515949e5d54fb22b8ed95575
+drop table t1;
+set sql_warnings = 0;
+# OLD_PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (old_password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (old_password(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd 7f84554057dd964b
+drop table t1;
+set sql_warnings = 0;
+# PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (password(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd *AAB3E285149C0135D51A520E1940DD3263DC008C
+drop table t1;
+set sql_warnings = 0;
+# SHA1()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha1(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha1(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# SHA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# UNCOMPRESSED_LENGTH()
+set sql_warnings = 1;
+create table t1 (a char, b varchar(1024) as (uncompressed_length(compress(repeat(a,30)))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompressed_length(compress(repeat(a,30)))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a',default);
+select * from t1;
+a b
+a 30
+drop table t1;
+set sql_warnings = 0;
=== added file 'mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,2942 @@
+SET @@session.storage_engine = 'MyISAM';
+#
+# NUMERIC FUNCTIONS
+#
+# ABS()
+set sql_warnings = 1;
+create table t1 (a int, b int as (abs(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (abs(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1, default);
+select * from t1;
+a b
+-1 1
+drop table t1;
+set sql_warnings = 0;
+# ACOS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(acos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(acos(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1, default);
+insert into t1 values (1.0001,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 0
+1.0001 NULL
+0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ASIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(asin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(asin(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (0.2, default);
+insert into t1 values (1.0001,default);
+select * from t1;
+a b
+0.2 0.201358
+1.0001 NULL
+drop table t1;
+set sql_warnings = 0;
+#ATAN
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan(a,b),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, c double as (format(atan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `c` double AS (format(atan(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-2,default);
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a c
+-2 -1.107149
+3.141593 1.262627
+drop table t1;
+set sql_warnings = 0;
+# ATAN2
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan2(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan2(a,b),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# CEIL()
+set sql_warnings = 1;
+create table t1 (a double, b int as (ceil(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (ceil(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 2
+-1.23 -1
+drop table t1;
+set sql_warnings = 0;
+# CONV()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int, c int, d varchar(10) as (conv(a,b,c)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (conv(a,b,c)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a',16,2,default);
+insert into t1 values ('6e',18,8,default);
+insert into t1 values (-17,10,-18,default);
+insert into t1 values (10+'10'+'10'+0xa,10,10,default);
+select * from t1;
+a b c d
+a 16 2 1010
+6e 18 8 172
+-17 10 -18 -H
+40 10 10 40
+drop table t1;
+set sql_warnings = 0;
+# COS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cos(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a b
+3.141593 -1
+drop table t1;
+set sql_warnings = 0;
+# COT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cot(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cot(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+12 -1.572673
+0 NULL
+drop table t1;
+set sql_warnings = 0;
+# CRC32()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (crc32(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (crc32(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('mysql',default);
+select * from t1;
+a b
+MySQL 3259397556
+mysql 2501908538
+drop table t1;
+set sql_warnings = 0;
+# DEGREES()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(degrees(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(degrees(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+3.141593 180.00002
+1.570796 89.999981
+drop table t1;
+set sql_warnings = 0;
+# /
+set sql_warnings = 1;
+create table t1 (a double, b double as (a/2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a/2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# EXP()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(exp(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(exp(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+2 7.389056
+-2 0.135335
+0 1
+drop table t1;
+set sql_warnings = 0;
+# FLOOR()
+set sql_warnings = 1;
+create table t1 (a double, b long as (floor(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` mediumtext AS (floor(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 1
+-1.23 -2
+drop table t1;
+set sql_warnings = 0;
+# LN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(ln(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(ln(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG()
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(log(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(log(a,b),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,65536,default);
+insert into t1 values (10,100,default);
+insert into t1 values (1,100,default);
+select * from t1;
+a b c
+2 65536 16
+10 100 2
+1 100 NULL
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG2()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log2(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log2(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (65536,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+65536 16
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG10()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log10(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log10(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (100,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+2 0.30103
+100 2
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# -
+set sql_warnings = 1;
+create table t1 (a double, b double as (a-1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a-1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# MOD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (mod(a,10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (mod(a,10)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# %
+set sql_warnings = 1;
+create table t1 (a int, b int as (a % 10));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 10) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# OCT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(10) as (oct(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(10) AS (oct(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 14
+drop table t1;
+set sql_warnings = 0;
+# PI()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(PI()*a*a,6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(PI()*a*a,6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 3.141593
+drop table t1;
+set sql_warnings = 0;
+# +
+set sql_warnings = 1;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 2
+drop table t1;
+set sql_warnings = 0;
+# POW, POWER
+set sql_warnings = 1;
+create table t1 (a int, b int as (pow(a,2)), c int as (power(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (pow(a,2)) VIRTUAL,
+ `c` int(11) AS (power(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default,default);
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 1 1
+2 4 4
+drop table t1;
+set sql_warnings = 0;
+# RADIANS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(radians(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(radians(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (90,default);
+select * from t1;
+a b
+90 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ROUND()
+set sql_warnings = 1;
+create table t1 (a double, b int as (round(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (round(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1.23,default);
+insert into t1 values (-1.58,default);
+insert into t1 values (1.58,default);
+select * from t1;
+a b
+-1.23 -1
+-1.58 -2
+1.58 2
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double, c int as (round(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` int(11) AS (round(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.298,1,default);
+insert into t1 values (1.298,0,default);
+insert into t1 values (23.298,-1,default);
+select * from t1;
+a b c
+1.298 1 1
+1.298 0 1
+23.298 -1 20
+drop table t1;
+set sql_warnings = 0;
+# SIGN()
+set sql_warnings = 1;
+create table t1 (a double, b int as (sign(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (sign(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-32,default);
+insert into t1 values (0,default);
+insert into t1 values (234,default);
+select * from t1;
+a b
+-32 -1
+0 0
+234 1
+drop table t1;
+set sql_warnings = 0;
+# SIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sin(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+1.570796 1
+drop table t1;
+set sql_warnings = 0;
+# SQRT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sqrt(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sqrt(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (4,default);
+insert into t1 values (20,default);
+insert into t1 values (-16,default);
+select * from t1;
+a b
+4 2
+20 4.472136
+-16 NULL
+drop table t1;
+set sql_warnings = 0;
+# TAN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(tan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(tan(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()+1,6),default);
+select * from t1;
+a b
+3.141593 0
+4.141593 1.557409
+drop table t1;
+set sql_warnings = 0;
+# *
+set sql_warnings = 1;
+create table t1 (a double, b double as (a*3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a*3) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 0
+1 3
+2 6
+drop table t1;
+set sql_warnings = 0;
+# TRUNCATE()
+set sql_warnings = 1;
+create table t1 (a double, b double as (truncate(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (truncate(a,4)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.223,default);
+insert into t1 values (1.999,default);
+insert into t1 values (1.999,default);
+insert into t1 values (122,default);
+select * from t1;
+a b
+1.223 1.223
+1.999 1.999
+1.999 1.999
+122 122
+drop table t1;
+set sql_warnings = 0;
+# Unary -
+set sql_warnings = 1;
+create table t1 (a double, b double as (-a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (-a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 -1
+-1 1
+drop table t1;
+set sql_warnings = 0;
+#
+# STRING FUNCTIONS
+#
+# ASCII()
+set sql_warnings = 1;
+create table t1 (a char(2), b int as (ascii(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(2) DEFAULT NULL,
+ `b` int(11) AS (ascii(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+insert into t1 values (2,default);
+insert into t1 values ('dx',default);
+select * from t1;
+a b
+2 50
+2 50
+dx 100
+drop table t1;
+set sql_warnings = 0;
+# BIN()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (bin(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (bin(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 1100
+drop table t1;
+set sql_warnings = 0;
+# BIT_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (bit_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (bit_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 32
+drop table t1;
+set sql_warnings = 0;
+# CHAR_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (char_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (char_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CHAR()
+set sql_warnings = 1;
+create table t1 (a int, b int, c varbinary(10) as (char(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` varbinary(10) AS (char(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (77,121,default);
+select * from t1;
+a b c
+77 121 My
+drop table t1;
+set sql_warnings = 0;
+# CHARACTER_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (character_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (character_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CONCAT_WS()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat_ws(',',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat_ws(',',a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# CONCAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat(a,',',b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat(a,',',b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# ELT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(10) as (elt(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (elt(c,a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',1,default);
+insert into t1 values ('value1','value2',2,default);
+select * from t1;
+a b c d
+value1 value2 1 value1
+value1 value2 2 value2
+drop table t1;
+set sql_warnings = 0;
+# EXPORT_SET()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (export_set(a,'1','0','',10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (export_set(a,'1','0','',10)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (6,default);
+select * from t1;
+a b
+6 0110000000
+drop table t1;
+set sql_warnings = 0;
+# FIELD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (field('aa',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (field('aa',a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('aa','bb',default);
+insert into t1 values ('bb','aa',default);
+select * from t1;
+a b c
+aa bb 1
+bb aa 2
+drop table t1;
+set sql_warnings = 0;
+# FIND_IN_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (find_in_set(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (find_in_set(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('aa','aa,bb,cc',default);
+insert into t1 values ('aa','bb,aa,cc',default);
+select * from t1;
+a b c
+aa aa,bb,cc 1
+aa bb,aa,cc 2
+drop table t1;
+set sql_warnings = 0;
+# FORMAT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(20) as (format(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(20) AS (format(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12332.123456,default);
+select * from t1;
+a b
+12332.123456 12,332.12
+drop table t1;
+set sql_warnings = 0;
+# HEX()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (17,default);
+select * from t1;
+a b
+17 11
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 616263
+drop table t1;
+set sql_warnings = 0;
+# INSERT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (insert(a,length(a),length(b),b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (insert(a,length(a),length(b),b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('start,','end',default);
+select * from t1;
+a b c
+start, end startend
+drop table t1;
+set sql_warnings = 0;
+# INSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (instr(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (instr(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar,','bar',default);
+insert into t1 values ('xbar,','foobar',default);
+select * from t1;
+a b c
+foobarbar, bar 4
+xbar, foobar 0
+drop table t1;
+set sql_warnings = 0;
+# LCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lcase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lcase(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LEFT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(5) as (left(a,5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(5) AS (left(a,5)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fooba
+drop table t1;
+set sql_warnings = 0;
+# LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a like 'H%o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# LOCATE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (locate('bar',a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (locate('bar',a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# LOWER()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lower(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lower(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lpad(a,4,' ')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lpad(a,4,' ')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('M',default);
+select * from t1;
+a b
+MySQL MySQ
+M M
+drop table t1;
+set sql_warnings = 0;
+# LTRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (ltrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (ltrim(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (' MySQL',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+ MySQL MySQL
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# MAKE_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(30) as (make_set(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(30) AS (make_set(c,a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',1,default);
+insert into t1 values ('a','b',3,default);
+select * from t1;
+a b c d
+a b 1 a
+a b 3 a,b
+drop table t1;
+set sql_warnings = 0;
+# MID()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (mid(a,1,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (mid(a,1,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fo
+drop table t1;
+set sql_warnings = 0;
+# NOT LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not like 'H%o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 0
+MySQL 1
+drop table t1;
+set sql_warnings = 0;
+# NOT REGEXP
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not regexp 'H.+o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 0
+hello 0
+drop table t1;
+set sql_warnings = 0;
+# OCTET_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (octet_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (octet_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# ORD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (ord(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (ord(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+select * from t1;
+a b
+2 50
+drop table t1;
+set sql_warnings = 0;
+# POSITION()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (position('bar' in a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (position('bar' in a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# QUOTE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (quote(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (quote(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Don\'t',default);
+select * from t1;
+a b
+Don't 'Don\'t'
+drop table t1;
+set sql_warnings = 0;
+# REGEXP()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a regexp 'H.+o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 1
+hello 1
+drop table t1;
+set sql_warnings = 0;
+# REPEAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (repeat(a,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (repeat(a,3)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQLMySQLMySQL
+drop table t1;
+set sql_warnings = 0;
+# REPLACE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (replace(a,'aa','bb')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (replace(a,'aa','bb')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa mbb
+drop table t1;
+set sql_warnings = 0;
+# REVERSE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (reverse(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (reverse(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa aam
+drop table t1;
+set sql_warnings = 0;
+# RIGHT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (right(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (right(a,4)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar rbar
+drop table t1;
+set sql_warnings = 0;
+# RLIKE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a rlike 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a rlike 'H.+o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# RPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rpad(a,4,'??')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rpad(a,4,'??')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('He',default);
+select * from t1;
+a b
+He He??
+drop table t1;
+set sql_warnings = 0;
+# RTRIM();
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rtrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rtrim(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello ',default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# SOUNDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(20) as (soundex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(20) AS (soundex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello H400
+drop table t1;
+set sql_warnings = 0;
+# SOUNDS LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a sounds like b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a sounds like b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello',default);
+insert into t1 values ('Hello','MySQL',default);
+insert into t1 values ('Hello','hello',default);
+select * from t1;
+a b c
+Hello Hello 1
+Hello MySQL 0
+Hello hello 1
+drop table t1;
+set sql_warnings = 0;
+# SPACE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (concat(a,space(5))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (concat(a,space(5))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello', default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# STRCMP()
+set sql_warnings = 1;
+create table t1 (a varchar(9), b varchar(9), c tinyint(1) as (strcmp(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(9) DEFAULT NULL,
+ `b` varchar(9) DEFAULT NULL,
+ `c` tinyint(1) AS (strcmp(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello', default);
+insert into t1 values ('Hello','Hello1', default);
+select * from t1;
+a b c
+Hello Hello 0
+Hello Hello1 -1
+drop table t1;
+set sql_warnings = 0;
+# SUBSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substr(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substr(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello ello
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING_INDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (substring_index(a,'.',2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (substring_index(a,'.',2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('www.mysql.com',default);
+select * from t1;
+a b
+www.mysql.com www.mysql
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substring(a from 2 for 2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substring(a from 2 for 2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello el
+drop table t1;
+set sql_warnings = 0;
+# TRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (trim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (trim(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (' aa ',default);
+select * from t1;
+a b
+ aa aa
+drop table t1;
+set sql_warnings = 0;
+# UCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (ucase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (ucase(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+# UNHEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (unhex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (unhex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('4D7953514C',default);
+select * from t1;
+a b
+4D7953514C MySQL
+drop table t1;
+set sql_warnings = 0;
+# UPPER()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (upper(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (upper(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+#
+# CONTROL FLOW FUNCTIONS
+#
+# CASE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(16) as (case a when NULL then 'asd' when 'b' then 'B' else a end));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(16) AS (case a when NULL then 'asd' when 'b' then 'B' else a end) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (NULL,default);
+insert into t1 values ('b',default);
+insert into t1 values ('c',default);
+select * from t1;
+a b
+NULL NULL
+b B
+c c
+drop table t1;
+set sql_warnings = 0;
+# IF
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (if(a=1,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (if(a=1,a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,2,default);
+insert into t1 values (3,4,default);
+select * from t1;
+a b c
+1 2 1
+3 4 4
+drop table t1;
+set sql_warnings = 0;
+# IFNULL
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(10) as (ifnull(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(10) AS (ifnull(a,'DEFAULT')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (NULL,'adf',default);
+insert into t1 values ('a','adf',default);
+select * from t1;
+a b c
+NULL adf DEFAULT
+a adf a
+drop table t1;
+set sql_warnings = 0;
+# NULLIF
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (nullif(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (nullif(a,'DEFAULT')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('DEFAULT',default);
+insert into t1 values ('a',default);
+select * from t1;
+a b
+DEFAULT NULL
+a a
+drop table t1;
+set sql_warnings = 0;
+#
+# OPERATORS
+#
+# AND, &&
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a>0 && a<2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a>0 && a<2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a between 0 and 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BINARY
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varbinary(10) as (binary a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varbinary(10) AS (binary a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('11',default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+11 11
+1 1
+drop table t1;
+set sql_warnings = 0;
+# &
+set sql_warnings = 1;
+create table t1 (a int, b int as (a & 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a & 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 1
+0 0
+drop table t1;
+set sql_warnings = 0;
+# ~
+set sql_warnings = 1;
+create table t1 (a int, b int as (~a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (~a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+Warnings:
+Warning 1264 Out of range value for column 'b' at row 1
+select * from t1;
+a b
+1 2147483647
+drop table t1;
+set sql_warnings = 0;
+# |
+set sql_warnings = 1;
+create table t1 (a int, b int as (a | 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a | 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 5
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# ^
+set sql_warnings = 1;
+create table t1 (a int, b int as (a ^ 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a ^ 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 4
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# DIV
+set sql_warnings = 1;
+create table t1 (a int, b int as (a div 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a div 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (7,default);
+select * from t1;
+a b
+1 0
+7 1
+drop table t1;
+set sql_warnings = 0;
+# <=>
+set sql_warnings = 1;
+create table t1 (a int, b int, c bool as (a <=> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` tinyint(1) AS (a <=> b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,1,default);
+insert into t1 values (NULL,NULL,default);
+insert into t1 values (1,NULL,default);
+select * from t1;
+a b c
+1 1 1
+NULL NULL 1
+1 NULL 0
+drop table t1;
+set sql_warnings = 0;
+# =
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a=b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a=b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a >= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a >= b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a > b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a > b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 0
+drop table t1;
+set sql_warnings = 0;
+# IS NOT NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is not null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is not null) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 1
+NULL 0
+drop table t1;
+set sql_warnings = 0;
+# IS NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is null) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 0
+NULL 1
+drop table t1;
+set sql_warnings = 0;
+# <<
+set sql_warnings = 1;
+create table t1 (a int, b int as (a << 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a << 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+1 4
+3 12
+drop table t1;
+set sql_warnings = 0;
+# <=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <= b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 1
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# <
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a < b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a < b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# NOT BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a not between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a not between 0 and 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 1
+1 0
+drop table t1;
+set sql_warnings = 0;
+# <>
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <> b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# !=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a != b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a != b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# ||, OR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a>5 || a<3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a>5 || a<3) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (4,default);
+select * from t1;
+a b
+1 1
+4 0
+drop table t1;
+set sql_warnings = 0;
+# >>
+set sql_warnings = 1;
+create table t1 (a int, b int as (a >> 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a >> 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (8,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+8 2
+3 0
+drop table t1;
+set sql_warnings = 0;
+# XOR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a xor 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a xor 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 1
+1 0
+2 0
+drop table t1;
+set sql_warnings = 0;
+#
+# DATE AND TIME FUNCTIONS
+#
+# ADDDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (adddate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (adddate(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# ADDTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (addtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (addtime(a,'02:00:00')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-31 02:00:00
+drop table t1;
+set sql_warnings = 0;
+# CONVERT_TZ()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (convert_tz(a,'MET','UTC')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (convert_tz(a,'MET','UTC')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_ADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_add(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_add(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(64) as (date_format(a,'%W %M %D')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(64) AS (date_format(a,'%W %M %D')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday August 31st
+drop table t1;
+set sql_warnings = 0;
+# DATE_SUB()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_sub(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_sub(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:00:00',default);
+select * from t1;
+a b
+2008-08-31 02:00:00 2008-08-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (datediff(a,'2000-01-01')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (datediff(a,'2000-01-01')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3165
+drop table t1;
+set sql_warnings = 0;
+# DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (day(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(10) as (dayname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(10) AS (dayname(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday
+drop table t1;
+set sql_warnings = 0;
+# DAYOFMONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofmonth(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofmonth(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYOFWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofweek(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 1
+drop table t1;
+set sql_warnings = 0;
+# DAYOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofyear(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 244
+drop table t1;
+set sql_warnings = 0;
+# EXTRACT
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (extract(year from a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (extract(year from a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# FROM_DAYS()
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_days(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (730669,default);
+select * from t1;
+a b
+730669 2000-07-03 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# FROM_UNIXTIME()
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_unixtime(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_unixtime(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1196440219,default);
+select * from t1;
+a b
+1196440219 2007-11-30 19:30:19
+drop table t1;
+set sql_warnings = 0;
+# GET_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (date_format(a,get_format(DATE,'EUR'))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (date_format(a,get_format(DATE,'EUR'))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31.08.2008
+drop table t1;
+set sql_warnings = 0;
+# HOUR()
+set sql_warnings = 1;
+create table t1 (a time, b long as (hour(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (hour(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+10:05:03 10
+drop table t1;
+set sql_warnings = 0;
+# LAST_DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (last_day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (last_day(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-05',default);
+insert into t1 values ('2003-02-32',default);
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+select * from t1;
+a b
+2003-02-05 00:00:00 2003-02-28 00:00:00
+0000-00-00 00:00:00 NULL
+drop table t1;
+set sql_warnings = 0;
+# MAKEDATE()
+set sql_warnings = 1;
+create table t1 (a int, b datetime as (makedate(a,1)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime AS (makedate(a,1)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2001,default);
+select * from t1;
+a b
+2001 2001-01-01 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# MAKETIME()
+set sql_warnings = 1;
+create table t1 (a int, b time as (maketime(a,1,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` time AS (maketime(a,1,3)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 12:01:03
+drop table t1;
+set sql_warnings = 0;
+# MICROSECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (microsecond(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (microsecond(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 12:00:00.123456',default);
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 12:00:00 0
+2009-12-31 23:59:59 0
+drop table t1;
+set sql_warnings = 0;
+# MINUTE()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (minute(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (minute(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 59
+drop table t1;
+set sql_warnings = 0;
+# MONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (month(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (month(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 12
+drop table t1;
+set sql_warnings = 0;
+# MONTHNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(16) as (monthname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(16) AS (monthname(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 December
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_ADD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (period_add(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (period_add(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (200801,default);
+select * from t1;
+a b
+200801 200803
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_DIFF()
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (period_diff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (period_diff(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (200802,200703,default);
+select * from t1;
+a b c
+200802 200703 11
+drop table t1;
+set sql_warnings = 0;
+# QUARTER()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (quarter(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (quarter(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# SEC_TO_TIME()
+set sql_warnings = 1;
+create table t1 (a long, b time as (sec_to_time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` time AS (sec_to_time(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2378,default);
+select * from t1;
+a b
+2378 00:39:38
+drop table t1;
+set sql_warnings = 0;
+# SECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (second(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (second(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+2010-05-03 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# STR_TO_DATE()
+set sql_warnings = 1;
+create table t1 (a varchar(64), b datetime as (str_to_date(a,'%m/%d/%Y')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(64) DEFAULT NULL,
+ `b` datetime AS (str_to_date(a,'%m/%d/%Y')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('04/30/2004',default);
+select * from t1;
+a b
+04/30/2004 2004-04-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subdate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subdate(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subtime(a,'02:00:00')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIME_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (time_format(a,'%r')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (time_format(a,'%r')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04 AM
+drop table t1;
+set sql_warnings = 0;
+# TIME_TO_SEC()
+set sql_warnings = 1;
+create table t1 (a time, b long as (time_to_sec(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (time_to_sec(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('22:23:00',default);
+select * from t1;
+a b
+22:23:00 80580
+drop table t1;
+set sql_warnings = 0;
+# TIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b time as (time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` time AS (time(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04
+drop table t1;
+set sql_warnings = 0;
+# TIMEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime, c long as (timediff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` mediumtext AS (timediff(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31 23:59:59.000001','2008-12-30 01:01:01.000002',default);
+select * from t1;
+a b c
+2008-12-31 23:59:59 2008-12-30 01:01:01 46:58:58
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMP()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestamp(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestamp(a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31',default);
+select * from t1;
+a b
+2008-12-31 00:00:00 2008-12-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestampadd(minute,1,a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2003-01-02',default);
+select * from t1;
+a b
+2003-01-02 00:00:00 2003-01-02 00:01:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPDIFF()
+set sql_warnings = 1;
+create table t1 (a timestamp, b timestamp, c long as (timestampdiff(MONTH, a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `c` mediumtext AS (timestampdiff(MONTH, a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-01','2003-05-01',default);
+select * from t1;
+a b c
+2003-02-01 00:00:00 2003-05-01 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# TO_DAYS()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (to_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (to_days(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2007-10-07',default);
+select * from t1;
+a b
+2007-10-07 00:00:00 733321
+drop table t1;
+set sql_warnings = 0;
+# WEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (week(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (week(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 35
+drop table t1;
+set sql_warnings = 0;
+# WEEKDAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekday(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekday(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# WEEKOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekofyear(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 36
+drop table t1;
+set sql_warnings = 0;
+# YEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (year(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (year(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# YEARWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (yearweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (yearweek(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 200835
+drop table t1;
+set sql_warnings = 0;
+#
+# FULL TEXT SEARCH FUNCTIONS
+#
+# None.
+#
+# CAST FUNCTIONS AND OPERATORS
+#
+# CAST()
+set sql_warnings = 1;
+create table t1 (a int, b long as (cast(a as unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (cast(a as unsigned)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+# Convert()
+set sql_warnings = 1;
+create table t1 (a int, b long as (convert(a,unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (convert(a,unsigned)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+#
+# XML FUNCTIONS
+#
+# None.
+#
+# OTHER FUNCTIONS
+#
+# AES_DECRYPT(), AES_ENCRYPT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (aes_encrypt(aes_decrypt(a,'adf'),'adf')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (aes_encrypt(aes_decrypt(a,'adf'),'adf')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL NULL
+drop table t1;
+set sql_warnings = 0;
+# BIT_COUNT()
+set sql_warnings = 1;
+create table t1 (a int, b int as (bit_count(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (bit_count(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (5,default);
+select * from t1;
+a b
+5 2
+drop table t1;
+set sql_warnings = 0;
+# CHARSET()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (charset(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (charset(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1
+drop table t1;
+set sql_warnings = 0;
+# COERCIBILITY()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b int as (coercibility(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` int(11) AS (coercibility(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 2
+drop table t1;
+set sql_warnings = 0;
+# COLLATION()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (collation(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (collation(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1_swedish_ci
+drop table t1;
+set sql_warnings = 0;
+# COMPRESS(), UNCOMPRESS()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (uncompress(compress(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompress(compress(a))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# ENCODE(), DECODE()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (decode(encode(a,'abc'),'abc')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (decode(encode(a,'abc'),'abc')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# DEFAULT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024) default 'aaa', b varchar(1024) as (ifnull(a,default(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT 'aaa',
+ `b` varchar(1024) AS (ifnull(a,default(a))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('any value',default);
+select * from t1;
+a b
+any value any value
+drop table t1;
+set sql_warnings = 0;
+# INET_ATON(), INET_NTOA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (inet_ntoa(inet_aton(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (inet_ntoa(inet_aton(a))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('127.0.0.1',default);
+select * from t1;
+a b
+127.0.0.1 127.0.0.1
+drop table t1;
+set sql_warnings = 0;
+# MD5()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varbinary(32) as (md5(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varbinary(32) AS (md5(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('testing',default);
+select * from t1;
+a b
+testing ae2b1fca515949e5d54fb22b8ed95575
+drop table t1;
+set sql_warnings = 0;
+# OLD_PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (old_password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (old_password(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd 7f84554057dd964b
+drop table t1;
+set sql_warnings = 0;
+# PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (password(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd *AAB3E285149C0135D51A520E1940DD3263DC008C
+drop table t1;
+set sql_warnings = 0;
+# SHA1()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha1(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha1(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# SHA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# UNCOMPRESSED_LENGTH()
+set sql_warnings = 1;
+create table t1 (a char, b varchar(1024) as (uncompressed_length(compress(repeat(a,30)))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompressed_length(compress(repeat(a,30)))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a',default);
+select * from t1;
+a b
+a 30
+drop table t1;
+set sql_warnings = 0;
=== added file 'mysql-test/suite/vcol/r/vcol_syntax.result'
--- a/mysql-test/suite/vcol/r/vcol_syntax.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_syntax.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,52 @@
+drop table if exists t1;
+set @OLD_SQL_MODE=@@SESSION.SQL_MODE;
+create table t1 (a int, b int generated always as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int as (a+1) virtual);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set session sql_mode='ORACLE';
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) DEFAULT NULL,
+ "b" int(11) AS (a+1) VIRTUAL
+)
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) virtual);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) DEFAULT NULL,
+ "b" int(11) AS (a+1) VIRTUAL
+)
+drop table t1;
+create table t1 (a int, b int as (a+1) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) DEFAULT NULL,
+ "b" int(11) AS (a+1) PERSISTENT
+)
+drop table t1;
+set session sql_mode=@OLD_SQL_MODE;
=== added file 'mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,87 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (a/10),
+c int as (a/10) persistent);
+create table t2 (a timestamp);
+create trigger trg1 before insert on t1 for each row
+begin
+if (new.b < 10) then
+set new.a:= 100;
+set new.b:= 9;
+set new.c:= 9;
+end if;
+if (new.c > 50) then
+set new.a:= 500;
+end if;
+end|
+create trigger trg2 after insert on t1 for each row
+begin
+if (new.b >= 60) then
+insert into t2 values (now());
+end if;
+end|
+create function f1()
+returns int
+begin
+declare sum1 int default '0';
+declare cur1 cursor for select sum(b) from t1;
+open cur1;
+fetch cur1 into sum1;
+close cur1;
+return sum1;
+end|
+set sql_warnings = 1;
+insert into t1 (a) values (200);
+select * from t1;
+a b c
+200 20 20
+select * from t2;
+a
+insert into t1 (a) values (10);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+select * from t2;
+a
+insert into t1 (a) values (600);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+500 50 50
+select * from t2;
+a
+select f1();
+f1()
+80
+set sql_warnings = 0;
+drop trigger trg1;
+drop trigger trg2;
+drop table t2;
+create procedure p1()
+begin
+declare i int default '0';
+create table t2 like t1;
+insert into t2 (a) values (100), (200);
+begin
+declare cur1 cursor for select sum(c) from t2;
+open cur1;
+fetch cur1 into i;
+close cur1;
+if (i=30) then
+insert into t1 values (300,default,default);
+end if;
+end;
+end|
+delete from t1;
+call p1();
+select * from t2;
+a b c
+100 10 10
+200 20 20
+select * from t1;
+a b c
+300 30 30
+drop table t1,t2;
+drop procedure p1;
=== added file 'mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,87 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (a/10),
+c int as (a/10) persistent);
+create table t2 (a timestamp);
+create trigger trg1 before insert on t1 for each row
+begin
+if (new.b < 10) then
+set new.a:= 100;
+set new.b:= 9;
+set new.c:= 9;
+end if;
+if (new.c > 50) then
+set new.a:= 500;
+end if;
+end|
+create trigger trg2 after insert on t1 for each row
+begin
+if (new.b >= 60) then
+insert into t2 values (now());
+end if;
+end|
+create function f1()
+returns int
+begin
+declare sum1 int default '0';
+declare cur1 cursor for select sum(b) from t1;
+open cur1;
+fetch cur1 into sum1;
+close cur1;
+return sum1;
+end|
+set sql_warnings = 1;
+insert into t1 (a) values (200);
+select * from t1;
+a b c
+200 20 20
+select * from t2;
+a
+insert into t1 (a) values (10);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+select * from t2;
+a
+insert into t1 (a) values (600);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+500 50 50
+select * from t2;
+a
+select f1();
+f1()
+80
+set sql_warnings = 0;
+drop trigger trg1;
+drop trigger trg2;
+drop table t2;
+create procedure p1()
+begin
+declare i int default '0';
+create table t2 like t1;
+insert into t2 (a) values (100), (200);
+begin
+declare cur1 cursor for select sum(c) from t2;
+open cur1;
+fetch cur1 into i;
+close cur1;
+if (i=30) then
+insert into t1 values (300,default,default);
+end if;
+end;
+end|
+delete from t1;
+call p1();
+select * from t2;
+a b c
+100 10 10
+200 20 20
+select * from t1;
+a b c
+300 30 30
+drop table t1,t2;
+drop procedure p1;
=== added file 'mysql-test/suite/vcol/r/vcol_view_innodb.result'
--- a/mysql-test/suite/vcol/r/vcol_view_innodb.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_view_innodb.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,276 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (1), (2), (2), (3);
+create view v1 (d,e) as select abs(b), abs(c) from t1;
+select d,e from v1;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+select is_updatable from information_schema.views where table_name='v1';
+is_updatable
+NO
+explain extended select d,e from v1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select abs(`test`.`t1`.`b`) AS `d`,abs(`test`.`t1`.`c`) AS `e` from `test`.`t1`
+create algorithm=temptable view v2 (d,e) as select abs(b), abs(c) from t1;
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select abs(`t1`.`b`) AS `d`,abs(`t1`.`c`) AS `e` from `t1` latin1 latin1_swedish_ci
+select d,e from v2;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+explain extended select d,e from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
+create view v3 (d,e) as select d*2, e*2 from v1;
+select * from v3;
+d e
+2 2
+2 2
+4 4
+4 4
+6 6
+explain extended select * from v3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select (abs(`test`.`t1`.`b`) * 2) AS `d`,(abs(`test`.`t1`.`c`) * 2) AS `e` from `test`.`t1`
+drop view v1,v2,v3;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct b from t1;
+select * from v1;
+b
+-1
+-2
+-3
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+create view v1 as select distinct c from t1;
+select * from v1;
+c
+-1
+-2
+-3
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (4);
+create view v1 as select b+1 from t1 order by 1 desc limit 2;
+select * from v1;
+b+1
+0
+-1
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
+drop view v1;
+create view v1 as select c+1 from t1 order by 1 desc limit 2;
+select * from v1;
+c+1
+0
+-1
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int,
+c int as (-a),
+d int as (-a) persistent,
+primary key(a));
+insert into t1 (a,b) values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,e,f,g) as select a, b+1,c+1,d+1 from t1;
+update v1 set a=a+e;
+select * from v1;
+a e f g
+13 3 -12 -12
+24 4 -23 -23
+35 5 -34 -34
+46 6 -45 -45
+61 11 -60 -60
+select * from t1;
+a b c d
+13 2 -13 -13
+24 3 -24 -24
+35 4 -35 -35
+46 5 -46 -46
+61 10 -61 -61
+delete from v1;
+select * from v1;
+a e f g
+select * from t1;
+a b c d
+insert into v1 (a,e) values (60,15);
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
+drop table t1;
+drop view v1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+primary key(a));
+insert into t1 (a) values (1), (2), (3);
+create view v1 (x,y,z) as select a,b,c from t1 where b < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.b= v1.y);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+create view v1 (x,y,z) as select a,b,c from t1 where c < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.c= v1.z);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a1 int,
+b1 int as (-a1),
+c1 int as (-a1) persistent);
+create table t2 (a2 int,
+b2 int as (-a2),
+c2 int as (-a2) persistent);
+insert into t1 (a1) values (1), (2);
+insert into t2 (a2) values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+a1 b1 c1 a2 b2 c2
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+drop view v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create table t2 like t1;
+create view v1 as select a,b,c from t1;
+create view v2 as select a,b,c from t2 where b in (select b from v1);
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t2` where `t2`.`b` in (select `v1`.`b` AS `b` from `v1`) latin1 latin1_swedish_ci
+drop view v2, v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1),(1),(2),(2),(3),(3);
+create view v1 as select b from t1;
+select distinct b from v1;
+b
+-1
+-2
+-3
+select distinct b from v1 limit 2;
+b
+-1
+-2
+select distinct b from t1 limit 2;
+b
+-1
+-2
+prepare stmt1 from "select distinct b from v1 limit 2";
+execute stmt1;
+b
+-1
+-2
+execute stmt1;
+b
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+create view v1 as select c from t1;
+select distinct c from v1;
+c
+-1
+-2
+-3
+select distinct c from v1 limit 2;
+c
+-1
+-2
+select distinct c from t1 limit 2;
+c
+-1
+-2
+prepare stmt1 from "select distinct c from v1 limit 2";
+execute stmt1;
+c
+-1
+-2
+execute stmt1;
+c
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create view v1 as select * from t1 where b > -2 && c >-2 with check option;
+insert into v1 (a) values (1);
+insert into v1 (a) values (3);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 (a) values (2),(3),(0);
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a b c
+1 -1 -1
+0 0 0
+drop view v1;
+drop table t1;
=== added file 'mysql-test/suite/vcol/r/vcol_view_myisam.result'
--- a/mysql-test/suite/vcol/r/vcol_view_myisam.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/r/vcol_view_myisam.result 2009-10-16 22:57:48 +0000
@@ -0,0 +1,276 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (1), (2), (2), (3);
+create view v1 (d,e) as select abs(b), abs(c) from t1;
+select d,e from v1;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+select is_updatable from information_schema.views where table_name='v1';
+is_updatable
+NO
+explain extended select d,e from v1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select abs(`test`.`t1`.`b`) AS `d`,abs(`test`.`t1`.`c`) AS `e` from `test`.`t1`
+create algorithm=temptable view v2 (d,e) as select abs(b), abs(c) from t1;
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select abs(`t1`.`b`) AS `d`,abs(`t1`.`c`) AS `e` from `t1` latin1 latin1_swedish_ci
+select d,e from v2;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+explain extended select d,e from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
+create view v3 (d,e) as select d*2, e*2 from v1;
+select * from v3;
+d e
+2 2
+2 2
+4 4
+4 4
+6 6
+explain extended select * from v3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select (abs(`test`.`t1`.`b`) * 2) AS `d`,(abs(`test`.`t1`.`c`) * 2) AS `e` from `test`.`t1`
+drop view v1,v2,v3;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct b from t1;
+select * from v1;
+b
+-1
+-2
+-3
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+create view v1 as select distinct c from t1;
+select * from v1;
+c
+-1
+-2
+-3
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (4);
+create view v1 as select b+1 from t1 order by 1 desc limit 2;
+select * from v1;
+b+1
+0
+-1
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
+drop view v1;
+create view v1 as select c+1 from t1 order by 1 desc limit 2;
+select * from v1;
+c+1
+0
+-1
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int,
+c int as (-a),
+d int as (-a) persistent,
+primary key(a));
+insert into t1 (a,b) values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,e,f,g) as select a, b+1,c+1,d+1 from t1;
+update v1 set a=a+e;
+select * from v1;
+a e f g
+13 3 -12 -12
+24 4 -23 -23
+35 5 -34 -34
+46 6 -45 -45
+61 11 -60 -60
+select * from t1;
+a b c d
+13 2 -13 -13
+24 3 -24 -24
+35 4 -35 -35
+46 5 -46 -46
+61 10 -61 -61
+delete from v1;
+select * from v1;
+a e f g
+select * from t1;
+a b c d
+insert into v1 (a,e) values (60,15);
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
+drop table t1;
+drop view v1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+primary key(a));
+insert into t1 (a) values (1), (2), (3);
+create view v1 (x,y,z) as select a,b,c from t1 where b < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.b= v1.y);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+create view v1 (x,y,z) as select a,b,c from t1 where c < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.c= v1.z);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a1 int,
+b1 int as (-a1),
+c1 int as (-a1) persistent);
+create table t2 (a2 int,
+b2 int as (-a2),
+c2 int as (-a2) persistent);
+insert into t1 (a1) values (1), (2);
+insert into t2 (a2) values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+a1 b1 c1 a2 b2 c2
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+drop view v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create table t2 like t1;
+create view v1 as select a,b,c from t1;
+create view v2 as select a,b,c from t2 where b in (select b from v1);
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t2` where `t2`.`b` in (select `v1`.`b` AS `b` from `v1`) latin1 latin1_swedish_ci
+drop view v2, v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1),(1),(2),(2),(3),(3);
+create view v1 as select b from t1;
+select distinct b from v1;
+b
+-1
+-2
+-3
+select distinct b from v1 limit 2;
+b
+-1
+-2
+select distinct b from t1 limit 2;
+b
+-1
+-2
+prepare stmt1 from "select distinct b from v1 limit 2";
+execute stmt1;
+b
+-1
+-2
+execute stmt1;
+b
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+create view v1 as select c from t1;
+select distinct c from v1;
+c
+-1
+-2
+-3
+select distinct c from v1 limit 2;
+c
+-1
+-2
+select distinct c from t1 limit 2;
+c
+-1
+-2
+prepare stmt1 from "select distinct c from v1 limit 2";
+execute stmt1;
+c
+-1
+-2
+execute stmt1;
+c
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create view v1 as select * from t1 where b > -2 && c >-2 with check option;
+insert into v1 (a) values (1);
+insert into v1 (a) values (3);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 (a) values (2),(3),(0);
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a b c
+1 -1 -1
+0 0 0
+drop view v1;
+drop table t1;
=== added directory 'mysql-test/suite/vcol/t'
=== added file 'mysql-test/suite/vcol/t/rpl_vcol.test'
--- a/mysql-test/suite/vcol/t/rpl_vcol.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/rpl_vcol.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,69 @@
+################################################################################
+# t/vcol_rpl.test #
+# #
+# Purpose: #
+# Test replication of tables with virtual columns. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+SET @@session.storage_engine = 'InnoDB';
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source include/master-slave.inc
+
+connection master;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+save_master_pos;
+
+connection slave;
+sync_with_master;
+select * from t1;
+
+connection master;
+drop table t1;
+save_master_pos;
+
+connection slave;
+sync_with_master;
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_archive.test'
--- a/mysql-test/suite/vcol/t/vcol_archive.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_archive.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_archive.test #
+# #
+# Purpose: #
+# ARCHIVE branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_archive.inc
+SET @@session.storage_engine = 'archive';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--source suite/vcol/inc/vcol_unsupported_storage_engines.inc
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_blackhole.test'
--- a/mysql-test/suite/vcol/t/vcol_blackhole.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_blackhole.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_blackhole.test #
+# #
+# Purpose: #
+# BLACKHOLE branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_blackhole.inc
+SET @@session.storage_engine = 'blackhole';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--source suite/vcol/inc/vcol_unsupported_storage_engines.inc
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions not allowed for virtual columns #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+let $skip_full_text_checks = 1;
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions not allowed for virtual columns #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_column_def_options_innodb.test #
+# #
+# Purpose: #
+# Testing different optional parameters of virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_column_def_options.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_column_def_options_myisam.test #
+# #
+# Purpose: #
+# Testing different optional parameters of virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_column_def_options.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_csv.test'
--- a/mysql-test/suite/vcol/t/vcol_csv.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_csv.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,54 @@
+################################################################################
+# t/vcol_csv.test #
+# #
+# Purpose: #
+# CSV branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_csv.inc
+SET @@session.storage_engine = 'CSV';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1));
+create table t1 (a int not null);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 add column b int as (a+1);
+drop table t1;
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_handler_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_handler_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_handler_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_handler_innodb.test #
+# #
+# Purpose: #
+# Testing HANDLER.
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_handler.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_handler_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_handler_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_handler_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_handler_myisam.test #
+# #
+# Purpose: #
+# Testing HANDLER.
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_handler.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_ins_upd_innodb.test #
+# #
+# Purpose: #
+# Testing DDL operations such as INSERT, UPDATE, REPLACE and DELETE. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_ins_upd.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_ins_upd_myisam.test #
+# #
+# Purpose: #
+# Testing DDL operations such as INSERT, UPDATE, REPLACE and DELETE. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_ins_upd.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_keys_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_keys_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_keys_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_keys_innodb.test #
+# #
+# Purpose: #
+# Testing keys, indexes defined upon virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+let $skip_spatial_index_check = 1;
+--source suite/vcol/inc/vcol_keys.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_keys_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_keys_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_keys_myisam.test #
+# #
+# Purpose: #
+# Testing keys, indexes defined upon virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_keys.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_memory.test'
--- a/mysql-test/suite/vcol/t/vcol_memory.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_memory.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,48 @@
+################################################################################
+# t/vcol_memory.test #
+# #
+# Purpose: #
+# MEMORY branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+SET @@session.storage_engine = 'memory';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--source suite/vcol/inc/vcol_unsupported_storage_engines.inc
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_merge.test'
--- a/mysql-test/suite/vcol/t/vcol_merge.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_merge.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,57 @@
+################################################################################
+# t/vcol_merge.test #
+# #
+# Purpose: #
+# MERGE branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-03 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+
+create table t1 (a int, b int as (a % 10));
+create table t2 (a int, b int as (a % 10));
+insert into t1 values (1,default);
+insert into t2 values (2,default);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2);
+drop table t1,t2;
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,53 @@
+################################################################################
+# t/vcol_non_stored_columns_innodb.test #
+# #
+# Purpose: #
+# Ensure that MySQL behaviour is consistent irrelevant of #
+# - the place of a non-stored column among other columns, #
+# - the total number of non-stored fields. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_non_stored_columns.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_non_stored_columns_myisam.test #
+# #
+# Purpose: #
+# Ensure that MySQL behaviour is consistent irrelevant of #
+# - the place of a non-stored column among other columns, #
+# - the total number of non-stored fields. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_non_stored_columns.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_partition_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_partition_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_partition_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_partition_innodb.test #
+# #
+# Purpose: #
+# Testing partitioning tables with virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+--source include/have_partition.inc
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_partition.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_partition_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_partition_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_partition_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_partition_myisam.test #
+# #
+# Purpose: #
+# Testing partitioning tables with virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+--source include/have_partition.inc
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_partition.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_select_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_select_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_select_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_select_innodb.test #
+# #
+# Purpose: #
+# Testing different SELECTs. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-18 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_select.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_select_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_select_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_select_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_select.test #
+# #
+# Purpose: #
+# Testing different SELECTs. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-18 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_select.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions allowed for virtual columns #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_supported_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions allowed for virtual columns #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_supported_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_syntax.test'
--- a/mysql-test/suite/vcol/t/vcol_syntax.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_syntax.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,30 @@
+#
+# test syntax
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+set @OLD_SQL_MODE=@@SESSION.SQL_MODE;
+create table t1 (a int, b int generated always as (a+1));
+show create table t1;
+drop table t1;
+create table t1 (a int, b int as (a+1) virtual);
+show create table t1;
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) persistent);
+show create table t1;
+drop table t1;
+
+set session sql_mode='ORACLE';
+create table t1 (a int, b int as (a+1));
+show create table t1;
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) virtual);
+show create table t1;
+drop table t1;
+create table t1 (a int, b int as (a+1) persistent);
+show create table t1;
+drop table t1;
+set session sql_mode=@OLD_SQL_MODE;
+
=== added file 'mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_trigger_sp_innodb.test #
+# #
+# Purpose: #
+# Testing triggers, stored procedures and functions #
+# defined on tables with virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_trigger_sp.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_trigger_sp_myisam.test #
+# #
+# Purpose: #
+# Testing triggers, stored procedures and functions #
+# defined on tables with virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_trigger_sp.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_view_innodb.test'
--- a/mysql-test/suite/vcol/t/vcol_view_innodb.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_view_innodb.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_view_innodb.test #
+# #
+# Purpose: #
+# Testing views defined on tables with virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_view.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== added file 'mysql-test/suite/vcol/t/vcol_view_myisam.test'
--- a/mysql-test/suite/vcol/t/vcol_view_myisam.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/vcol/t/vcol_view_myisam.test 2009-10-16 22:57:48 +0000
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_view_myisam.test #
+# #
+# Purpose: #
+# Testing views defined on tables with virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_view.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
=== modified file 'mysql-test/t/analyse.test'
--- a/mysql-test/t/analyse.test 2006-09-28 18:32:30 +0000
+++ b/mysql-test/t/analyse.test 2009-08-27 10:22:19 +0000
@@ -14,6 +14,7 @@ create table t2 select * from t1 procedu
select * from t2;
drop table t1,t2;
+--error ER_WRONG_USAGE
EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
#
@@ -102,4 +103,13 @@ select f2 from t1 procedure analyse(1, 1
select f3 from t1 procedure analyse(1, 1);
drop table t1;
+#
+# Bug#46184 Crash, SELECT ... FROM derived table procedure analyze
+#
+CREATE TABLE t1(a INT,b INT,c INT,d INT,e INT,f INT,g INT,h INT,i INT,j INT,k INT);
+INSERT INTO t1 VALUES ();
+--error ER_WRONG_USAGE
+SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE();
+DROP TABLE t1;
+
--echo End of 4.1 tests
=== modified file 'mysql-test/t/auto_increment.test'
--- a/mysql-test/t/auto_increment.test 2009-02-05 09:49:32 +0000
+++ b/mysql-test/t/auto_increment.test 2009-08-20 12:30:59 +0000
@@ -324,3 +324,21 @@ insert into t1 values(null,0,0,0,null);
replace into t1 values(null,1,0,2,null);
select last_insert_id();
drop table t1;
+
+--echo #
+--echo # Bug#46616: Assertion `!table->auto_increment_field_not_null' on view
+--echo # manipulations
+--echo #
+CREATE TABLE t1 ( a INT );
+INSERT INTO t1 VALUES (1), (1);
+
+CREATE TABLE t2 ( a INT AUTO_INCREMENT KEY );
+--error ER_DUP_ENTRY
+CREATE TABLE IF NOT EXISTS t2 AS SELECT a FROM t1;
+
+UPDATE t2 SET a = 2;
+
+SELECT a FROM t2;
+
+DROP TABLE t1, t2;
+
=== modified file 'mysql-test/t/group_min_max.test'
--- a/mysql-test/t/group_min_max.test 2009-07-13 17:36:54 +0000
+++ b/mysql-test/t/group_min_max.test 2009-08-30 07:03:37 +0000
@@ -1018,3 +1018,18 @@ DROP TABLE t;
--echo End of 5.0 tests
+
+--echo #
+--echo # Bug #46607: Assertion failed: (cond_type == Item::FUNC_ITEM) results in
+--echo # server crash
+--echo #
+
+CREATE TABLE t (a INT, b INT, INDEX (a,b));
+INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1);
+INSERT INTO t SELECT * FROM t;
+
+SELECT a, MAX(b) FROM t WHERE b GROUP BY a;
+
+DROP TABLE t;
+
+--echo End of 5.1 tests
=== modified file 'mysql-test/t/handler_myisam.test'
--- a/mysql-test/t/handler_myisam.test 2006-08-16 17:29:49 +0000
+++ b/mysql-test/t/handler_myisam.test 2009-08-21 05:55:35 +0000
@@ -19,3 +19,22 @@ let $other_engine_type= MEMORY;
let $other_handler_engine_type= MyISAM;
--source include/handler.inc
+
+--echo #
+--echo # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
+--echo #
+CREATE TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+DROP TABLE t1;
+
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+DROP TABLE t1;
+
+--echo End of 5.1 tests
=== modified file 'mysql-test/t/lock_multi_bug38499.test'
--- a/mysql-test/t/lock_multi_bug38499.test 2009-07-06 10:30:25 +0000
+++ b/mysql-test/t/lock_multi_bug38499.test 2009-08-28 21:49:16 +0000
@@ -5,6 +5,9 @@
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
+SET @odl_sync_frm = @@global.sync_frm;
+SET @@global.sync_frm = OFF;
+
connect (locker,localhost,root,,);
connect (writer,localhost,root,,);
@@ -214,6 +217,8 @@ DROP TABLE t1;
--disconnect locker
--disconnect writer
+SET @@global.sync_frm = @odl_sync_frm;
+
# End of 5.0 tests
# Wait till all disconnects are completed
=== modified file 'mysql-test/t/lock_multi_bug38691.test'
--- a/mysql-test/t/lock_multi_bug38691.test 2009-03-23 14:22:31 +0000
+++ b/mysql-test/t/lock_multi_bug38691.test 2009-08-28 21:49:16 +0000
@@ -8,6 +8,9 @@
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
+SET @odl_sync_frm = @@global.sync_frm;
+SET @@global.sync_frm = OFF;
+
# Test to see if select will get the lock ahead of low priority update
connect (locker,localhost,root,,);
@@ -136,6 +139,8 @@ DROP TABLE t1, t2, t3;
--disconnect locker
--disconnect writer
+SET @@global.sync_frm = @odl_sync_frm;
+
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
=== modified file 'mysql-test/t/merge.test'
--- a/mysql-test/t/merge.test 2009-10-28 07:52:34 +0000
+++ b/mysql-test/t/merge.test 2009-11-06 17:22:32 +0000
@@ -1632,6 +1632,17 @@ DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7;
--error ER_NO_SUCH_TABLE
SELECT 1 FROM m1; # Should not hang!
+--echo #
+--echo # Bug #46614: Assertion in show_create_trigger()
+--echo #
+CREATE TABLE t1(a int);
+CREATE TABLE t2(a int);
+CREATE TABLE t3(a int) ENGINE = MERGE UNION(t1, t2);
+CREATE TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo();
+SHOW CREATE TRIGGER tr1;
+DROP TRIGGER tr1;
+DROP TABLE t1, t2, t3;
+
--echo End of 5.1 tests
--disable_result_log
=== modified file 'mysql-test/t/not_partition.test'
--- a/mysql-test/t/not_partition.test 2006-10-26 17:11:09 +0000
+++ b/mysql-test/t/not_partition.test 2009-01-08 14:16:44 +0000
@@ -1,12 +1,35 @@
--disable_abort_on_error
-# Run this tets only when mysqld don't has partitioning
+# Run this test only when mysqld don't has partitioning (not compiled with)
# the statements are not expected to work, just check that we
# can't crash the server
-- require r/not_partition.require
disable_query_log;
show variables like "have_partitioning";
enable_query_log;
-
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+
+#
+# Bug#39893: Crash if select on a partitioned table,
+# when partitioning is disabled
+FLUSH TABLES;
+--copy_file $MYSQLTEST_VARDIR/std_data_ln/parts/t1.frm $MYSQLD_DATADIR/test/t1.frm
+SELECT * FROM t1;
+TRUNCATE TABLE t1;
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+ALTER TABLE t1 REPAIR PARTITION ALL;
+ALTER TABLE t1 CHECK PARTITION ALL;
+ALTER TABLE t1 OPTIMIZE PARTITION ALL;
+ALTER TABLE t1 ANALYZE PARTITION ALL;
+ALTER TABLE t1 REBUILD PARTITION ALL;
+ALTER TABLE t1 ENGINE Memory;
+ALTER TABLE t1 ADD (new INT);
+DROP TABLE t1;
--error ER_FEATURE_DISABLED
CREATE TABLE t1 (
=== modified file 'mysql-test/t/partition.test'
--- a/mysql-test/t/partition.test 2009-10-28 07:52:34 +0000
+++ b/mysql-test/t/partition.test 2009-11-06 17:22:32 +0000
@@ -15,6 +15,53 @@ drop table if exists t1, t2;
--enable_warnings
#
+# Bug#46639: 1030 (HY000): Got error 124 from storage engine on
+# INSERT ... SELECT ...
+CREATE TABLE t1 (
+ a int NOT NULL,
+ b int NOT NULL);
+
+CREATE TABLE t2 (
+ a int NOT NULL,
+ b int NOT NULL,
+ INDEX(b)
+)
+PARTITION BY HASH(a) PARTITIONS 2;
+
+INSERT INTO t1 VALUES (399, 22);
+INSERT INTO t2 VALUES (1, 22), (1, 42);
+
+INSERT INTO t2 SELECT 1, 399 FROM t2, t1
+WHERE t1.b = t2.b;
+
+DROP TABLE t1, t2;
+
+#
+# Bug#46478: timestamp field incorrectly defaulted when partition is reorganized
+#
+CREATE TABLE t1 (
+ a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ b varchar(10),
+ PRIMARY KEY (a)
+)
+PARTITION BY RANGE (to_days(a)) (
+ PARTITION p1 VALUES LESS THAN (733407),
+ PARTITION pmax VALUES LESS THAN MAXVALUE
+);
+
+INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1');
+INSERT INTO t1 VALUES ('2009-07-14 17:35:55', 'pmax');
+INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax');
+
+SELECT * FROM t1;
+ALTER TABLE t1 REORGANIZE PARTITION pmax INTO (
+ PARTITION p3 VALUES LESS THAN (733969),
+ PARTITION pmax VALUES LESS THAN MAXVALUE);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+#
# Bug#36001: Partitions: spelling and using some error messages
#
--error ER_FOREIGN_KEY_ON_PARTITIONED
=== added file 'mysql-test/t/partition_disabled-master.opt'
--- a/mysql-test/t/partition_disabled-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/partition_disabled-master.opt 2009-01-08 14:16:44 +0000
@@ -0,0 +1 @@
+--loose-skip-partition
=== added file 'mysql-test/t/partition_disabled.test'
--- a/mysql-test/t/partition_disabled.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/partition_disabled.test 2009-08-12 10:03:05 +0000
@@ -0,0 +1,85 @@
+--disable_abort_on_error
+# Run this test only when mysqld has partitioning, but it is disabled.
+# The statements are not expected to work, just check that we
+# can't crash the server.
+--require r/disabled_partition.require
+--disable_query_log
+show variables like "have_partitioning";
+--enable_query_log
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+
+#
+# Bug#39893: Crash if select on a partitioned table,
+# when partitioning is disabled
+FLUSH TABLES;
+--copy_file $MYSQLTEST_VARDIR/std_data/parts/t1.frm $MYSQLD_DATADIR/test/t1.frm
+SELECT * FROM t1;
+TRUNCATE TABLE t1;
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+ALTER TABLE t1 REPAIR PARTITION ALL;
+ALTER TABLE t1 CHECK PARTITION ALL;
+ALTER TABLE t1 OPTIMIZE PARTITION ALL;
+ALTER TABLE t1 ANALYZE PARTITION ALL;
+ALTER TABLE t1 REBUILD PARTITION ALL;
+ALTER TABLE t1 ENGINE Memory;
+ALTER TABLE t1 ADD (new INT);
+DROP TABLE t1;
+
+--error ER_OPTION_PREVENTS_STATEMENT
+CREATE TABLE t1 (
+ firstname VARCHAR(25) NOT NULL,
+ lastname VARCHAR(25) NOT NULL,
+ username VARCHAR(16) NOT NULL,
+ email VARCHAR(35),
+ joined DATE NOT NULL
+)
+PARTITION BY KEY(joined)
+PARTITIONS 6;
+
+--error ER_OPTION_PREVENTS_STATEMENT
+ALTER TABLE t1 PARTITION BY KEY(joined) PARTITIONS 2;
+
+--error ER_BAD_TABLE_ERROR
+drop table t1;
+
+--error ER_OPTION_PREVENTS_STATEMENT
+CREATE TABLE t1 (
+ firstname VARCHAR(25) NOT NULL,
+ lastname VARCHAR(25) NOT NULL,
+ username VARCHAR(16) NOT NULL,
+ email VARCHAR(35),
+ joined DATE NOT NULL
+)
+PARTITION BY RANGE( YEAR(joined) ) (
+ PARTITION p0 VALUES LESS THAN (1960),
+ PARTITION p1 VALUES LESS THAN (1970),
+ PARTITION p2 VALUES LESS THAN (1980),
+ PARTITION p3 VALUES LESS THAN (1990),
+ PARTITION p4 VALUES LESS THAN MAXVALUE
+);
+--error ER_BAD_TABLE_ERROR
+drop table t1;
+
+--error ER_OPTION_PREVENTS_STATEMENT
+CREATE TABLE t1 (id INT, purchased DATE)
+ PARTITION BY RANGE( YEAR(purchased) )
+ SUBPARTITION BY HASH( TO_DAYS(purchased) )
+ SUBPARTITIONS 2 (
+ PARTITION p0 VALUES LESS THAN (1990),
+ PARTITION p1 VALUES LESS THAN (2000),
+ PARTITION p2 VALUES LESS THAN MAXVALUE
+ );
+--error ER_BAD_TABLE_ERROR
+drop table t1;
+
+# Create a table without partitions to test "EXPLAIN PARTITIONS"
+create table t1 (a varchar(10) charset latin1 collate latin1_bin);
+insert into t1 values (''),(' '),('a'),('a '),('a ');
+explain partitions select * from t1 where a='a ' OR a='a';
+drop table t1;
=== modified file 'mysql-test/t/partition_pruning.test'
--- a/mysql-test/t/partition_pruning.test 2008-12-28 11:33:49 +0000
+++ b/mysql-test/t/partition_pruning.test 2009-08-28 10:55:59 +0000
@@ -9,6 +9,357 @@ drop table if exists t1,t2,t3,t4,t5,t6,t
--enable_warnings
#
+# Bug#20577: Partitions: use of to_days() function leads to selection failures
+#
+--let $explain_partitions= 1;
+--let $verify_without_partitions= 0;
+--echo # test of RANGE and index
+CREATE TABLE t1 (a DATE, KEY(a))
+PARTITION BY RANGE (TO_DAYS(a))
+(PARTITION `pNULL` VALUES LESS THAN (0),
+ PARTITION `p0001-01-01` VALUES LESS THAN (366 + 1),
+ PARTITION `p1001-01-01` VALUES LESS THAN (TO_DAYS('1001-01-01') + 1),
+ PARTITION `p2001-01-01` VALUES LESS THAN (TO_DAYS('2001-01-01') + 1));
+if ($verify_without_partitions)
+{
+ALTER TABLE t1 REMOVE PARTITIONING;
+}
+INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
+ ('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
+--source include/partition_date_range.inc
+--echo # test without index
+ALTER TABLE t1 DROP KEY a;
+--source include/partition_date_range.inc
+DROP TABLE t1;
+
+--echo # test of LIST and index
+CREATE TABLE t1 (a DATE, KEY(a))
+PARTITION BY LIST (TO_DAYS(a))
+(PARTITION `p0001-01-01` VALUES IN (TO_DAYS('0001-01-01')),
+ PARTITION `p2001-01-01` VALUES IN (TO_DAYS('2001-01-01')),
+ PARTITION `pNULL` VALUES IN (NULL),
+ PARTITION `p0000-01-02` VALUES IN (TO_DAYS('0000-01-02')),
+ PARTITION `p1001-01-01` VALUES IN (TO_DAYS('1001-01-01')));
+if ($verify_without_partitions)
+{
+ALTER TABLE t1 REMOVE PARTITIONING;
+}
+INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
+ ('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
+--source include/partition_date_range.inc
+--echo # test without index
+ALTER TABLE t1 DROP KEY a;
+--source include/partition_date_range.inc
+DROP TABLE t1;
+
+#
+# Bug#46362: Endpoint should be set to false for TO_DAYS(DATE)
+# There is a problem when comparing DATE with DATETIME.
+# In pruning it is converted into the field type
+# and in row evaluation it is converted to longlong
+# (like a DATETIME).
+--echo # Test with DATETIME column NOT NULL
+CREATE TABLE t1 (
+ a int(10) unsigned NOT NULL,
+ b DATETIME NOT NULL,
+ PRIMARY KEY (a, b)
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+ PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+ PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+ PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+ PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+ (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'),
+ (1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'),
+ (1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+DROP TABLE t1;
+
+--echo # Test with DATE column NOT NULL
+CREATE TABLE t1 (
+ a int(10) unsigned NOT NULL,
+ b DATE NOT NULL,
+ PRIMARY KEY (a, b)
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+ PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+ PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+ PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+ PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+ (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'),
+ (1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'),
+ (1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+DROP TABLE t1;
+
+--echo # Test with DATETIME column NULL
+CREATE TABLE t1 (
+ a int(10) unsigned NOT NULL,
+ b DATETIME NULL
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+ PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+ PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+ PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+ PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+ (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'),
+ (1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'),
+ (1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+DROP TABLE t1;
+
+--echo # Test with DATE column NULL
+CREATE TABLE t1 (
+ a int(10) unsigned NOT NULL,
+ b DATE NULL
+) PARTITION BY RANGE (TO_DAYS(b))
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+ PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+ PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+ PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+ PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'),
+ (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'),
+ (1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'),
+ (1, '2009-04-07');
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE);
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03';
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME);
+EXPLAIN PARTITIONS SELECT * FROM t1
+ WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME);
+DROP TABLE t1;
+
+--echo # For better code coverage of the patch
+CREATE TABLE t1 (
+ a int(10) unsigned NOT NULL,
+ b DATE
+) PARTITION BY RANGE ( TO_DAYS(b) )
+(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')),
+ PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')),
+ PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')),
+ PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')),
+ PARTITION p20090405 VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL);
+--echo # test with an invalid date, which lead to item->null_value is set.
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME);
+DROP TABLE t1;
+
+#
# Bug#40972: some sql execution lead the whole database crashing
#
# Setup so the start is at partition pX and end is at p1
=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test 2009-10-28 07:52:34 +0000
+++ b/mysql-test/t/subselect.test 2009-11-06 17:22:32 +0000
@@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1);
SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
-- error ER_WRONG_USAGE
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
--- error ER_WRONG_PARAMETERS_TO_PROCEDURE
+-- error ER_WRONG_USAGE
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-- error ER_BAD_FIELD_ERROR
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -3342,6 +3342,38 @@ EXPLAIN EXTENDED SELECT * FROM C WHERE `
DROP TABLE C;
--echo # End of test for bug#45061.
+
+--echo #
+--echo # Bug #46749: Segfault in add_key_fields() with outer subquery level
+--echo # field references
+--echo #
+
+CREATE TABLE t1 (
+ a int,
+ b int,
+ UNIQUE (a), KEY (b)
+);
+INSERT INTO t1 VALUES (1,1), (2,1);
+
+CREATE TABLE st1 like t1;
+INSERT INTO st1 VALUES (1,1), (2,1);
+
+CREATE TABLE st2 like t1;
+INSERT INTO st2 VALUES (1,1), (2,1);
+
+# should have "impossible where"
+EXPLAIN
+SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
+FROM t1
+WHERE a = 230;
+
+# should not crash
+SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
+FROM t1
+WHERE a = 230;
+
+DROP TABLE t1, st1, st2;
+
--echo End of 5.0 tests.
#
=== added file 'mysql-test/t/table_elim_debug.test'
--- a/mysql-test/t/table_elim_debug.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/table_elim_debug.test 2009-10-29 17:50:33 +0000
@@ -0,0 +1,27 @@
+#
+# Table elimination (MWL#17) tests that need debug build
+#
+--source include/have_debug.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+# Check if optimizer_switch works
+
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3);
+
+create table t2 (a int primary key, b int)
+ as select a, a as b from t1 where a in (1,2);
+
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+
+set optimizer_switch='table_elimination=off';
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+set optimizer_switch='table_elimination=on';
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+set optimizer_switch='table_elimination=default';
+explain select t1.a from t1 left join t2 on t2.a=t1.a;
+
+drop table t1, t2;
=== modified file 'mysql-test/t/type_newdecimal.test'
--- a/mysql-test/t/type_newdecimal.test 2009-07-03 10:36:04 +0000
+++ b/mysql-test/t/type_newdecimal.test 2009-08-24 19:47:08 +0000
@@ -1286,3 +1286,137 @@ CREATE TABLE t1 SELECT 1 % .123456789123
DESCRIBE t1;
SELECT my_col FROM t1;
DROP TABLE t1;
+
+--echo #
+--echo # Bug#45261: Crash, stored procedure + decimal
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 SELECT
+ /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT
+ .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */
+ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Test that the integer and decimal parts are properly calculated.
+--echo #
+
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
+DESC t2;
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1;
+DESC t2;
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (a DECIMAL(30,30));
+INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
+CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1;
+DESC t2;
+DROP TABLE t1,t2;
+
+--echo #
+--echo # Test that variables get maximum precision.
+--echo #
+
+SET @decimal= 1.1;
+CREATE TABLE t1 SELECT @decimal AS c1;
+DESC t1;
+SELECT * FROM t1;
+DROP TABLE t1;
=== modified file 'mysql-test/t/view.test'
--- a/mysql-test/t/view.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/view.test 2009-10-15 21:38:29 +0000
@@ -3703,38 +3703,6 @@ DROP TABLE t1;
--echo # -- End of test case for Bug#40825
--echo
---echo #
---echo # Bug #45806 crash when replacing into a view with a join!
---echo #
-CREATE TABLE t1(a INT UNIQUE);
-CREATE VIEW v1 AS SELECT t1.a FROM t1, t1 AS a;
-INSERT INTO t1 VALUES (1), (2);
-
-REPLACE INTO v1(a) SELECT 1 FROM t1,t1 AS c;
-SELECT * FROM v1;
-REPLACE INTO v1(a) SELECT 3 FROM t1,t1 AS c;
-SELECT * FROM v1;
-DELETE FROM t1 WHERE a=3;
-INSERT INTO v1(a) SELECT 1 FROM t1,t1 AS c
-ON DUPLICATE KEY UPDATE `v1`.`a`= 1;
-SELECT * FROM v1;
-
-CREATE VIEW v2 AS SELECT t1.a FROM t1, v1 AS a;
-
-REPLACE INTO v2(a) SELECT 1 FROM t1,t1 AS c;
-SELECT * FROM v2;
-REPLACE INTO v2(a) SELECT 3 FROM t1,t1 AS c;
-SELECT * FROM v2;
-INSERT INTO v2(a) SELECT 1 FROM t1,t1 AS c
-ON DUPLICATE KEY UPDATE `v2`.`a`= 1;
-SELECT * FROM v2;
-
-DROP VIEW v1;
-DROP VIEW v2;
-DROP TABLE t1;
-
---echo # -- End of test case for Bug#45806
-
--echo # -----------------------------------------------------------------
--echo # -- End of 5.0 tests.
--echo # -----------------------------------------------------------------
=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp 2009-09-15 10:46:35 +0000
+++ b/mysql-test/valgrind.supp 2009-10-30 18:50:56 +0000
@@ -880,3 +880,17 @@
fun:nptl_pthread_exit_hack_handler
fun:start_thread
}
+
+#
+# Problem with glibc and gethostbyaddr_r
+#
+
+{
+ libc_res_nsend: Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ fun: __libc_res_nsend
+ fun: __libc_res_nquery
+ obj: /lib64/libnss_dns-*so)
+ obj: /lib64/libnss_dns-*so)
+ fun: gethostbyaddr_r
+}
=== modified file 'mysys/array.c'
--- a/mysys/array.c 2009-09-07 20:50:10 +0000
+++ b/mysys/array.c 2009-10-15 21:38:29 +0000
@@ -61,7 +61,7 @@ my_bool init_dynamic_array2(DYNAMIC_ARRA
Since the dynamic array is usable even if allocation fails here malloc
should not throw an error
*/
- if (!(array->buffer= (char*) my_malloc_ci(element_size*init_alloc, MYF(0))))
+ if (!(array->buffer= (uchar*) my_malloc_ci(element_size*init_alloc, MYF(0))))
array->max_element=0;
DBUG_RETURN(FALSE);
}
=== modified file 'mysys/mf_iocache.c'
--- a/mysys/mf_iocache.c 2008-04-28 16:24:05 +0000
+++ b/mysys/mf_iocache.c 2009-10-15 21:38:29 +0000
@@ -227,15 +227,21 @@ int init_io_cache(IO_CACHE *info, File f
for (;;)
{
size_t buffer_block;
+ /*
+ Unset MY_WAIT_IF_FULL bit if it is set, to prevent conflict with
+ MY_ZEROFILL.
+ */
+ myf flags= (myf) (cache_myflags & ~(MY_WME | MY_WAIT_IF_FULL));
+
if (cachesize < min_cache)
cachesize = min_cache;
buffer_block= cachesize;
if (type == SEQ_READ_APPEND)
buffer_block *= 2;
- if ((info->buffer=
- (uchar*) my_malloc(buffer_block,
- MYF((cache_myflags & ~ MY_WME) |
- (cachesize == min_cache ? MY_WME : 0)))) != 0)
+ if (cachesize == min_cache)
+ flags|= (myf) MY_WME;
+
+ if ((info->buffer= (uchar*) my_malloc(buffer_block, flags)) != 0)
{
info->write_buffer=info->buffer;
if (type == SEQ_READ_APPEND)
=== modified file 'mysys/mf_pack.c'
--- a/mysys/mf_pack.c 2008-08-18 17:11:55 +0000
+++ b/mysys/mf_pack.c 2009-08-28 16:21:54 +0000
@@ -33,12 +33,11 @@ static char * NEAR_F expand_tilde(char *
void pack_dirname(char * to, const char *from)
{
int cwd_err;
- size_t d_length,length,buff_length;
+ size_t d_length,length,UNINIT_VAR(buff_length);
char * start;
char buff[FN_REFLEN];
DBUG_ENTER("pack_dirname");
- LINT_INIT(buff_length);
(void) intern_filename(to,from); /* Change to intern name */
#ifdef FN_DEVCHAR
=== modified file 'mysys/my_copy.c'
--- a/mysys/my_copy.c 2009-10-26 11:35:42 +0000
+++ b/mysys/my_copy.c 2009-11-06 17:22:32 +0000
@@ -57,6 +57,7 @@ int my_copy(const char *from, const char
File from_file,to_file;
uchar buff[IO_SIZE];
MY_STAT stat_buff,new_stat_buff;
+ int res;
DBUG_ENTER("my_copy");
DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));
@@ -95,7 +96,7 @@ int my_copy(const char *from, const char
if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
DBUG_RETURN(0); /* File copyed but not stat */
- VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */
+ res= chmod(to, stat_buff.st_mode & 07777); /* Copy modes */
#if !defined(__WIN__) && !defined(__NETWARE__)
if (chown(to, stat_buff.st_uid,stat_buff.st_gid))
{
=== modified file 'mysys/my_getopt.c'
--- a/mysys/my_getopt.c 2009-09-15 12:53:07 +0000
+++ b/mysys/my_getopt.c 2009-10-15 21:38:29 +0000
@@ -115,7 +115,7 @@ int handle_options(int *argc, char ***ar
uint opt_found, argvpos= 0, length;
my_bool end_of_options= 0, must_be_var, set_maximum_value,
option_is_loose;
- char **pos, **pos_end, *optend, *prev_found,
+ char **pos, **pos_end, *optend, *UNINIT_VAR(prev_found),
*opt_str, key_name[FN_REFLEN];
const struct my_option *optp;
uchar* *value;
=== modified file 'mysys/my_redel.c'
--- a/mysys/my_redel.c 2009-10-26 11:35:42 +0000
+++ b/mysys/my_redel.c 2009-11-06 17:22:32 +0000
@@ -77,6 +77,9 @@ end:
int my_copystat(const char *from, const char *to, int MyFlags)
{
struct stat statbuf;
+#if !defined(__WIN__) && !defined(__NETWARE__)
+ int res;
+#endif
if (stat((char*) from, &statbuf))
{
=== modified file 'mysys/safemalloc.c'
--- a/mysys/safemalloc.c 2009-10-26 11:38:17 +0000
+++ b/mysys/safemalloc.c 2009-11-06 17:22:32 +0000
@@ -272,6 +272,9 @@ void _myfree(void *ptr, const char *file
irem= (struct st_irem *) ((char*) ptr- ALIGN_SIZE(sizeof(struct st_irem))-
sf_malloc_prehunc);
+ if (sf_malloc_quick)
+ (void) _checkchunk(irem, filename, lineno);
+
/*
Check to make sure that we have a real remember structure.
Note: this test could fail for four reasons:
=== modified file 'mysys/typelib.c'
--- a/mysys/typelib.c 2009-03-12 22:27:35 +0000
+++ b/mysys/typelib.c 2009-10-15 21:38:29 +0000
@@ -78,7 +78,8 @@ uint find_type_or_exit(const char *x, TY
int find_type(char *x, const TYPELIB *typelib, uint full_name)
{
- int find,pos,findpos;
+ int find,pos;
+ int UNINIT_VAR(findpos); /* guarded by find */
reg1 char * i;
reg2 const char *j;
DBUG_ENTER("find_type");
@@ -89,7 +90,6 @@ int find_type(char *x, const TYPELIB *ty
DBUG_PRINT("exit",("no count"));
DBUG_RETURN(0);
}
- LINT_INIT(findpos);
find=0;
for (pos=0 ; (j=typelib->type_names[pos]) ; pos++)
{
=== modified file 'regex/regcomp.c'
--- a/regex/regcomp.c 2007-08-13 13:11:25 +0000
+++ b/regex/regcomp.c 2009-08-28 16:21:54 +0000
@@ -213,11 +213,11 @@ register struct parse *p;
int stop; /* character this ERE should end at */
{
register char c;
- register sopno prevback;
- register sopno prevfwd;
+ register sopno UNINIT_VAR(prevback);
+ register sopno UNINIT_VAR(prevfwd);
register sopno conc;
register int first = 1; /* is this the first alternative? */
- LINT_INIT(prevback); LINT_INIT(prevfwd);
+
for (;;) {
/* do a bunch of concatenated expressions */
conc = HERE();
=== modified file 'scripts/make_binary_distribution.sh'
--- a/scripts/make_binary_distribution.sh 2009-10-23 16:48:54 +0000
+++ b/scripts/make_binary_distribution.sh 2009-10-30 20:28:11 +0000
@@ -231,6 +231,18 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; t
# ----------------------------------------------------------------------
set -e
+ #
+ # Check that the client is compiled with libmysqlclient.a
+ #
+ if test -f ./client/.libs/mysql
+ then
+ echo ""
+ echo "The MySQL clients are compiled dynamicly, which is not allowed for"
+ echo "a MySQL binary tar file. Please configure with"
+ echo "--with-client-ldflags=-all-static and try again"
+ exit 1;
+ fi
+
# ----------------------------------------------------------------------
# Really ugly, one script, "mysql_install_db", needs prefix set to ".",
# i.e. makes access relative the current directory. This matches
@@ -293,11 +305,6 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; t
fi
fi
- # FIXME let this script be in "bin/", where it is in the RPMs?
- # http://dev.mysql.com/doc/refman/5.1/en/mysql-install-db-problems.html
- mkdir $DEST/scripts
- mv $DEST/bin/mysql_install_db $DEST/scripts/
-
# Note, no legacy "safe_mysqld" link to "mysqld_safe" in 5.1
# Copy readme and license files
@@ -330,18 +337,25 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; t
#
# Move things to make them easier to find in tar installation
#
- mv $DEST/libexec/* $DEST/bin
+
+ # The following test is needed if the original configure was done with
+ # something like --libexecdir=/usr/local/mysql/bin
+ if test -f $DEST/libexec/mysqld
+ then
+ mv $DEST/libexec/* $DEST/bin
+ rmdir $DEST/libexec
+ fi
mv $DEST/share/man $DEST
mv $DEST/share/mysql/binary-configure $DEST/configure
mv $DEST/share/mysql/*.sql $DEST/share
mv $DEST/share/mysql/*.cnf $DEST/share/mysql/*.server $DEST/share/mysql/mysql-log-rotate $DEST/support-files
- rmdir $DEST/libexec
#
# Move some scripts that are only run once to 'scripts' directory
# but add symbolic links instead to old place for compatibility
#
- for i in mysql_secure_installation mysql_fix_extensions mysql_fix_privilege_tables
+ mkdir $DEST/scripts
+ for i in mysql_secure_installation mysql_fix_extensions mysql_fix_privilege_tables mysql_install_db
do
mv $DEST/bin/$i $DEST/scripts
ln -s "../scripts/$i" $DEST/bin/$i
=== modified file 'server-tools/instance-manager/mysql_connection.cc'
--- a/server-tools/instance-manager/mysql_connection.cc 2009-04-25 10:05:32 +0000
+++ b/server-tools/instance-manager/mysql_connection.cc 2009-10-15 21:38:29 +0000
@@ -69,6 +69,18 @@ void my_net_local_init(NET *net)
C_MODE_END
+/*
+ Unused stub hook required for linking the client API.
+*/
+
+C_MODE_START
+
+void slave_io_thread_detach_vio()
+{
+}
+
+C_MODE_END
+
/*
Every resource, which we can fail to acquire, is allocated in init().
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2009-09-07 20:50:10 +0000
+++ b/sql-common/client.c 2009-10-15 21:38:29 +0000
@@ -482,6 +482,15 @@ HANDLE create_shared_memory(MYSQL *mysql
int 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))))
@@ -933,6 +942,9 @@ void end_server(MYSQL *mysql)
{
init_sigpipe_variables
DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
+#ifdef MYSQL_SERVER
+ slave_io_thread_detach_vio();
+#endif
set_sigpipe(mysql);
vio_delete(mysql->net.vio);
reset_sigpipe(mysql);
@@ -1851,7 +1863,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100];
- char *end,*host_info;
+ char *end,*host_info= NULL;
my_socket sock;
in_addr_t ip_addr;
struct sockaddr_in sock_addr;
@@ -1869,7 +1881,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
#endif
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
- LINT_INIT(host_info);
DBUG_PRINT("enter",("host: %s db: %s user: %s",
host ? host : "(Null)",
=== modified file 'sql-common/my_time.c'
--- a/sql-common/my_time.c 2009-06-11 16:21:32 +0000
+++ b/sql-common/my_time.c 2009-09-01 11:04:56 +0000
@@ -160,7 +160,7 @@ enum enum_mysql_timestamp_type
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
uint flags, int *was_cut)
{
- uint field_length, year_length, digits, i, number_of_fields;
+ uint field_length, UNINIT_VAR(year_length), digits, i, number_of_fields;
uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
uint add_hours= 0, start_loop;
ulong not_zero_date, allow_space;
@@ -174,7 +174,6 @@ str_to_datetime(const char *str, uint le
DBUG_PRINT("ENTER",("str: %.*s",length,str));
LINT_INIT(field_length);
- LINT_INIT(year_length);
LINT_INIT(last_field_pos);
*was_cut= 0;
@@ -450,9 +449,7 @@ str_to_datetime(const char *str, uint le
}
}
- DBUG_RETURN(l_time->time_type=
- (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE :
- MYSQL_TIMESTAMP_DATETIME));
+ DBUG_RETURN(l_time->time_type);
err:
bzero((char*) l_time, sizeof(*l_time));
@@ -778,11 +775,12 @@ long calc_daynr(uint year,uint month,uin
if (y == 0 && month == 0 && day == 0)
DBUG_RETURN(0); /* Skip errors */
- delsum= (long) (365L * y+ 31*(month-1) +day);
+ /* Cast to int to be able to handle month == 0 */
+ delsum= (long) (365 * y + 31 *((int) month - 1) + (int) day);
if (month <= 2)
y--;
else
- delsum-= (long) (month*4+23)/10;
+ delsum-= (long) ((int) month * 4 + 23) / 10;
temp=(int) ((y/100+1)*3)/4;
DBUG_PRINT("exit",("year: %d month: %d day: %d -> daynr: %ld",
y+(month <= 2),month,day,delsum+y/4-temp));
=== modified file 'sql/client_settings.h'
--- a/sql/client_settings.h 2006-12-31 00:02:27 +0000
+++ b/sql/client_settings.h 2009-08-13 20:07:20 +0000
@@ -33,3 +33,11 @@
#define mysql_server_init(a,b,c) 0
+#ifdef HAVE_REPLICATION
+C_MODE_START
+void slave_io_thread_detach_vio();
+C_MODE_END
+#else
+#define slave_io_thread_detach_vio()
+#endif
+
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2009-09-15 10:46:35 +0000
+++ b/sql/events.cc 2009-10-15 21:38:29 +0000
@@ -341,6 +341,33 @@ common_1_lev_code:
/**
+ Create a new query string for removing executable comments
+ for avoiding leak and keeping consistency of the execution
+ on master and slave.
+
+ @param[in] thd Thread handler
+ @param[in] buf Query string
+
+ @return
+ 0 ok
+ 1 error
+*/
+static int
+create_query_string(THD *thd, String *buf)
+{
+ /* Append the "CREATE" part of the query */
+ if (buf->append(STRING_WITH_LEN("CREATE ")))
+ return 1;
+ /* Append definer */
+ append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host));
+ /* Append the left part of thd->query after "DEFINER" part */
+ if (buf->append(thd->lex->stmt_definition_begin))
+ return 1;
+
+ return 0;
+}
+
+/**
Create a new event.
@param[in,out] thd THD
@@ -438,7 +465,16 @@ Events::create_event(THD *thd, Event_par
{
/* Binlog the create event. */
DBUG_ASSERT(thd->query && thd->query_length);
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ String log_query;
+ if (create_query_string(thd, &log_query))
+ {
+ sql_print_error("Event Error: An error occurred while creating query string, "
+ "before writing it into binary log.");
+ DBUG_RETURN(TRUE);
+ }
+ /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER
+ will be written into the binary log as the definer for the SQL thread. */
+ write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length());
}
}
pthread_mutex_unlock(&LOCK_event_metadata);
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2009-09-07 20:50:10 +0000
+++ b/sql/field.cc 2009-11-10 02:32:39 +0000
@@ -57,7 +57,7 @@ const char field_separator=',';
((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1)))
#define ASSERT_COLUMN_MARKED_FOR_READ DBUG_ASSERT(!table || (!table->read_set || bitmap_is_set(table->read_set, field_index)))
-#define ASSERT_COLUMN_MARKED_FOR_WRITE DBUG_ASSERT(!table || (!table->write_set || bitmap_is_set(table->write_set, field_index)))
+#define ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED DBUG_ASSERT(!table || (!table->write_set || bitmap_is_set(table->write_set, field_index) || bitmap_is_set(&table->vcol_set, field_index)))
/*
Rules for merging different types of fields in UNION
@@ -1312,7 +1312,8 @@ Field::Field(uchar *ptr_arg,uint32 lengt
key_start(0), part_of_key(0), part_of_key_not_clustered(0),
part_of_sortkey(0), unireg_check(unireg_check_arg),
field_length(length_arg), null_bit(null_bit_arg),
- is_created_from_null_item(FALSE)
+ is_created_from_null_item(FALSE),
+ vcol_info(0), stored_in_db(TRUE)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -1611,7 +1612,7 @@ longlong Field::convert_decimal2longlong
int Field_num::store_decimal(const my_decimal *val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int err= 0;
longlong i= convert_decimal2longlong(val, unsigned_flag, &err);
return test(err | store(i, unsigned_flag));
@@ -1683,7 +1684,7 @@ void Field_num::make_field(Send_field *f
int Field_str::store_decimal(const my_decimal *d)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
double val;
/* TODO: use decimal2string? */
int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
@@ -1760,7 +1761,7 @@ bool Field::get_time(MYSQL_TIME *ltime)
int Field::store_time(MYSQL_TIME *ltime, timestamp_type type_arg)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[MAX_DATE_STRING_REP_LENGTH];
uint length= (uint) my_TIME_to_str(ltime, buff);
return store(buff, length, &my_charset_bin);
@@ -1887,7 +1888,7 @@ void Field_decimal::overflow(bool negati
int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff,sizeof(buff), &my_charset_bin);
const uchar *from= (uchar*) from_arg;
@@ -1923,16 +1924,16 @@ int Field_decimal::store(const char *fro
Pointers used when digits move from the left of the '.' to the
right of the '.' (explained below)
*/
- const uchar *int_digits_tail_from;
+ const uchar *UNINIT_VAR(int_digits_tail_from);
/* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */
- uint int_digits_added_zeros;
+ uint UNINIT_VAR(int_digits_added_zeros);
/*
Pointer used when digits move from the right of the '.' to the left
of the '.'
*/
- const uchar *frac_digits_head_end;
+ const uchar *UNINIT_VAR(frac_digits_head_end);
/* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
- uint frac_digits_added_zeros;
+ uint UNINIT_VAR(frac_digits_added_zeros);
uchar *pos,*tmp_left_pos,*tmp_right_pos;
/* Pointers that are used as limits (begin and end of the field buffer) */
uchar *left_wall,*right_wall;
@@ -1943,11 +1944,6 @@ int Field_decimal::store(const char *fro
*/
bool is_cuted_fields_incr=0;
- LINT_INIT(int_digits_tail_from);
- LINT_INIT(int_digits_added_zeros);
- LINT_INIT(frac_digits_head_end);
- LINT_INIT(frac_digits_added_zeros);
-
/*
There are three steps in this function :
- parse the input string
@@ -2258,7 +2254,7 @@ int Field_decimal::store(const char *fro
int Field_decimal::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
if (unsigned_flag && nr < 0)
{
overflow(1);
@@ -2303,7 +2299,7 @@ int Field_decimal::store(double nr)
int Field_decimal::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[22];
uint length, int_part;
char fyllchar;
@@ -2486,12 +2482,97 @@ Field_new_decimal::Field_new_decimal(uin
{
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
+ DBUG_ASSERT(precision >= dec);
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
(dec <= DECIMAL_MAX_SCALE));
bin_size= my_decimal_get_binary_size(precision, dec);
}
+/**
+ Create a field to hold a decimal value from an item.
+
+ @remark The MySQL DECIMAL data type has a characteristic that needs to be
+ taken into account when deducing the type from a Item_decimal.
+
+ But first, let's briefly recap what is the new MySQL DECIMAL type:
+
+ The declaration syntax for a decimal is DECIMAL(M,D), where:
+
+ * M is the maximum number of digits (the precision).
+ It has a range of 1 to 65.
+ * D is the number of digits to the right of the decimal separator (the scale).
+ It has a range of 0 to 30 and must be no larger than M.
+
+ D and M are used to determine the storage requirements for the integer
+ and fractional parts of each value. The integer part is to the left of
+ the decimal separator and to the right is the fractional part. Hence:
+
+ M is the number of digits for the integer and fractional part.
+ D is the number of digits for the fractional part.
+
+ Consequently, M - D is the number of digits for the integer part. For
+ example, a DECIMAL(20,10) column has ten digits on either side of
+ the decimal separator.
+
+ The characteristic that needs to be taken into account is that the
+ backing type for Item_decimal is a my_decimal that has a higher
+ precision (DECIMAL_MAX_POSSIBLE_PRECISION, see my_decimal.h) than
+ DECIMAL.
+
+ Drawing a comparison between my_decimal and DECIMAL:
+
+ * M has a range of 1 to 81.
+ * D has a range of 0 to 81.
+
+ There can be a difference in range if the decimal contains a integer
+ part. This is because the fractional part must always be on a group
+ boundary, leaving at least one group for the integer part. Since each
+ group is 9 (DIG_PER_DEC1) digits and there are 9 (DECIMAL_BUFF_LENGTH)
+ groups, the fractional part is limited to 72 digits if there is at
+ least one digit in the integral part.
+
+ Although the backing type for a DECIMAL is also my_decimal, every
+ time a my_decimal is stored in a DECIMAL field, the precision and
+ scale are explicitly capped at 65 (DECIMAL_MAX_PRECISION) and 30
+ (DECIMAL_MAX_SCALE) digits, following my_decimal truncation procedure
+ (FIX_INTG_FRAC_ERROR).
+*/
+
+Field_new_decimal *
+Field_new_decimal::new_decimal_field(const Item *item)
+{
+ uint32 len;
+ uint intg= item->decimal_int_part(), scale= item->decimals;
+
+ DBUG_ASSERT(item->decimal_precision() >= item->decimals);
+
+ /*
+ Employ a procedure along the lines of the my_decimal truncation process:
+ - If the integer part is equal to or bigger than the maximum precision:
+ Truncate integer part to fit and the fractional becomes zero.
+ - Otherwise:
+ Truncate fractional part to fit.
+ */
+ if (intg >= DECIMAL_MAX_PRECISION)
+ {
+ intg= DECIMAL_MAX_PRECISION;
+ scale= 0;
+ }
+ else
+ {
+ uint room= min(DECIMAL_MAX_PRECISION - intg, DECIMAL_MAX_SCALE);
+ if (scale > room)
+ scale= room;
+ }
+
+ len= my_decimal_precision_to_length(intg + scale, scale, item->unsigned_flag);
+
+ return new Field_new_decimal(len, item->maybe_null, item->name, scale,
+ item->unsigned_flag);
+}
+
+
int Field_new_decimal::reset(void)
{
store_value(&decimal_zero);
@@ -2539,7 +2620,7 @@ void Field_new_decimal::set_value_on_ove
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
DBUG_ENTER("Field_new_decimal::store_value");
#ifndef DBUG_OFF
@@ -2584,7 +2665,7 @@ bool Field_new_decimal::store_value(cons
int Field_new_decimal::store(const char *from, uint length,
CHARSET_INFO *charset_arg)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int err;
my_decimal decimal_value;
DBUG_ENTER("Field_new_decimal::store(char*)");
@@ -2651,7 +2732,7 @@ int Field_new_decimal::store(const char
int Field_new_decimal::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
my_decimal decimal_value;
int err;
DBUG_ENTER("Field_new_decimal::store(double)");
@@ -2686,7 +2767,7 @@ int Field_new_decimal::store(double nr)
int Field_new_decimal::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
my_decimal decimal_value;
int err;
@@ -2708,7 +2789,7 @@ int Field_new_decimal::store(longlong nr
int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
return store_value(decimal_value);
}
@@ -2929,7 +3010,7 @@ Field_new_decimal::unpack(uchar* to,
int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error;
longlong rnd;
@@ -2941,7 +3022,7 @@ int Field_tiny::store(const char *from,u
int Field_tiny::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
nr=rint(nr);
if (unsigned_flag)
@@ -2984,7 +3065,7 @@ int Field_tiny::store(double nr)
int Field_tiny::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if (unsigned_flag)
@@ -3104,7 +3185,7 @@ void Field_tiny::sql_type(String &res) c
int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int store_tmp;
int error;
longlong rnd;
@@ -3125,7 +3206,7 @@ int Field_short::store(const char *from,
int Field_short::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int16 res;
nr=rint(nr);
@@ -3177,7 +3258,7 @@ int Field_short::store(double nr)
int Field_short::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int16 res;
@@ -3351,7 +3432,7 @@ void Field_short::sql_type(String &res)
int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int store_tmp;
int error;
longlong rnd;
@@ -3365,7 +3446,7 @@ int Field_medium::store(const char *from
int Field_medium::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
nr=rint(nr);
if (unsigned_flag)
@@ -3411,7 +3492,7 @@ int Field_medium::store(double nr)
int Field_medium::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if (unsigned_flag)
@@ -3541,7 +3622,7 @@ void Field_medium::sql_type(String &res)
int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long store_tmp;
int error;
longlong rnd;
@@ -3562,7 +3643,7 @@ int Field_long::store(const char *from,u
int Field_long::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int32 res;
nr=rint(nr);
@@ -3614,7 +3695,7 @@ int Field_long::store(double nr)
int Field_long::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int32 res;
@@ -3788,7 +3869,7 @@ void Field_long::sql_type(String &res) c
int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
char *end;
ulonglong tmp;
@@ -3818,7 +3899,7 @@ int Field_longlong::store(const char *fr
int Field_longlong::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
longlong res;
@@ -3870,7 +3951,7 @@ int Field_longlong::store(double nr)
int Field_longlong::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if (nr < 0) // Only possible error
@@ -4096,7 +4177,7 @@ int Field_float::store(const char *from,
int Field_float::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= truncate(&nr, FLT_MAX);
float j= (float)nr;
@@ -4358,7 +4439,7 @@ int Field_double::store(const char *from
int Field_double::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= truncate(&nr, DBL_MAX);
#ifdef WORDS_BIGENDIAN
@@ -4785,7 +4866,7 @@ timestamp_auto_set_type Field_timestamp:
int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
my_time_t tmp= 0;
int error;
@@ -4848,7 +4929,7 @@ int Field_timestamp::store(double nr)
int Field_timestamp::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
my_time_t timestamp= 0;
int error;
@@ -5147,7 +5228,7 @@ int Field_time::store_time(MYSQL_TIME *l
int Field_time::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
int error= 0;
if (nr > (double)TIME_MAX_VALUE)
@@ -5185,7 +5266,7 @@ int Field_time::store(double nr)
int Field_time::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
int error= 0;
if (nr < (longlong) -TIME_MAX_VALUE && !unsigned_val)
@@ -5356,7 +5437,7 @@ void Field_time::sql_type(String &res) c
int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char *end;
int error;
longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error);
@@ -5404,7 +5485,7 @@ int Field_year::store(double nr)
int Field_year::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155)
{
*ptr= 0;
@@ -5477,7 +5558,7 @@ void Field_year::sql_type(String &res) c
int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
uint32 tmp;
int error;
@@ -5532,7 +5613,7 @@ int Field_date::store(double nr)
int Field_date::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME not_used;
int error;
longlong initial_nr= nr;
@@ -5711,7 +5792,7 @@ void Field_date::sql_type(String &res) c
int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
MYSQL_TIME l_time;
int error;
@@ -5761,7 +5842,7 @@ int Field_newdate::store(double nr)
int Field_newdate::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
longlong tmp;
int error;
@@ -5797,7 +5878,7 @@ int Field_newdate::store(longlong nr, bo
int Field_newdate::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
int error= 0;
if (time_type == MYSQL_TIMESTAMP_DATE ||
@@ -5944,7 +6025,7 @@ void Field_newdate::sql_type(String &res
int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME time_tmp;
int error;
ulonglong tmp= 0;
@@ -5997,7 +6078,7 @@ int Field_datetime::store(double nr)
int Field_datetime::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME not_used;
int error;
longlong initial_nr= nr;
@@ -6035,7 +6116,7 @@ int Field_datetime::store(longlong nr, b
int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
longlong tmp;
int error= 0;
/*
@@ -6338,7 +6419,7 @@ Field_longstr::report_if_important_data(
int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
@@ -6379,7 +6460,7 @@ int Field_string::store(const char *from
int Field_str::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
uint length;
uint local_char_length= field_length / charset()->mbmaxlen;
@@ -6994,7 +7075,7 @@ int Field_varstring::do_save_field_metad
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
@@ -7658,7 +7739,7 @@ void Field_blob::put_length(uchar *pos,
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length, new_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
@@ -8420,7 +8501,7 @@ void Field_enum::store_type(ulonglong va
int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int err= 0;
uint32 not_used;
char buff[STRING_BUFFER_USUAL_SIZE];
@@ -8469,7 +8550,7 @@ int Field_enum::store(double nr)
int Field_enum::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if ((ulonglong) nr > typelib->count || nr == 0)
{
@@ -8638,7 +8719,7 @@ Field *Field_enum::new_field(MEM_ROOT *r
int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
bool got_warning= 0;
int err= 0;
char *not_used;
@@ -8678,7 +8759,7 @@ int Field_set::store(const char *from,ui
int Field_set::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
ulonglong max_nr= set_bits(ulonglong, typelib->count);
if ((ulonglong) nr > max_nr)
@@ -8942,7 +9023,7 @@ uint Field_bit::is_equal(Create_field *n
int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int delta;
for (; length && !*from; from++, length--) // skip left 0's
@@ -9353,7 +9434,7 @@ Field_bit_as_char::Field_bit_as_char(uch
int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int delta;
uchar bits= (uchar) (field_length & 7);
@@ -9461,6 +9542,8 @@ void Create_field::init_for_tmp_table(en
((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
(maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
(is_unsigned ? 0 : FIELDFLAG_DECIMAL));
+ vcol_info= 0;
+ stored_in_db= TRUE;
}
@@ -9480,6 +9563,7 @@ void Create_field::init_for_tmp_table(en
@param fld_interval_list Interval list (if any)
@param fld_charset Field charset
@param fld_geom_type Field geometry type (if any)
+ @param fld_vcol_info Virtual column data
@retval
FALSE on success
@@ -9492,13 +9576,14 @@ bool Create_field::init(THD *thd, char *
uint fld_type_modifier, Item *fld_default_value,
Item *fld_on_update_value, LEX_STRING *fld_comment,
char *fld_change, List<String> *fld_interval_list,
- CHARSET_INFO *fld_charset, uint fld_geom_type)
+ CHARSET_INFO *fld_charset, uint fld_geom_type,
+ Virtual_column_info *fld_vcol_info)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("Create_field::init()");
-
+
field= 0;
field_name= fld_name;
def= fld_default_value;
@@ -9523,6 +9608,33 @@ bool Create_field::init(THD *thd, char *
interval_list.empty();
comment= *fld_comment;
+ vcol_info= fld_vcol_info;
+ stored_in_db= TRUE;
+
+ /* Initialize data for a computed field */
+ if ((uchar)fld_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ {
+ DBUG_ASSERT(vcol_info && vcol_info->expr_item);
+ stored_in_db= vcol_info->is_stored();
+ /*
+ Walk through the Item tree checking if all items are valid
+ to be part of the virtual column
+ */
+ if (vcol_info->expr_item->walk(&Item::check_vcol_func_processor, 0, NULL))
+ {
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ Make a field created for the real type.
+ Note that regular and computed fields differ from each other only by
+ Field::vcol_info. It is is always NULL for a column that is not
+ computed.
+ */
+ sql_type= fld_type= vcol_info->get_real_type();
+ }
+
/*
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
@@ -9813,7 +9925,7 @@ bool Create_field::init(THD *thd, char *
}
case MYSQL_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
- }
+ }
/* Remember the value of length */
char_length= length;
@@ -9912,7 +10024,6 @@ uint pack_length_to_packflag(uint type)
return 0; // This shouldn't happen
}
-
Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
@@ -9923,10 +10034,8 @@ Field *make_field(TABLE_SHARE *share, uc
TYPELIB *interval,
const char *field_name)
{
- uchar *bit_ptr;
- uchar bit_offset;
- LINT_INIT(bit_ptr);
- LINT_INIT(bit_offset);
+ uchar *UNINIT_VAR(bit_ptr);
+ uchar UNINIT_VAR(bit_offset);
if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
{
bit_ptr= null_pos;
@@ -10106,6 +10215,8 @@ Create_field::Create_field(Field *old_fi
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
+ vcol_info= old_field->vcol_info;
+ stored_in_db= old_field->stored_in_db;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
=== modified file 'sql/field.h'
--- a/sql/field.h 2009-09-07 20:50:10 +0000
+++ b/sql/field.h 2009-11-10 02:32:39 +0000
@@ -45,6 +45,80 @@ inline uint get_set_pack_length(int elem
return len > 4 ? 8 : len;
}
+/*
+ Virtual_column_info is the class to contain additional
+ characteristics that is specific for a virtual/computed
+ field such as:
+ - the defining expression that is evaluated to compute the value
+ of the field
+ - whether the field is to be stored in the database
+ - whether the field is used in a partitioning expression
+*/
+
+class Virtual_column_info: public Sql_alloc
+{
+private:
+ /*
+ The following data is only updated by the parser and read
+ when a Create_field object is created/initialized.
+ */
+ enum_field_types field_type; /* Real field type*/
+ /* Flag indicating that the field is physically stored in the database */
+ my_bool stored_in_db;
+ /* Flag indicating that the field used in a partitioning expression */
+ my_bool in_partitioning_expr;
+
+public:
+ /* The expression to compute the value of the virtual column */
+ Item *expr_item;
+ /* Text representation of the defining expression */
+ LEX_STRING expr_str;
+ /*
+ The list of items created when the defining expression for the virtual
+ column is being parsed and validated. These items are freed in the closefrm
+ function when the table containing this virtual column is removed from
+ the TABLE cache.
+ TODO. Items for all different virtual columns of a table should be put into
+ one list attached to the TABLE structure.
+ */
+ Item *item_free_list;
+
+ Virtual_column_info()
+ : field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
+ stored_in_db(FALSE), in_partitioning_expr(FALSE),
+ expr_item(NULL), item_free_list(NULL)
+ {
+ expr_str.str= NULL;
+ expr_str.length= 0;
+ };
+ ~Virtual_column_info() {}
+ enum_field_types get_real_type()
+ {
+ return field_type;
+ }
+ void set_field_type(enum_field_types fld_type)
+ {
+ /* Calling this function can only be done once. */
+ field_type= fld_type;
+ }
+ bool is_stored()
+ {
+ return stored_in_db;
+ }
+ void set_stored_in_db_flag(bool stored)
+ {
+ stored_in_db= stored;
+ }
+ bool is_in_partitioning_expr()
+ {
+ return in_partitioning_expr;
+ }
+ void mark_as_in_partitioning_expr()
+ {
+ in_partitioning_expr= TRUE;
+ }
+};
+
class Field
{
Field(const Item &); /* Prevent use of these */
@@ -57,7 +131,7 @@ public:
uchar *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
/*
- Note that you can use table->in_use as replacement for current_thd member
+ Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
*/
struct st_table *table; // Pointer for table
@@ -67,10 +141,10 @@ public:
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
key_map part_of_sortkey;
- /*
- We use three additional unireg types for TIMESTAMP to overcome limitation
- of current binary format of .frm file. We'd like to be able to support
- NOW() as default and on update value for such fields but unable to hold
+ /*
+ We use three additional unireg types for TIMESTAMP to overcome limitation
+ of current binary format of .frm file. We'd like to be able to support
+ NOW() as default and on update value for such fields but unable to hold
this info anywhere except unireg_check field. This issue will be resolved
in more clean way with transition to new text based .frm format.
See also comment for Field_timestamp::Field_timestamp().
@@ -103,6 +177,19 @@ public:
*/
bool is_created_from_null_item;
+ /*
+ This is additional data provided for any computed(virtual) field.
+ In particular it includes a pointer to the item by which this field
+ can be computed from other fields.
+ */
+ Virtual_column_info *vcol_info;
+ /*
+ Flag indicating that the field is physically stored in tables
+ rather than just computed from other fields.
+ As of now, FALSE can be set only for computed virtual columns.
+ */
+ bool stored_in_db;
+
Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg);
@@ -608,6 +695,10 @@ protected:
class Field_num :public Field {
public:
+ /**
+ The scale of the Field's value, i.e. the number of digits to the right
+ of the decimal point.
+ */
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
@@ -766,6 +857,11 @@ public:
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const char *field_name_arg, uint8 dec_arg,
bool unsigned_arg);
+ /*
+ Create a field to hold a decimal value from an item.
+ Truncates the precision and/or scale if necessary.
+ */
+ static Field_new_decimal *new_decimal_field(const Item *item);
enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
@@ -2044,6 +2140,20 @@ public:
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
+
+ /*
+ This is additinal data provided for any computed(virtual) field.
+ In particular it includes a pointer to the item by which this field
+ can be computed from other fields.
+ */
+ Virtual_column_info *vcol_info;
+ /*
+ Flag indicating that the field is physically stored in tables
+ rather than just computed from other fields.
+ As of now, FALSE can be set only for computed virtual columns.
+ */
+ bool stored_in_db;
+
Create_field() :after(0) {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
@@ -2060,7 +2170,8 @@ public:
char *decimals, uint type_modifier, Item *default_value,
Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
};
=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc 2009-10-19 17:14:48 +0000
+++ b/sql/filesort.cc 2009-11-12 04:31:28 +0000
@@ -565,6 +565,8 @@ static ha_rows find_all_keys(SORTPARAM *
{
if ((error= select->quick->get_next()))
break;
+ if (!error)
+ update_virtual_fields(sort_form);
file->position(sort_form->record[0]);
DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE););
}
@@ -582,6 +584,8 @@ static ha_rows find_all_keys(SORTPARAM *
else
{
error=file->ha_rnd_next(sort_form->record[0]);
+ if (!error)
+ update_virtual_fields(sort_form);
if (!flag)
{
my_store_ptr(ref_pos,ref_length,record); // Position to row
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2009-10-28 14:56:07 +0000
+++ b/sql/ha_partition.cc 2009-11-12 04:31:28 +0000
@@ -2436,7 +2436,7 @@ int ha_partition::open(const char *name,
DBUG_RETURN(1);
m_start_key.length= 0;
m_rec0= table->record[0];
- m_rec_length= table_share->reclength;
+ m_rec_length= table_share->stored_rec_length;
alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
alloc_len+= table_share->max_key_length;
if (!m_ordered_rec_buffer)
=== modified file 'sql/ha_partition.h'
--- a/sql/ha_partition.h 2009-02-19 09:01:25 +0000
+++ b/sql/ha_partition.h 2009-10-16 22:57:48 +0000
@@ -245,6 +245,7 @@ public:
DBUG_RETURN(0);
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes);
private:
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2009-10-19 17:14:48 +0000
+++ b/sql/handler.h 2009-11-12 04:31:28 +0000
@@ -1897,6 +1897,17 @@ public:
LEX_STRING *engine_name() { return hton_name(ht); }
+ /*
+ @brief
+ Check whether the engine supports virtual columns
+
+ @retval
+ FALSE if the engine does not support virtual columns
+ @retval
+ TRUE if the engine supports virtual columns
+ */
+ virtual bool check_if_supported_virtual_columns(void) { return FALSE;}
+
protected:
/* Service methods for use by storage engines. */
void ha_statistic_increment(ulong SSV::*offset) const;
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2009-09-15 10:46:35 +0000
+++ b/sql/item.cc 2009-11-10 02:32:39 +0000
@@ -433,17 +433,26 @@ Item::Item(THD *thd, Item *item):
}
+/**
+ Decimal precision of the item.
+
+ @remark The precision must not be capped as it can be used in conjunction
+ with Item::decimals to determine the size of the integer part when
+ constructing a decimal data type.
+
+ @see Item::decimal_int_part()
+ @see Item::decimals
+*/
+
uint Item::decimal_precision() const
{
+ uint precision= max_length;
Item_result restype= result_type();
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
- {
- uint prec=
- my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
- return min(prec, DECIMAL_MAX_PRECISION);
- }
- return min(max_length, DECIMAL_MAX_PRECISION);
+ precision= my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
+
+ return precision;
}
@@ -681,9 +690,24 @@ bool Item_field::register_field_in_read_
TABLE *table= (TABLE *) arg;
if (field->table == table || !table)
bitmap_set_bit(field->table->read_set, field->field_index);
+ if (field->vcol_info && field->vcol_info->expr_item)
+ return field->vcol_info->expr_item->walk(&Item::register_field_in_read_map,
+ 1, arg);
return 0;
}
+/*
+ @brief
+ Mark field in bitmap supplied as *arg
+*/
+
+bool Item_field::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap= (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ bitmap_set_bit(bitmap, field->field_index);
+ return 0;
+}
bool Item::check_cols(uint c)
{
@@ -1664,7 +1688,7 @@ bool agg_item_collations_for_comparison(
bool agg_item_set_converter(DTCollation &coll, const char *fname,
Item **args, uint nargs, uint flags, int item_sep)
{
- Item **arg, *safe_args[2];
+ Item **arg, *safe_args[2]= {NULL, NULL};
/*
For better error reporting: save the first and the second argument.
@@ -1673,8 +1697,6 @@ bool agg_item_set_converter(DTCollation
doesn't display each argument's characteristics.
- if nargs is 1, then this error cannot happen.
*/
- LINT_INIT(safe_args[0]);
- LINT_INIT(safe_args[1]);
if (nargs >=2 && nargs <= 3)
{
safe_args[0]= args[0];
@@ -3305,8 +3327,7 @@ Item_copy *Item_copy::create (Item *item
new Item_copy_uint (item) : new Item_copy_int (item);
case DECIMAL_RESULT:
return new Item_copy_decimal (item);
- case IMPOSSIBLE_RESULT:
- case ROW_RESULT:
+ default:
DBUG_ASSERT (0);
}
/* should not happen */
@@ -4453,6 +4474,21 @@ error:
return TRUE;
}
+/*
+ @brief
+ Mark virtual columns as used in a partitioning expression
+*/
+
+bool Item_field::vcol_in_partition_func_processor(uchar *int_arg)
+{
+ DBUG_ASSERT(fixed);
+ if (field->vcol_info)
+ {
+ field->vcol_info->mark_as_in_partitioning_expr();
+ }
+ return FALSE;
+}
+
Item *Item_field::safe_charset_converter(CHARSET_INFO *tocs)
{
@@ -4911,9 +4947,7 @@ Field *Item::tmp_table_field_from_field_
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
- field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0,
- Field::NONE, name, decimals, 0,
- unsigned_flag);
+ field= Field_new_decimal::new_decimal_field(this);
break;
case MYSQL_TYPE_TINY:
field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
@@ -5510,9 +5544,8 @@ bool Item_null::send(Protocol *protocol,
bool Item::send(Protocol *protocol, String *buffer)
{
- bool result;
+ bool UNINIT_VAR(result); // Will be set if null_value == 0
enum_field_types f_type;
- LINT_INIT(result); // Will be set if null_value == 0
switch ((f_type=field_type())) {
default:
@@ -6855,14 +6888,21 @@ void resolve_const_item(THD *thd, Item *
}
/**
- Return true if the value stored in the field is equal to the const
- item.
+ Compare the value stored in field, with the original item.
+
+ @param field field which the item is converted and stored in
+ @param item original item
+
+ @return Return an integer greater than, equal to, or less than 0 if
+ the value stored in the field is greater than, equal to,
+ or less than the original item
- We need to use this on the range optimizer because in some cases
- we can't store the value in the field without some precision/character loss.
+ @note We only use this on the range optimizer/partition pruning,
+ because in some cases we can't store the value in the field
+ without some precision/character loss.
*/
-bool field_is_equal_to_item(Field *field,Item *item)
+int stored_field_cmp_to_item(Field *field, Item *item)
{
Item_result res_type=item_cmp_type(field->result_type(),
@@ -6873,28 +6913,49 @@ bool field_is_equal_to_item(Field *field
char field_buff[MAX_FIELD_WIDTH];
String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result;
String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin);
+ enum_field_types field_type;
item_result=item->val_str(&item_tmp);
if (item->null_value)
- return 1; // This must be true
+ return 0;
field->val_str(&field_tmp);
- return !stringcmp(&field_tmp,item_result);
+
+ /*
+ If comparing DATE with DATETIME, append the time-part to the DATE.
+ So that the strings are equally formatted.
+ A DATE converted to string is 10 characters, and a DATETIME converted
+ to string is 19 characters.
+ */
+ field_type= field->type();
+ if (field_type == MYSQL_TYPE_DATE &&
+ item_result->length() == 19)
+ field_tmp.append(" 00:00:00");
+ else if (field_type == MYSQL_TYPE_DATETIME &&
+ item_result->length() == 10)
+ item_result->append(" 00:00:00");
+
+ return stringcmp(&field_tmp,item_result);
}
if (res_type == INT_RESULT)
- return 1; // Both where of type int
+ return 0; // Both are of type int
if (res_type == DECIMAL_RESULT)
{
my_decimal item_buf, *item_val,
field_buf, *field_val;
item_val= item->val_decimal(&item_buf);
if (item->null_value)
- return 1; // This must be true
+ return 0;
field_val= field->val_decimal(&field_buf);
- return !my_decimal_cmp(item_val, field_val);
+ return my_decimal_cmp(item_val, field_val);
}
double result= item->val_real();
if (item->null_value)
+ return 0;
+ double field_result= field->val_real();
+ if (field_result < result)
+ return -1;
+ else if (field_result > result)
return 1;
- return result == field->val_real();
+ return 0;
}
Item_cache* Item_cache::get_cache(const Item *item)
=== modified file 'sql/item.h'
--- a/sql/item.h 2009-09-15 10:46:35 +0000
+++ b/sql/item.h 2009-11-10 02:32:39 +0000
@@ -18,6 +18,24 @@
#pragma interface /* gcc class implementation */
#endif
+inline
+bool trace_unsupported_func(const char *where, const char *processor_name)
+{
+ char buff[64];
+ sprintf(buff, "%s::%s", where, processor_name);
+ DBUG_ENTER(buff);
+ sprintf(buff, "%s returns TRUE: unsupported function", processor_name);
+ DBUG_PRINT("info", (buff));
+ DBUG_RETURN(TRUE);
+}
+
+inline
+bool trace_unsupported_by_check_vcol_func_processor(const char *where)
+{
+ return trace_unsupported_func(where, "check_vcol_func_processor");
+}
+
+
class Protocol;
struct TABLE_LIST;
void item_init(void); /* Init item functions */
@@ -397,13 +415,20 @@ public:
from INT_RESULT, may be NULL, or are unsigned.
It will be possible to address this issue once the related partitioning bugs
(BUG#16002, BUG#15447, BUG#13436) are fixed.
+
+ The NOT_NULL enums are used in TO_DAYS, since TO_DAYS('2001-00-00') returns
+ NULL which puts those rows into the NULL partition, but
+ '2000-12-31' < '2001-00-00' < '2001-01-01'. So special handling is needed
+ for this (see Bug#20577).
*/
typedef enum monotonicity_info
{
NON_MONOTONIC, /* none of the below holds */
MONOTONIC_INCREASING, /* F() is unary and (x < y) => (F(x) <= F(y)) */
- MONOTONIC_STRICT_INCREASING /* F() is unary and (x < y) => (F(x) < F(y)) */
+ MONOTONIC_INCREASING_NOT_NULL, /* But only for valid/real x and y */
+ MONOTONIC_STRICT_INCREASING,/* F() is unary and (x < y) => (F(x) < F(y)) */
+ MONOTONIC_STRICT_INCREASING_NOT_NULL /* But only for valid/real x and y */
} enum_monotonicity_info;
/*************************************************************************/
@@ -576,8 +601,8 @@ public:
left_endp FALSE <=> The interval is "x < const" or "x <= const"
TRUE <=> The interval is "x > const" or "x >= const"
- incl_endp IN TRUE <=> the comparison is '<' or '>'
- FALSE <=> the comparison is '<=' or '>='
+ incl_endp IN FALSE <=> the comparison is '<' or '>'
+ TRUE <=> the comparison is '<=' or '>='
OUT The same but for the "F(x) $CMP$ F(const)" comparison
DESCRIPTION
@@ -759,9 +784,10 @@ public:
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
+ /** Returns the uncapped decimal precision of this item. */
virtual uint decimal_precision() const;
inline int decimal_int_part() const
- { return my_decimal_int_part(decimal_precision(), decimals); }
+ { return decimal_precision() - decimals; }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -895,6 +921,11 @@ public:
virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; }
virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; }
/*
+ The next function differs from the previous one that a bitmap to be updated
+ is passed as uchar *arg.
+ */
+ virtual bool register_field_in_bitmap(uchar *arg) { return 0; }
+ /*
Check if a partition function is allowed
SYNOPSIS
check_partition_func_processor()
@@ -946,11 +977,43 @@ public:
fields.
*/
virtual bool check_partition_func_processor(uchar *bool_arg) { return TRUE;}
+ /*
+ @brief
+ Processor used to mark virtual columns used in partitioning expression
+
+ @param
+ arg always ignored
+
+ @retval
+ FALSE always
+ */
+ virtual bool vcol_in_partition_func_processor(uchar *arg)
+ {
+ return FALSE;
+ }
+
virtual bool subst_argument_checker(uchar **arg)
- {
+ {
if (*arg)
- *arg= NULL;
- return TRUE;
+ *arg= NULL;
+ return TRUE;
+ }
+ /*
+ @brief
+ Processor used to check acceptability of an item in the defining
+ expression for a virtual column
+
+ @param
+ arg always ignored
+
+ @retval
+ FALSE the item is accepted in the definition of a virtual column
+ @retval
+ TRUE otherwise
+ */
+ virtual bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(full_name());
}
virtual Item *equal_fields_propagator(uchar * arg) { return this; }
@@ -1327,6 +1390,10 @@ public:
{
return value_item->send(protocol, str);
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("name_const");
+ }
};
bool agg_item_collations(DTCollation &c, const char *name,
@@ -1346,6 +1413,7 @@ public:
virtual Item_num *neg()= 0;
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
#define NO_CACHED_FIELD_INDEX ((uint)(-1))
@@ -1505,7 +1573,10 @@ public:
bool collect_item_field_processor(uchar * arg);
bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool vcol_in_partition_func_processor(uchar *bool_arg);
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
bool enumerate_field_refs_processor(uchar *arg);
void cleanup();
bool result_as_longlong()
@@ -1566,6 +1637,7 @@ public:
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
class Item_null_result :public Item_null
@@ -1579,7 +1651,11 @@ public:
save_in_field(result_field, no_conversions);
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
-};
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(full_name());
+ }
+};
/* Item represents one placeholder ('?') of prepared statement */
@@ -1720,6 +1796,7 @@ public:
/** Item is a argument to a limit clause. */
bool limit_clause_param;
void set_param_type_and_swap_value(Item_param *from);
+
};
@@ -1755,6 +1832,7 @@ public:
{ return (uint)(max_length - test(value < 0)); }
bool eq(const Item *, bool binary_cmp) const;
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar arg) { return FALSE;}
};
@@ -1773,6 +1851,7 @@ public:
Item_num *neg ();
uint decimal_precision() const { return max_length; }
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
@@ -1814,6 +1893,7 @@ public:
bool eq(const Item *, bool binary_cmp) const;
void set_decimal_value(my_decimal *value_par);
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
@@ -1971,6 +2051,7 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
/**
Return TRUE if character-set-introducer was explicitly specified in the
@@ -2024,7 +2105,7 @@ double_from_string_with_check (CHARSET_I
class Item_static_string_func :public Item_string
{
const char *func_name;
-public:
+ public:
Item_static_string_func(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs,
Derivation dv= DERIVATION_COERCIBLE)
@@ -2038,6 +2119,10 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name);
+ }
};
@@ -2049,6 +2134,10 @@ public:
CHARSET_INFO *cs= NULL):
Item_string(name_arg, length, cs)
{}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("safe_string");
+ }
};
@@ -2128,6 +2217,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
@@ -2158,6 +2248,7 @@ public:
save_in_field(result_field, no_conversions);
}
void cleanup();
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
@@ -2287,7 +2378,10 @@ public:
if (ref && result_type() == ROW_RESULT)
(*ref)->bring_value();
}
-
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("ref");
+ }
};
@@ -2563,6 +2657,10 @@ public:
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
bool is_null() { return null_value; }
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("copy");
+ }
/*
Override the methods below as pure virtual to make sure all the
@@ -2805,6 +2903,10 @@ public:
return arg->walk(processor, walk_subquery, args) ||
(this->*processor)(args);
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("values");
+ }
};
@@ -2901,6 +3003,10 @@ private:
BEFORE INSERT of BEFORE UPDATE trigger.
*/
bool read_only;
+ virtual bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("trigger");
+ }
};
@@ -2960,6 +3066,11 @@ public:
{
return this == item;
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("cache");
+ }
+
};
@@ -3152,4 +3263,4 @@ void mark_select_range_as_dependent(THD
extern Cached_item *new_Cached_item(THD *thd, Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item);
-extern bool field_is_equal_to_item(Field *field,Item *item);
+extern int stored_field_cmp_to_item(Field *field, Item *item);
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2009-09-15 10:46:35 +0000
+++ b/sql/item_cmpfunc.cc 2009-10-15 21:38:29 +0000
@@ -395,11 +395,10 @@ static bool convert_constant_item(THD *t
ulong orig_sql_mode= thd->variables.sql_mode;
enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields;
my_bitmap_map *old_maps[2];
- ulonglong orig_field_val; /* original field value if valid */
+ ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */
LINT_INIT(old_maps[0]);
LINT_INIT(old_maps[1]);
- LINT_INIT(orig_field_val);
if (table)
dbug_tmp_use_all_columns(table, old_maps,
@@ -2182,7 +2181,7 @@ uint Item_func_ifnull::decimal_precision
int arg1_int_part= args[1]->decimal_int_part();
int max_int_part= max(arg0_int_part, arg1_int_part);
int precision= max_int_part + decimals;
- return min(precision, DECIMAL_MAX_PRECISION);
+ return precision;
}
@@ -2366,7 +2365,7 @@ uint Item_func_if::decimal_precision() c
int arg1_prec= args[1]->decimal_int_part();
int arg2_prec= args[2]->decimal_int_part();
int precision=max(arg1_prec,arg2_prec) + decimals;
- return min(precision, DECIMAL_MAX_PRECISION);
+ return precision;
}
@@ -2783,7 +2782,7 @@ uint Item_func_case::decimal_precision()
if (else_expr_num != -1)
set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
- return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+ return max_int_part + decimals;
}
=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc 2009-04-25 10:05:32 +0000
+++ b/sql/item_create.cc 2009-10-15 21:38:29 +0000
@@ -5032,10 +5032,9 @@ create_func_cast(THD *thd, Item *a, Cast
const char *c_len, const char *c_dec,
CHARSET_INFO *cs)
{
- Item *res;
+ Item *UNINIT_VAR(res);
ulong len;
uint dec;
- LINT_INIT(res);
switch (cast_type) {
case ITEM_CAST_BINARY:
=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc 2009-09-07 20:50:10 +0000
+++ b/sql/item_func.cc 2009-11-10 02:32:39 +0000
@@ -451,45 +451,8 @@ Field *Item_func::tmp_table_field(TABLE
case STRING_RESULT:
return make_string_field(table);
case DECIMAL_RESULT:
- {
- uint8 dec= decimals;
- uint8 intg= decimal_precision() - dec;
- uint32 len= max_length;
-
- /*
- Trying to put too many digits overall in a DECIMAL(prec,dec)
- will always throw a warning. We must limit dec to
- DECIMAL_MAX_SCALE however to prevent an assert() later.
- */
-
- if (dec > 0)
- {
- int overflow;
-
- dec= min(dec, DECIMAL_MAX_SCALE);
-
- /*
- If the value still overflows the field with the corrected dec,
- we'll throw out decimals rather than integers. This is still
- bad and of course throws a truncation warning.
- */
-
- const int required_length=
- my_decimal_precision_to_length(intg + dec, dec,
- unsigned_flag);
-
- overflow= required_length - len;
-
- if (overflow > 0)
- dec= max(0, dec - overflow); // too long, discard fract
- else
- /* Corrected value fits. */
- len= required_length;
- }
-
- field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag);
+ field= Field_new_decimal::new_decimal_field(this);
break;
- }
case ROW_RESULT:
default:
// This case should never be chosen
@@ -2304,9 +2267,8 @@ void Item_func_min_max::fix_length_and_d
uint Item_func_min_max::cmp_datetimes(ulonglong *value)
{
- longlong min_max;
+ longlong UNINIT_VAR(min_max);
uint min_max_idx= 0;
- LINT_INIT(min_max);
for (uint i=0; i < arg_count ; i++)
{
@@ -2371,8 +2333,7 @@ String *Item_func_min_max::val_str(Strin
}
case STRING_RESULT:
{
- String *res;
- LINT_INIT(res);
+ String *UNINIT_VAR(res);
for (uint i=0; i < arg_count ; i++)
{
if (i == 0)
@@ -2461,8 +2422,7 @@ longlong Item_func_min_max::val_int()
my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
{
DBUG_ASSERT(fixed == 1);
- my_decimal tmp_buf, *tmp, *res;
- LINT_INIT(res);
+ my_decimal tmp_buf, *tmp, *UNINIT_VAR(res);
if (compare_as_dates)
{
@@ -3940,10 +3900,30 @@ bool Item_func_set_user_var::register_fi
TABLE *table= (TABLE *) arg;
if (result_field->table == table || !table)
bitmap_set_bit(result_field->table->read_set, result_field->field_index);
+ if (result_field->vcol_info)
+ return result_field->vcol_info->
+ expr_item->walk(&Item::register_field_in_read_map, 1, arg);
}
return 0;
}
+/*
+ Mark field in bitmap supplied as *arg
+
+*/
+
+bool Item_func_set_user_var::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap = (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ if (result_field)
+ {
+ if (!bitmap)
+ return 1;
+ bitmap_set_bit(bitmap, result_field->field_index);
+ }
+ return 0;
+}
/**
Set value to user variable.
@@ -4784,6 +4764,19 @@ void Item_func_get_user_var::fix_length_
}
+uint Item_func_get_user_var::decimal_precision() const
+{
+ uint precision= max_length;
+ Item_result restype= result_type();
+
+ /* Default to maximum as the precision is unknown a priori. */
+ if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
+ precision= DECIMAL_MAX_PRECISION;
+
+ return precision;
+}
+
+
bool Item_func_get_user_var::const_item() const
{
return (!var_entry || current_thd->query_id != var_entry->update_query_id);
@@ -5447,8 +5440,7 @@ void Item_func_match::init_search(bool n
bool Item_func_match::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- Item *item;
- LINT_INIT(item); // Safe as arg_count is > 1
+ Item *UNINIT_VAR(item); // Safe as arg_count is > 1
maybe_null=1;
join_key=0;
=== modified file 'sql/item_func.h'
--- a/sql/item_func.h 2009-09-07 20:50:10 +0000
+++ b/sql/item_func.h 2009-11-10 02:32:39 +0000
@@ -339,6 +339,7 @@ public:
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};
@@ -399,6 +400,7 @@ public:
Item_func_additive_op(Item *a,Item *b) :Item_num_op(a,b) {}
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -434,6 +436,7 @@ public:
my_decimal *decimal_op(my_decimal *);
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -466,6 +469,7 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -480,6 +484,7 @@ public:
void result_precision();
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -496,6 +501,7 @@ public:
void fix_num_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -509,6 +515,7 @@ public:
const char *func_name() const { return "abs"; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
// A class to handle logarithmic and trigonometric functions
@@ -664,6 +671,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -676,6 +684,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
/* This handles round and truncate */
@@ -707,6 +716,10 @@ public:
void update_used_tables();
bool fix_fields(THD *thd, Item **ref);
void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
private:
void seed_random (Item * val);
};
@@ -989,6 +1002,10 @@ public:
max_length= args[0]->max_length;
}
bool fix_fields(THD *thd, Item **ref);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1002,6 +1019,10 @@ public:
const char *func_name() const { return "benchmark"; }
void fix_length_and_dec() { max_length=1; maybe_null=0; }
virtual void print(String *str, enum_query_type query_type);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1017,6 +1038,10 @@ public:
used_tables_cache|= RAND_TABLE_BIT;
}
longlong val_int();
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1266,6 +1291,10 @@ class Item_func_get_lock :public Item_in
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
class Item_func_release_lock :public Item_int_func
@@ -1276,6 +1305,10 @@ public:
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
/* replication functions */
@@ -1289,6 +1322,10 @@ public:
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1360,6 +1397,7 @@ public:
}
void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); }
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
void cleanup();
};
@@ -1393,6 +1431,7 @@ public:
table_map used_tables() const
{ return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
+ uint decimal_precision() const;
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
@@ -1534,6 +1573,11 @@ public:
bool fix_index();
void init_search(bool no_order);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /* TODO: consider adding in support for the MATCH-based virtual columns */
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1553,6 +1597,17 @@ public:
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+#if 0
+ DBUG_ENTER("Item_func_is_free_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+#else
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+#endif
+ }
};
class Item_func_is_used_lock :public Item_int_func
@@ -1563,6 +1618,10 @@ public:
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
/* For type casts */
@@ -1582,6 +1641,11 @@ public:
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1690,6 +1754,10 @@ public:
{
return sp_result_field;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1700,6 +1768,10 @@ public:
longlong val_int();
const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1714,5 +1786,9 @@ public:
void fix_length_and_dec()
{ max_length= 21; unsigned_flag=1; }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
=== modified file 'sql/item_row.h'
--- a/sql/item_row.h 2008-02-22 10:30:33 +0000
+++ b/sql/item_row.h 2009-10-16 22:57:48 +0000
@@ -76,4 +76,5 @@ public:
bool check_cols(uint c);
bool null_inside() { return with_null; };
void bring_value();
-};
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE; }
+ };
=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h 2009-09-07 20:50:10 +0000
+++ b/sql/item_strfunc.h 2009-10-16 22:57:48 +0000
@@ -344,6 +344,10 @@ public:
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
const char *func_name() const { return "encrypt"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
#include "sql_crypt.h"
@@ -381,6 +385,11 @@ public:
call
*/
virtual const char *fully_qualified_func_name() const = 0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(
+ fully_qualified_func_name());
+ }
};
@@ -644,6 +653,10 @@ public:
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -840,5 +853,9 @@ public:
}
const char *func_name() const{ return "uuid"; }
String *val_str(String *);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h 2009-08-31 20:02:09 +0000
+++ b/sql/item_subselect.h 2009-10-16 22:57:48 +0000
@@ -136,6 +136,10 @@ public:
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
bool mark_as_eliminated_processor(uchar *arg);
bool enumerate_field_refs_processor(uchar *arg);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("subselect");
+ }
/**
Get the SELECT_LEX structure associated with this Item.
=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc 2009-09-15 10:46:35 +0000
+++ b/sql/item_sum.cc 2009-10-15 21:38:29 +0000
@@ -517,8 +517,7 @@ Field *Item_sum::create_tmp_field(bool g
name, table->s, collation.collation);
break;
case DECIMAL_RESULT:
- field= new Field_new_decimal(max_length, maybe_null, name,
- decimals, unsigned_flag);
+ field= Field_new_decimal::new_decimal_field(this);
break;
case ROW_RESULT:
default:
=== modified file 'sql/item_sum.h'
--- a/sql/item_sum.h 2009-09-15 10:46:35 +0000
+++ b/sql/item_sum.h 2009-10-16 22:57:48 +0000
@@ -399,6 +399,10 @@ public:
Item *get_arg(int i) { return args[i]; }
Item *set_arg(int i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -679,6 +683,10 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("avg_field");
+ }
};
@@ -747,6 +755,10 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("var_field");
+ }
};
=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc 2009-09-07 20:50:10 +0000
+++ b/sql/item_timefunc.cc 2009-10-15 21:38:29 +0000
@@ -961,9 +961,9 @@ enum_monotonicity_info Item_func_to_days
if (args[0]->type() == Item::FIELD_ITEM)
{
if (args[0]->field_type() == MYSQL_TYPE_DATE)
- return MONOTONIC_STRICT_INCREASING;
+ return MONOTONIC_STRICT_INCREASING_NOT_NULL;
if (args[0]->field_type() == MYSQL_TYPE_DATETIME)
- return MONOTONIC_INCREASING;
+ return MONOTONIC_INCREASING_NOT_NULL;
}
return NON_MONOTONIC;
}
@@ -974,12 +974,27 @@ longlong Item_func_to_days::val_int_endp
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
longlong res;
- if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
+ int dummy; /* unused */
+ if (get_arg0_date(<ime, TIME_FUZZY_DATE))
{
/* got NULL, leave the incl_endp intact */
return LONGLONG_MIN;
}
res=(longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
+ /* 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);
+ if (null_value)
+ {
+ /*
+ Even if the evaluation return NULL, the calc_daynr is useful for pruning
+ */
+ if (args[0]->field_type() != MYSQL_TYPE_DATE)
+ *incl_endp= TRUE;
+ return res;
+ }
if (args[0]->field_type() == MYSQL_TYPE_DATE)
{
@@ -992,15 +1007,19 @@ longlong Item_func_to_days::val_int_endp
point to day bound ("strictly less" comparison stays intact):
col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
+ col > '2007-09-15 23:59:59' -> TO_DAYS(col) > TO_DAYS('2007-09-15')
which is different from the general case ("strictly less" changes to
"less or equal"):
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))
- ; /* do nothing */
+ if ((!left_endp && !(ltime.hour || ltime.minute || ltime.second ||
+ ltime.second_part)) ||
+ (left_endp && ltime.hour == 23 && ltime.minute == 59 &&
+ ltime.second == 59))
+ /* do nothing */
+ ;
else
*incl_endp= TRUE;
return res;
=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h 2009-02-07 15:50:31 +0000
+++ b/sql/item_timefunc.h 2009-10-16 22:57:48 +0000
@@ -70,6 +70,7 @@ public:
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -86,6 +87,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -111,6 +113,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -124,6 +127,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE;}
};
@@ -140,6 +144,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -156,6 +161,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -172,6 +178,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -188,6 +195,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -204,6 +212,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -234,6 +243,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -252,6 +262,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -282,6 +293,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
class Item_func_dayname :public Item_func_weekday
@@ -294,6 +306,7 @@ class Item_func_dayname :public Item_fun
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -310,6 +323,14 @@ public:
decimals=0;
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /*
+ TODO: Allow UNIX_TIMESTAMP called with an argument to be a part
+ of the expression for a virtual column
+ */
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -325,6 +346,7 @@ public:
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -445,6 +467,10 @@ public:
*/
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
bool result_as_longlong() { return TRUE; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -481,6 +507,10 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -521,6 +551,10 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -578,6 +612,7 @@ public:
const char *func_name() const { return "from_days"; }
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -705,6 +740,7 @@ class Item_extract :public Item_int_func
bool eq(const Item *item, bool binary_cmp) const;
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -953,6 +989,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
=== modified file 'sql/item_xmlfunc.cc'
--- a/sql/item_xmlfunc.cc 2009-09-07 20:50:10 +0000
+++ b/sql/item_xmlfunc.cc 2009-10-16 22:57:48 +0000
@@ -220,6 +220,11 @@ public:
collation.collation= pxml->charset();
}
const char *func_name() const { return "nodeset"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
+
};
@@ -526,6 +531,10 @@ public:
enum Type type() const { return XPATH_NODESET_CMP; };
const char *func_name() const { return "xpath_nodeset_to_const_comparator"; }
bool is_bool_func() { return 1; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
longlong val_int()
{
=== modified file 'sql/item_xmlfunc.h'
--- a/sql/item_xmlfunc.h 2007-11-21 12:00:09 +0000
+++ b/sql/item_xmlfunc.h 2009-10-16 22:57:48 +0000
@@ -40,6 +40,10 @@ public:
}
void fix_length_and_dec();
String *parse_xml(String *raw_xml, String *parsed_xml_buf);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
=== modified file 'sql/lex.h'
--- a/sql/lex.h 2009-10-19 17:14:48 +0000
+++ b/sql/lex.h 2009-11-12 04:31:28 +0000
@@ -62,6 +62,7 @@ static SYMBOL symbols[] = {
{ "ALL", SYM(ALL)},
{ "ALGORITHM", SYM(ALGORITHM_SYM)},
{ "ALTER", SYM(ALTER)},
+ { "ALWAYS", SYM(ALWAYS_SYM)},
{ "ANALYZE", SYM(ANALYZE_SYM)},
{ "AND", SYM(AND_SYM)},
{ "ANY", SYM(ANY_SYM)},
@@ -221,6 +222,7 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL)},
{ "FULLTEXT", SYM(FULLTEXT_SYM)},
{ "FUNCTION", SYM(FUNCTION_SYM)},
+ { "GENERATED", SYM(GENERATED_SYM)},
{ "GEOMETRY", SYM(GEOMETRY_SYM)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)},
@@ -387,14 +389,16 @@ static SYMBOL symbols[] = {
{ "OUTFILE", SYM(OUTFILE)},
{ "OWNER", SYM(OWNER_SYM)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
- { "PARSER", SYM(PARSER_SYM)},
{ "PAGE", SYM(PAGE_SYM)},
{ "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)},
+ { "PARSER", SYM(PARSER_SYM)},
+ { "PARSE_VCOL_EXPR", SYM(PARSE_VCOL_EXPR_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
{ "PARTITION", SYM(PARTITION_SYM)},
{ "PARTITIONING", SYM(PARTITIONING_SYM)},
{ "PARTITIONS", SYM(PARTITIONS_SYM)},
{ "PASSWORD", SYM(PASSWORD)},
+ { "PERSISTENT", SYM(PERSISTENT_SYM)},
{ "PHASE", SYM(PHASE_SYM)},
{ "PLUGIN", SYM(PLUGIN_SYM)},
{ "PLUGINS", SYM(PLUGINS_SYM)},
@@ -586,13 +590,14 @@ static SYMBOL symbols[] = {
{ "VARCHARACTER", SYM(VARCHAR)},
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
+ { "VIEW", SYM(VIEW_SYM)},
+ { "VIRTUAL", SYM(VIRTUAL_SYM)},
{ "WAIT", SYM(WAIT_SYM)},
{ "WARNINGS", SYM(WARNINGS)},
{ "WEEK", SYM(WEEK_SYM)},
{ "WHEN", SYM(WHEN_SYM)},
{ "WHERE", SYM(WHERE)},
{ "WHILE", SYM(WHILE_SYM)},
- { "VIEW", SYM(VIEW_SYM)},
{ "WITH", SYM(WITH)},
{ "WORK", SYM(WORK_SYM)},
{ "WRAPPER", SYM(WRAPPER_SYM)},
=== modified file 'sql/lock.cc'
--- a/sql/lock.cc 2009-09-07 20:50:10 +0000
+++ b/sql/lock.cc 2009-10-15 21:38:29 +0000
@@ -1472,11 +1472,10 @@ void unlock_global_read_lock(THD *thd)
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
bool is_not_commit)
{
- const char *old_message;
+ const char *UNINIT_VAR(old_message);
bool result= 0, need_exit_cond;
DBUG_ENTER("wait_if_global_read_lock");
- LINT_INIT(old_message);
/*
Assert that we do not own LOCK_open. If we would own it, other
threads could not close their tables. This would make a pretty
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2009-10-28 14:56:07 +0000
+++ b/sql/log.cc 2009-11-12 04:31:28 +0000
@@ -1297,6 +1297,25 @@ int LOGGER::set_handlers(uint error_log_
return 0;
}
+/**
+ This function checks if a transactional talbe was updated by the
+ current statement.
+
+ @param thd The client thread that executed the current statement.
+ @return
+ @c true if a transactional table was updated, @false otherwise.
+*/
+static bool stmt_has_updated_trans_table(THD *thd)
+{
+ Ha_trx_info *ha_info;
+
+ for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next())
+ {
+ if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton)
+ return (TRUE);
+ }
+ return (FALSE);
+}
/*
Save position of binary log transaction cache.
@@ -4129,7 +4148,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
IO_CACHE *trans_log= &trx_data->trans_log;
my_off_t trans_log_pos= my_b_tell(trans_log);
- if (event_info->get_cache_stmt() || trans_log_pos != 0)
+ if (event_info->get_cache_stmt() || trans_log_pos != 0 ||
+ stmt_has_updated_trans_table(thd))
{
DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu",
event_info->get_cache_stmt(),
@@ -4894,7 +4914,8 @@ bool flush_error_log()
my_rename(log_error_file,err_renamed,MYF(0));
if (freopen(log_error_file,"a+",stdout))
{
- freopen(log_error_file,"a+",stderr);
+ FILE *reopen;
+ reopen= freopen(log_error_file,"a+",stderr);
setbuf(stderr, NULL);
}
else
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2009-11-04 22:41:58 +0000
+++ b/sql/log_event.cc 2009-11-12 04:31:28 +0000
@@ -2948,6 +2948,8 @@ int Query_log_event::do_apply_event(Rela
{
LEX_STRING new_db;
int expected_error,actual_error= 0;
+ HA_CREATE_INFO db_options;
+
/*
Colleagues: please never free(thd->catalog) in MySQL. This would
lead to bugs as here thd->catalog is a part of an alloced block,
@@ -2959,6 +2961,13 @@ int Query_log_event::do_apply_event(Rela
new_db.length= db_len;
new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
thd->set_db(new_db.str, new_db.length); /* allocates a copy of 'db' */
+
+ /*
+ Setting the character set and collation of the current database thd->db.
+ */
+ load_db_opt_by_name(thd, thd->db, &db_options);
+ if (db_options.default_table_charset)
+ thd->db_charset= db_options.default_table_charset;
thd->variables.auto_increment_increment= auto_increment_increment;
thd->variables.auto_increment_offset= auto_increment_offset;
@@ -3159,7 +3168,7 @@ compare_errors:
/*
If we expected a non-zero error code, and we don't get the same error
- code, and none of them should be ignored.
+ code, and it should be ignored or is related to a concurrency issue.
*/
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
@@ -3182,7 +3191,8 @@ Default database: '%s'. Query: '%s'",
thd->is_slave_error= 1;
}
/*
- If we get the same error code as expected, or they should be ignored.
+ If we get the same error code as expected and it is not a concurrency
+ issue, or should be ignored.
*/
else if ((expected_error == actual_error &&
!concurrency_error_code(expected_error)) ||
@@ -3191,8 +3201,25 @@ Default database: '%s'. Query: '%s'",
DBUG_PRINT("info",("error ignored"));
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
thd->killed= THD::NOT_KILLED;
+ /*
+ When an error is expected and matches the actual error the
+ slave does not report any error and by consequence changes
+ on transactional tables are not rolled back in the function
+ close_thread_tables(). For that reason, we explicitly roll
+ them back here.
+ */
+ if (expected_error && expected_error == actual_error)
+ ha_autocommit_or_rollback(thd, TRUE);
}
/*
+ If we expected a non-zero error code and get nothing and, it is a concurrency
+ issue or should be ignored.
+ */
+ else if (expected_error && !actual_error &&
+ (concurrency_error_code(expected_error) ||
+ ignored_error_code(expected_error)))
+ ha_autocommit_or_rollback(thd, TRUE);
+ /*
Other cases: mostly we expected no error and get one.
*/
else if (thd->is_slave_error || thd->is_fatal_error)
=== modified file 'sql/my_decimal.h'
--- a/sql/my_decimal.h 2009-09-07 20:50:10 +0000
+++ b/sql/my_decimal.h 2009-10-15 21:38:29 +0000
@@ -48,10 +48,12 @@ C_MODE_END
digits * number of decimal digits in one our big digit - number of decimal
digits in one our big digit decreased by 1 (because we always put decimal
point on the border of our big digits))
+
+ This value is 65 due to historical reasons partly due to it being used
+ as the maximum allowed precision and not the actual maximum precision.
*/
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
#define DECIMAL_MAX_SCALE 30
-#define DECIMAL_NOT_SPECIFIED 31
/**
maximum length of string representation (number of maximum decimal
@@ -75,12 +77,6 @@ inline uint my_decimal_size(uint precisi
}
-inline int my_decimal_int_part(uint precision, uint decimals)
-{
- return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
-}
-
-
/**
my_decimal class limits 'decimal_t' type to what we need in MySQL.
@@ -184,7 +180,7 @@ inline uint my_decimal_length_to_precisi
}
inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
- uint8 scale,
+ uint scale,
bool unsigned_flag)
{
/*
@@ -196,7 +192,7 @@ inline uint32 my_decimal_precision_to_le
(unsigned_flag || !precision ? 0 : 1));
}
-inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
+inline uint32 my_decimal_precision_to_length(uint precision, uint scale,
bool unsigned_flag)
{
/*
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2009-11-04 22:41:58 +0000
+++ b/sql/mysql_priv.h 2009-11-12 04:31:28 +0000
@@ -1362,6 +1362,7 @@ find_field_in_table(THD *thd, TABLE *tab
bool allow_rowid, uint *cached_field_index_ptr);
Field *
find_field_in_table_sef(TABLE *table, const char *name);
+int update_virtual_fields(TABLE *table, bool ignore_stored= FALSE);
#endif /* MYSQL_SERVER */
@@ -1482,14 +1483,16 @@ bool add_field_to_list(THD *thd, LEX_STR
LEX_STRING *comment,
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
bool push_new_name_resolution_context(THD *thd,
@@ -2328,7 +2331,8 @@ enum enum_explain_filename_mode
{
EXPLAIN_ALL_VERBOSE= 0,
EXPLAIN_PARTITIONS_VERBOSE,
- EXPLAIN_PARTITIONS_AS_COMMENT
+ EXPLAIN_PARTITIONS_AS_COMMENT,
+ EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING
};
uint explain_filename(const char *from, char *to, uint to_length,
enum_explain_filename_mode explain_mode);
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2009-11-04 22:41:58 +0000
+++ b/sql/mysqld.cc 2009-11-12 04:31:28 +0000
@@ -1903,7 +1903,9 @@ void close_connection(THD *thd, uint err
extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
{
DBUG_ENTER("end_mysqld_signal");
- kill_mysql(); // Take down mysqld nicely
+ /* Don't call kill_mysql() if signal thread is not running */
+ if (signal_thread_in_use)
+ kill_mysql(); // Take down mysqld nicely
DBUG_VOID_RETURN; /* purecov: deadcode */
}
@@ -8124,7 +8126,7 @@ mysqld_get_one_option(int optid,
switch(optid) {
#ifndef DBUG_OFF
case OPT_DEBUG_FLUSH:
- argument= IF_WIN(default_dbug_option, (char*) "d:t:i:O,/tmp/mysqld.trace");
+ argument= IF_WIN((char*) default_dbug_option, (char*) "d:t:i:O,/tmp/mysqld.trace");
/* fall through */
case '#':
if (!argument)
=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc 2009-10-19 17:14:48 +0000
+++ b/sql/opt_range.cc 2009-11-12 04:31:28 +0000
@@ -2243,7 +2243,7 @@ int SQL_SELECT::test_quick_select(THD *t
KEY *key_info;
PARAM param;
- if (check_stack_overrun(thd, 2*STACK_MIN_SIZE, buff))
+ if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff))
DBUG_RETURN(0); // Fatal error flag is set
/* set up parameter that is passed to all functions */
@@ -4839,11 +4839,10 @@ static TRP_RANGE *get_key_scans_params(P
{
int idx;
SEL_ARG **key,**end, **key_to_read= NULL;
- ha_rows best_records;
+ ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */
TRP_RANGE* read_plan= NULL;
bool pk_is_clustered= param->table->file->primary_key_is_clustered();
DBUG_ENTER("get_key_scans_params");
- LINT_INIT(best_records); /* protected by key_to_read */
/*
Note that there may be trees that have type SEL_TREE::KEY but contain no
key reads at all, e.g. tree for expression "key1 is not null" where key1
@@ -5827,6 +5826,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND
{
tree= new (alloc) SEL_ARG(field, 0, 0);
tree->type= SEL_ARG::IMPOSSIBLE;
+ field->table->in_use->variables.sql_mode= orig_sql_mode;
goto end;
}
else
@@ -5856,11 +5856,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND
but we'll need to convert '>' to '>=' and '<' to '<='. This will
be done together with other types at the end of this function
- (grep for field_is_equal_to_item)
+ (grep for stored_field_cmp_to_item)
*/
}
else
+ {
+ field->table->in_use->variables.sql_mode= orig_sql_mode;
goto end;
+ }
}
}
@@ -5931,7 +5934,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND
switch (type) {
case Item_func::LT_FUNC:
- if (field_is_equal_to_item(field,value))
+ if (stored_field_cmp_to_item(field,value) == 0)
tree->max_flag=NEAR_MAX;
/* fall through */
case Item_func::LE_FUNC:
@@ -5945,11 +5948,16 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND
break;
case Item_func::GT_FUNC:
/* Don't use open ranges for partial key_segments */
- if (field_is_equal_to_item(field,value) &&
- !(key_part->flag & HA_PART_KEY_SEG))
+ if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
+ (stored_field_cmp_to_item(field, value) <= 0))
tree->min_flag=NEAR_MIN;
- /* fall through */
+ tree->max_flag= NO_MAX_RANGE;
+ break;
case Item_func::GE_FUNC:
+ /* Don't use open ranges for partial key_segments */
+ if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
+ (stored_field_cmp_to_item(field,value) < 0))
+ tree->min_flag= NEAR_MIN;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_EQUALS_FUNC:
@@ -6440,13 +6448,6 @@ key_and(RANGE_OPT_PARAM *param, SEL_ARG
return 0; // Can't optimize this
}
- if ((key1->min_flag | key2->min_flag) & GEOM_FLAG)
- {
- key1->free_tree();
- key2->free_tree();
- return 0; // Can't optimize this
- }
-
key1->use_count--;
key2->use_count--;
SEL_ARG *e1=key1->first(), *e2=key2->first(), *new_tree=0;
@@ -6797,9 +6798,7 @@ static bool eq_tree(SEL_ARG* a,SEL_ARG *
SEL_ARG *
SEL_ARG::insert(SEL_ARG *key)
{
- SEL_ARG *element,**par,*last_element;
- LINT_INIT(par);
- LINT_INIT(last_element);
+ SEL_ARG *element,**UNINIT_VAR(par),*UNINIT_VAR(last_element);
for (element= this; element != &null_element ; )
{
@@ -8066,7 +8065,10 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_
if (cur_quick->file->inited != handler::NONE)
cur_quick->file->ha_index_end();
if (cur_quick->init() || cur_quick->reset())
+ {
+ delete unique;
DBUG_RETURN(1);
+ }
}
if (result)
@@ -8074,13 +8076,17 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_
if (result != HA_ERR_END_OF_FILE)
{
cur_quick->range_end();
+ delete unique;
DBUG_RETURN(result);
}
break;
}
if (thd->killed)
+ {
+ delete unique;
DBUG_RETURN(1);
+ }
/* skip row if it will be retrieved by clustered PK scan */
if (pk_quick_select && pk_quick_select->row_in_ranges())
@@ -8089,8 +8095,10 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_
cur_quick->file->position(cur_quick->record);
result= unique->unique_add((char*)cur_quick->file->ref);
if (result)
+ {
+ delete unique;
DBUG_RETURN(1);
-
+ }
}
/*
@@ -9397,7 +9405,9 @@ get_best_group_min_max(PARAM *param, SEL
goto next_index;
}
else
+ {
DBUG_ASSERT(FALSE);
+ }
/* Check (SA2). */
if (min_max_arg_item)
@@ -9631,7 +9641,17 @@ check_group_min_max_predicates(COND *con
*/
if (cond_type == Item::SUBSELECT_ITEM)
DBUG_RETURN(FALSE);
-
+
+ /*
+ Condition of the form 'field' is equivalent to 'field <> 0' and thus
+ satisfies the SA3 condition.
+ */
+ if (cond_type == Item::FIELD_ITEM)
+ {
+ DBUG_PRINT("info", ("Analyzing: %s", cond->full_name()));
+ DBUG_RETURN(TRUE);
+ }
+
/* We presume that at this point there are no other Items than functions. */
DBUG_ASSERT(cond_type == Item::FUNC_ITEM);
@@ -9789,11 +9809,22 @@ get_constant_key_infix(KEY *index_info,
return FALSE;
uint field_length= cur_part->store_length;
- if ((cur_range->maybe_null &&
- cur_range->min_value[0] && cur_range->max_value[0]) ||
- !memcmp(cur_range->min_value, cur_range->max_value, field_length))
- {
- /* cur_range specifies 'IS NULL' or an equality condition. */
+ if (cur_range->maybe_null &&
+ cur_range->min_value[0] && cur_range->max_value[0])
+ {
+ /*
+ cur_range specifies 'IS NULL'. In this case the argument points
+ to a "null value" (is_null_string) that may not always be long
+ enough for a direct memcpy to a field.
+ */
+ DBUG_ASSERT (field_length > 0);
+ *key_ptr= 1;
+ bzero(key_ptr+1,field_length-1);
+ key_ptr+= field_length;
+ *key_infix_len+= field_length;
+ }
+ else if (memcmp(cur_range->min_value, cur_range->max_value, field_length) == 0)
+ { /* cur_range specifies an equality condition. */
memcpy(key_ptr, cur_range->min_value, field_length);
key_ptr+= field_length;
*key_infix_len+= field_length;
=== modified file 'sql/partition_info.h'
--- a/sql/partition_info.h 2008-11-10 20:21:49 +0000
+++ b/sql/partition_info.h 2009-09-02 15:42:08 +0000
@@ -300,6 +300,7 @@ static inline void init_single_partition
{
part_iter->part_nums.start= part_iter->part_nums.cur= part_id;
part_iter->part_nums.end= part_id+1;
+ part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
part_iter->get_next= get_next_partition_id_range;
}
@@ -310,5 +311,6 @@ void init_all_partitions_iterator(partit
{
part_iter->part_nums.start= part_iter->part_nums.cur= 0;
part_iter->part_nums.end= part_info->no_parts;
+ part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
part_iter->get_next= get_next_partition_id_range;
}
=== modified file 'sql/procedure.h'
--- a/sql/procedure.h 2008-03-21 15:48:28 +0000
+++ b/sql/procedure.h 2009-10-16 22:57:48 +0000
@@ -42,7 +42,11 @@ public:
{
init_make_field(tmp_field,field_type());
}
- unsigned int size_of() { return sizeof(*this);}
+ unsigned int size_of() { return sizeof(*this);}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("proc");
+ }
};
class Item_proc_real :public Item_proc
=== modified file 'sql/records.cc'
--- a/sql/records.cc 2009-10-19 17:14:48 +0000
+++ b/sql/records.cc 2009-11-12 04:31:28 +0000
@@ -323,6 +323,7 @@ static int rr_quick(READ_RECORD *info)
break;
}
}
+ update_virtual_fields(info->table);
return tmp;
}
@@ -395,6 +396,8 @@ int rr_sequential(READ_RECORD *info)
break;
}
}
+ if (!tmp)
+ update_virtual_fields(info->table);
return tmp;
}
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2009-09-15 11:55:37 +0000
+++ b/sql/share/errmsg.txt 2009-11-10 02:32:39 +0000
@@ -6184,17 +6184,17 @@ ER_FUNC_INEXISTENT_NAME_COLLISION 42000
# When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in
# mysql_priv.h with the new maximal additional length for explain_filename.
ER_DATABASE_NAME
- eng "Database `%s`"
- swe "Databas `%s`"
+ eng "Database"
+ swe "Databas"
ER_TABLE_NAME
- eng "Table `%s`"
- swe "Tabell `%s`"
+ eng "Table"
+ swe "Tabell"
ER_PARTITION_NAME
- eng "Partition `%s`"
- swe "Partition `%s`"
+ eng "Partition"
+ swe "Partition"
ER_SUBPARTITION_NAME
- eng "Subpartition `%s`"
- swe "Subpartition `%s`"
+ eng "Subpartition"
+ swe "Subpartition"
ER_TEMPORARY_NAME
eng "Temporary"
swe "Tempor�
@@ -6206,3 +6206,30 @@ ER_TOO_MANY_CONCURRENT_TRXS
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED
eng "Non-ASCII separator arguments are not fully supported"
+
+ER_VCOL_BASED_ON_VCOL
+ eng "A computed column cannot be based on a computed column"
+
+ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+ eng "Function or expression is not allowed for column '%s'."
+
+ER_DATA_CONVERSION_ERROR_FOR_VIRTUAL_COLUMN
+ eng "Generated value for computed column '%s' cannot be converted to type '%s'."
+
+ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN
+ eng "Primary key cannot be defined upon a computed column."
+
+ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+ eng "Key/Index cannot be defined on a non-stored computed column."
+
+ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+ eng "Cannot define foreign key with %s clause on a computed column."
+
+ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN
+ eng "The value specified for computed column '%s' in table '%s' ignored."
+
+ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+ eng "'%s' is not yet supported for computed columns."
+
+ER_CONST_EXPR_IN_VCOL
+ eng "Constant expression in computed column function is not allowed."
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2009-10-26 11:35:42 +0000
+++ b/sql/slave.cc 2009-11-06 17:22:32 +0000
@@ -1961,9 +1961,6 @@ static int has_temporary_error(THD *thd)
{
DBUG_ENTER("has_temporary_error");
- if (thd->is_fatal_error)
- DBUG_RETURN(0);
-
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
if (thd->main_da.is_error())
{
@@ -3689,6 +3686,31 @@ void end_relay_log_info(Relay_log_info*
DBUG_VOID_RETURN;
}
+
+/**
+ Hook to detach the active VIO before closing a connection handle.
+
+ The client API might close the connection (and associated data)
+ in case it encounters a unrecoverable (network) error. This hook
+ is called from the client code before the VIO handle is deleted
+ allows the thread to detach the active vio so it does not point
+ to freed memory.
+
+ Other calls to THD::clear_active_vio throughout this module are
+ redundant due to the hook but are left in place for illustrative
+ purposes.
+*/
+
+extern "C" void slave_io_thread_detach_vio()
+{
+#ifdef SIGNAL_WITH_VIO_CLOSE
+ THD *thd= current_thd;
+ if (thd->slave_thread)
+ thd->clear_active_vio();
+#endif
+}
+
+
/*
Try to connect until successful or slave killed
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2009-09-15 10:46:35 +0000
+++ b/sql/sp_head.cc 2009-10-16 22:57:48 +0000
@@ -816,6 +816,8 @@ sp_head::create_result_field(uint field_
m_return_field_def.interval,
field_name ? field_name : (const char *) m_name.str);
+ field->vcol_info= m_return_field_def.vcol_info;
+ field->stored_in_db= m_return_field_def.stored_in_db;
if (field)
field->init(table);
@@ -2197,7 +2199,8 @@ sp_head::fill_field_definition(THD *thd,
&lex->interval_list,
lex->charset ? lex->charset :
thd->variables.collation_database,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/spatial.cc'
--- a/sql/spatial.cc 2009-04-25 10:05:32 +0000
+++ b/sql/spatial.cc 2009-10-15 21:38:29 +0000
@@ -935,13 +935,10 @@ int Gis_polygon::interior_ring_n(uint32
int Gis_polygon::centroid_xy(double *x, double *y) const
{
uint32 n_linear_rings;
- double res_area;
- double res_cx, res_cy;
+ double UNINIT_VAR(res_area);
+ double UNINIT_VAR(res_cx), UNINIT_VAR(res_cy);
const char *data= m_data;
bool first_loop= 1;
- LINT_INIT(res_area);
- LINT_INIT(res_cx);
- LINT_INIT(res_cy);
if (no_data(data, 4))
return 1;
@@ -1636,14 +1633,10 @@ int Gis_multi_polygon::centroid(String *
uint32 n_polygons;
bool first_loop= 1;
Gis_polygon p;
- double res_area, res_cx, res_cy;
+ double UNINIT_VAR(res_area), UNINIT_VAR(res_cx), UNINIT_VAR(res_cy);
double cur_area, cur_cx, cur_cy;
const char *data= m_data;
- LINT_INIT(res_area);
- LINT_INIT(res_cx);
- LINT_INIT(res_cy);
-
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_base.cc 2009-11-12 04:31:28 +0000
@@ -1521,21 +1521,23 @@ void close_temporary_tables(THD *thd)
my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id;
/* Set pseudo_thread_id to be that of the processed table */
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
- /*
- Loop forward through all tables within the sublist of
- common pseudo_thread_id to create single DROP query.
+ String db;
+ db.append(table->s->db.str);
+ /* Loop forward through all tables that belong to a common database
+ within the sublist of common pseudo_thread_id to create single
+ DROP query
*/
for (s_query.length(stub_len);
table && is_user_table(table) &&
- tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
+ tmpkeyval(thd, table) == thd->variables.pseudo_thread_id &&
+ table->s->db.length == db.length() &&
+ strcmp(table->s->db.str, db.ptr()) == 0;
table= next)
{
/*
- We are going to add 4 ` around the db/table names and possible more
- due to special characters in the names
+ We are going to add ` around the table names and possible more
+ due to special characters
*/
- append_identifier(thd, &s_query, table->s->db.str, strlen(table->s->db.str));
- s_query.append('.');
append_identifier(thd, &s_query, table->s->table_name.str,
strlen(table->s->table_name.str));
s_query.append(',');
@@ -1548,6 +1550,7 @@ void close_temporary_tables(THD *thd)
Query_log_event qinfo(thd, s_query.ptr(),
s_query.length() - 1 /* to remove trailing ',' */,
0, FALSE, 0);
+ qinfo.db= db.ptr();
thd->variables.character_set_client= cs_save;
mysql_bin_log.write(&qinfo);
thd->variables.pseudo_thread_id= save_pseudo_thread_id;
@@ -5607,6 +5610,9 @@ static void update_field_dependencies(TH
table->covering_keys.intersect(field->part_of_key);
table->merge_keys.merge(field->part_of_key);
+ if (field->vcol_info)
+ table->mark_virtual_col(field);
+
if (thd->mark_used_columns == MARK_COLUMNS_READ)
current_bitmap= table->read_set;
else
@@ -7900,6 +7906,12 @@ insert_fields(THD *thd, Name_resolution_
{
/* 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);
if (table)
{
table->covering_keys.intersect(field->part_of_key);
@@ -8111,7 +8123,10 @@ fill_record(THD * thd, List<Item> &field
Item *value, *fld;
Item_field *field;
TABLE *table= 0;
+ List<TABLE> tbl_list;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
@@ -8145,14 +8160,54 @@ fill_record(THD * thd, List<Item> &field
table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (rfield->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ rfield->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
+ tbl_list.push_back(table);
+ }
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> it(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= it++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields(table, TRUE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
}
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8188,9 +8243,31 @@ fill_record_n_invoke_before_triggers(THD
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, fields, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, fields, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers)
+ {
+ TABLE *table= 0;
+ List_iterator_fast<Item> f(fields);
+ Item *fld;
+ Item_field *item_field;
+ if (fields.elements)
+ {
+ fld= (Item_field*)f++;
+ item_field= fld->filed_for_view_update();
+ if (item_field && item_field->field &&
+ (table= item_field->field->table) &&
+ table->vfield)
+ result= update_virtual_fields(table, TRUE);
+ }
+ }
+ return result;
}
@@ -8218,11 +8295,14 @@ bool
fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
+ List<TABLE> tbl_list;
Item *value;
TABLE *table= 0;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
Field *field;
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
only one row.
@@ -8242,12 +8322,52 @@ fill_record(THD *thd, Field **ptr, List<
table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (field->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ field->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if (value->save_in_field(field, 0) < 0)
goto err;
+ tbl_list.push_back(table);
}
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields(table, TRUE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8283,9 +8403,22 @@ fill_record_n_invoke_before_triggers(THD
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, ptr, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, ptr, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers && *ptr)
+ {
+ TABLE *table= (*ptr)->table;
+ if (table->vfield)
+ result= update_virtual_fields(table, TRUE);
+ }
+ return result;
+
}
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_class.cc 2009-11-12 04:31:28 +0000
@@ -194,6 +194,59 @@ bool foreign_key_prefix(Key *a, Key *b)
#endif
}
+/*
+ @brief
+ Check if the foreign key options are compatible with the specification
+ of the columns on which the key is created
+
+ @retval
+ FALSE The foreign key options are compatible with key columns
+ @retval
+ TRUE Otherwise
+*/
+bool Foreign_key::validate(List<Create_field> &table_fields)
+{
+ Create_field *sql_field;
+ Key_part_spec *column;
+ List_iterator<Key_part_spec> cols(columns);
+ List_iterator<Create_field> it(table_fields);
+ DBUG_ENTER("Foreign_key::validate");
+ while ((column= cols++))
+ {
+ it.rewind();
+ while ((sql_field= it++) &&
+ my_strcasecmp(system_charset_info,
+ column->field_name,
+ sql_field->field_name)) {}
+ if (!sql_field)
+ {
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+ DBUG_RETURN(TRUE);
+ }
+ if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
+ {
+ if (delete_opt == FK_OPTION_SET_NULL)
+ {
+ my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
+ "ON DELETE SET NULL");
+ DBUG_RETURN(TRUE);
+ }
+ if (update_opt == FK_OPTION_SET_NULL)
+ {
+ my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
+ "ON UPDATE SET NULL");
+ DBUG_RETURN(TRUE);
+ }
+ if (update_opt == FK_OPTION_CASCADE)
+ {
+ my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
+ "ON UPDATE CASCADE");
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
/****************************************************************************
** Thread specific functions
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2009-10-19 17:14:48 +0000
+++ b/sql/sql_class.h 2009-11-12 04:31:28 +0000
@@ -249,6 +249,8 @@ public:
*/
virtual Key *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Foreign_key(*this, mem_root); }
+ /* Used to validate foreign key options */
+ bool validate(List<Create_field> &table_fields);
};
typedef struct st_mysql_lock
=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc 2009-09-07 20:50:10 +0000
+++ b/sql/sql_db.cc 2009-10-15 21:38:29 +0000
@@ -658,10 +658,8 @@ int mysql_create_db(THD *thd, char *db,
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
- if (!silent)
- my_ok(thd);
error= 0;
- goto exit;
+ goto not_silent;
}
else
{
@@ -698,7 +696,8 @@ int mysql_create_db(THD *thd, char *db,
happened. (This is a very unlikely senario)
*/
}
-
+
+not_silent:
if (!silent)
{
char *query;
=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc 2009-09-07 20:50:10 +0000
+++ b/sql/sql_delete.cc 2009-10-15 21:38:29 +0000
@@ -1067,6 +1067,9 @@ bool mysql_truncate(THD *thd, TABLE_LIST
bzero((char*) &create_info,sizeof(create_info));
+ /* Remove tables from the HANDLER's hash. */
+ mysql_ha_rm_tables(thd, table_list, FALSE);
+
/* If it is a temporary table, close and regenerate it */
if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
{
=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_handler.cc 2009-11-12 04:31:28 +0000
@@ -666,6 +666,8 @@ retry:
}
goto ok;
}
+ /* Generate values for virtual fields */
+ update_virtual_fields(table);
if (cond && !cond->val_int())
continue;
if (num_rows >= offset_limit_cnt)
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_insert.cc 2009-11-12 04:31:28 +0000
@@ -280,6 +280,9 @@ static int check_insert_fields(THD *thd,
}
}
}
+ /* Mark virtual columns used in the insert statement */
+ if (table->vfield)
+ table->mark_virtual_columns_for_write();
// For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
@@ -3421,25 +3424,6 @@ static TABLE *create_table_from_items(TH
bool not_used;
DBUG_ENTER("create_table_from_items");
- DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););
-
- if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
- create_table->table->db_stat)
- {
- /* Table already exists and was open at open_and_lock_tables() stage. */
- if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- {
- create_info->table_existed= 1; // Mark that table existed
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
- create_table->table_name);
- DBUG_RETURN(create_table->table);
- }
-
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
- DBUG_RETURN(0);
- }
-
tmp_table.alias= 0;
tmp_table.timestamp_field= 0;
tmp_table.s= &share;
@@ -3648,10 +3632,35 @@ select_create::prepare(List<Item> &value
thd->binlog_start_trans_and_stmt();
}
- if (!(table= create_table_from_items(thd, create_info, create_table,
- alter_info, &values,
- &extra_lock, hook_ptr)))
- DBUG_RETURN(-1); // abort() deletes table
+ DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););
+
+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
+ create_table->table->db_stat)
+ {
+ /* Table already exists and was open at open_and_lock_tables() stage. */
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ /* Mark that table existed */
+ create_info->table_existed= 1;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ create_table->table_name);
+ if (thd->current_stmt_binlog_row_based)
+ binlog_show_create_table(&(create_table->table), 1);
+ table= create_table->table;
+ }
+ else
+ {
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ else
+ if (!(table= create_table_from_items(thd, create_info, create_table,
+ alter_info, &values,
+ &extra_lock, hook_ptr)))
+ /* abort() deletes table */
+ DBUG_RETURN(-1);
if (extra_lock)
{
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2009-09-15 10:46:35 +0000
+++ b/sql/sql_lex.cc 2009-10-16 22:57:48 +0000
@@ -340,6 +340,7 @@ void lex_start(THD *thd)
lex->reset_query_tables_list(FALSE);
lex->expr_allows_subselect= TRUE;
lex->use_only_table_context= FALSE;
+ lex->parse_vcol_expr= FALSE;
lex->name.str= 0;
lex->name.length= 0;
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2009-10-19 17:14:48 +0000
+++ b/sql/sql_lex.h 2009-11-12 04:31:28 +0000
@@ -1546,6 +1546,7 @@ typedef struct st_lex : public Query_tab
LEX_USER *grant_user;
XID *xid;
THD *thd;
+ Virtual_column_info *vcol_info;
/* maintain a list of used plugins for this LEX */
DYNAMIC_ARRAY plugins;
@@ -1628,6 +1629,14 @@ typedef struct st_lex : public Query_tab
syntax error back.
*/
bool expr_allows_subselect;
+ /*
+ A special command "PARSE_VCOL_EXPR" is defined for the parser
+ to translate a defining expression of a virtual column into an
+ Item object.
+ The following flag is used to prevent other applications to use
+ this command.
+ */
+ bool parse_vcol_expr;
thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2009-10-28 14:56:07 +0000
+++ b/sql/sql_parse.cc 2009-11-12 04:31:28 +0000
@@ -468,7 +468,7 @@ pthread_handler_t handle_bootstrap(void
thd->init_for_queries();
while (fgets(buff, thd->net.max_packet, file))
{
- char *query;
+ char *query, *res;
/* strlen() can't be deleted because fgets() doesn't return length */
ulong length= (ulong) strlen(buff);
while (buff[length-1] != '\n' && !feof(file))
@@ -6102,7 +6102,8 @@ bool add_field_to_list(THD *thd, LEX_STR
LEX_STRING *comment,
char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type)
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6188,7 +6189,7 @@ bool add_field_to_list(THD *thd, LEX_STR
if (!(new_field= new Create_field()) ||
new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
default_value, on_update_value, comment, change,
- interval_list, cs, uint_geom_type))
+ interval_list, cs, uint_geom_type, vcol_info))
DBUG_RETURN(1);
lex->alter_info.create_list.push_back(new_field);
=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc 2009-09-07 20:50:10 +0000
+++ b/sql/sql_partition.cc 2009-11-10 02:32:39 +0000
@@ -975,7 +975,8 @@ bool fix_fields_part_func(THD *thd, Item
thd->lex->use_only_table_context= TRUE;
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
- error= func_expr->fix_fields(thd, (Item**)&func_expr);
+ if (!(error= func_expr->fix_fields(thd, (Item**)&func_expr)))
+ func_expr->walk(&Item::vcol_in_partition_func_processor, 0, NULL);
thd->lex->use_only_table_context= save_use_only_table_context;
@@ -2766,8 +2767,24 @@ uint32 get_list_array_idx_for_endpoint(p
if (part_info->part_expr->null_value)
{
- DBUG_RETURN(0);
+ /*
+ Special handling for MONOTONIC functions that can return NULL for
+ values that are comparable. I.e.
+ '2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00')
+ returns NULL which cannot be compared used <, >, <=, >= etc.
+
+ Otherwise, just return the the first index (lowest value).
+ */
+ enum_monotonicity_info monotonic;
+ monotonic= part_info->part_expr->get_monotonicity_info();
+ if (monotonic != MONOTONIC_INCREASING_NOT_NULL &&
+ monotonic != MONOTONIC_STRICT_INCREASING_NOT_NULL)
+ {
+ /* F(col) can not return NULL, return index with lowest value */
+ DBUG_RETURN(0);
+ }
}
+
if (unsigned_flag)
part_func_value-= 0x8000000000000000ULL;
DBUG_ASSERT(part_info->no_list_values);
@@ -2916,11 +2933,29 @@ uint32 get_partition_id_range_for_endpoi
if (part_info->part_expr->null_value)
{
- uint32 ret_part_id= 0;
- if (!left_endpoint && include_endpoint)
- ret_part_id= 1;
- DBUG_RETURN(ret_part_id);
+ /*
+ Special handling for MONOTONIC functions that can return NULL for
+ values that are comparable. I.e.
+ '2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00')
+ returns NULL which cannot be compared used <, >, <=, >= etc.
+
+ Otherwise, just return the first partition
+ (may be included if not left endpoint)
+ */
+ enum_monotonicity_info monotonic;
+ monotonic= part_info->part_expr->get_monotonicity_info();
+ if (monotonic != MONOTONIC_INCREASING_NOT_NULL &&
+ monotonic != MONOTONIC_STRICT_INCREASING_NOT_NULL)
+ {
+ /* F(col) can not return NULL, return partition with lowest value */
+ if (!left_endpoint && include_endpoint)
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+
+ }
}
+
+
if (unsigned_flag)
part_func_value-= 0x8000000000000000ULL;
if (left_endpoint && !include_endpoint)
@@ -6077,6 +6112,9 @@ uint fast_alter_partition_table(THD *thd
lpt->pack_frm_len= 0;
thd->work_part_info= part_info;
+ /* Never update timestamp columns when alter */
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
if (fast_alter_partition & HA_PARTITION_ONE_PHASE)
{
/*
@@ -6693,6 +6731,7 @@ int get_part_iter_for_interval_via_mappi
Field *field= part_info->part_field_array[0];
uint32 max_endpoint_val;
get_endpoint_func get_endpoint;
+ bool can_match_multiple_values; /* is not '=' */
uint field_len= field->pack_length_in_rec();
part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
@@ -6730,6 +6769,23 @@ int get_part_iter_for_interval_via_mappi
}
else
assert(0);
+
+ can_match_multiple_values= (flags || !min_value || !max_value ||
+ memcmp(min_value, max_value, field_len));
+ if (can_match_multiple_values &&
+ (part_info->part_type == RANGE_PARTITION ||
+ part_info->has_null_value))
+ {
+ /* Range scan on RANGE or LIST partitioned table */
+ enum_monotonicity_info monotonic;
+ monotonic= part_info->part_expr->get_monotonicity_info();
+ if (monotonic == MONOTONIC_INCREASING_NOT_NULL ||
+ monotonic == MONOTONIC_STRICT_INCREASING_NOT_NULL)
+ {
+ /* col is NOT NULL, but F(col) can return NULL, add NULL partition */
+ part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
+ }
+ }
/*
Find minimum: Do special handling if the interval has left bound in form
@@ -6762,6 +6818,14 @@ int get_part_iter_for_interval_via_mappi
store_key_image_to_rec(field, min_value, field_len);
bool include_endp= !test(flags & NEAR_MIN);
part_iter->part_nums.start= get_endpoint(part_info, 1, include_endp);
+ if (!can_match_multiple_values && part_info->part_expr->null_value)
+ {
+ /* col = x and F(x) = NULL -> only search NULL partition */
+ part_iter->part_nums.cur= part_iter->part_nums.start= 0;
+ part_iter->part_nums.end= 0;
+ part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
+ return 1;
+ }
part_iter->part_nums.cur= part_iter->part_nums.start;
if (part_iter->part_nums.start == max_endpoint_val)
return 0; /* No partitions */
@@ -6846,6 +6910,7 @@ int get_part_iter_for_interval_via_walki
Field *field;
uint total_parts;
partition_iter_func get_next_func;
+ part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
if (is_subpart)
{
field= part_info->subpart_field_array[0];
@@ -6956,7 +7021,13 @@ uint32 get_next_partition_id_range(PARTI
{
if (part_iter->part_nums.cur >= part_iter->part_nums.end)
{
+ if (part_iter->ret_null_part)
+ {
+ part_iter->ret_null_part= FALSE;
+ return 0; /* NULL always in first range partition */
+ }
part_iter->part_nums.cur= part_iter->part_nums.start;
+ part_iter->ret_null_part= part_iter->ret_null_part_orig;
return NOT_A_PARTITION_ID;
}
else
@@ -6984,7 +7055,7 @@ uint32 get_next_partition_id_range(PARTI
uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter)
{
- if (part_iter->part_nums.cur == part_iter->part_nums.end)
+ if (part_iter->part_nums.cur >= part_iter->part_nums.end)
{
if (part_iter->ret_null_part)
{
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2009-10-28 14:56:07 +0000
+++ b/sql/sql_plugin.cc 2009-11-12 04:31:28 +0000
@@ -3226,7 +3226,6 @@ static int test_plugin_options(MEM_ROOT
my_bool can_disable;
bool disable_plugin;
enum_plugin_load_policy plugin_load_policy= PLUGIN_ON;
-
MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
&tmp->mem_root : &plugin_mem_root;
st_mysql_sys_var **opt;
@@ -3240,13 +3239,13 @@ static int test_plugin_options(MEM_ROOT
DBUG_ENTER("test_plugin_options");
DBUG_ASSERT(tmp->plugin && tmp->name.str);
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
/*
- The 'federated' and 'ndbcluster' storage engines are always disabled by
- default.
+ The 'ndbcluster' storage engines is always disabled by default.
*/
- if (!(my_strcasecmp(&my_charset_latin1, tmp->name.str, "federated") &&
- my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster")))
+ if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster"))
plugin_load_policy= PLUGIN_OFF;
+#endif
for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
@@ -3295,6 +3294,11 @@ static int test_plugin_options(MEM_ROOT
can_disable=
my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") &&
my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY");
+#ifdef USE_MARIA_FOR_TMP_TABLES
+ if (!can_disable)
+ can_disable= (my_strcasecmp(&my_charset_latin1, tmp->name.str, "Maria")
+ != 0);
+#endif
tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE) || !can_disable;
=== modified file 'sql/sql_profile.cc'
--- a/sql/sql_profile.cc 2009-09-07 20:50:10 +0000
+++ b/sql/sql_profile.cc 2009-10-15 21:38:29 +0000
@@ -33,7 +33,7 @@
#include "my_sys.h"
#define TIME_FLOAT_DIGITS 9
-/** two vals encoded: (dec*100)+len */
+/** two vals encoded: (len*100)+dec */
#define TIME_I_S_DECIMAL_SIZE (TIME_FLOAT_DIGITS*100)+(TIME_FLOAT_DIGITS-3)
#define MAX_QUERY_LENGTH 300
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2009-10-28 14:56:07 +0000
+++ b/sql/sql_select.cc 2009-11-12 04:31:28 +0000
@@ -9493,43 +9493,8 @@ static Field *create_tmp_field_from_item
new_field->set_derivation(item->collation.derivation);
break;
case DECIMAL_RESULT:
- {
- uint8 dec= item->decimals;
- uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec;
- uint32 len= item->max_length;
-
- /*
- Trying to put too many digits overall in a DECIMAL(prec,dec)
- will always throw a warning. We must limit dec to
- DECIMAL_MAX_SCALE however to prevent an assert() later.
- */
-
- if (dec > 0)
- {
- signed int overflow;
-
- dec= min(dec, DECIMAL_MAX_SCALE);
-
- /*
- If the value still overflows the field with the corrected dec,
- we'll throw out decimals rather than integers. This is still
- bad and of course throws a truncation warning.
- +1: for decimal point
- */
-
- overflow= my_decimal_precision_to_length(intg + dec, dec,
- item->unsigned_flag) - len;
-
- if (overflow > 0)
- dec= max(0, dec - overflow); // too long, discard fract
- else
- len -= item->decimals - dec; // corrected value fits
- }
-
- new_field= new Field_new_decimal(len, maybe_null, item->name,
- dec, item->unsigned_flag);
+ new_field= Field_new_decimal::new_decimal_field(item);
break;
- }
case ROW_RESULT:
default:
// This case should never be choosen
@@ -9761,6 +9726,10 @@ void setup_tmp_table_column_bitmaps(TABL
bitmap_init(&table->tmp_set,
(my_bitmap_map*) (bitmaps+ bitmap_buffer_size(field_count)),
field_count, FALSE);
+ bitmap_init(&table->vcol_set,
+ (my_bitmap_map*) (bitmaps+ 2+bitmap_buffer_size(field_count)),
+ field_count, FALSE);
+
/* write_set and all_set are copies of read_set */
table->def_write_set= table->def_read_set;
table->s->all_set= table->def_read_set;
@@ -9909,7 +9878,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
&tmpname, (uint) strlen(tmp_table_name)+1,
&group_buff, (group && ! using_unique_constraint ?
param->group_length : 0),
- &bitmaps, bitmap_buffer_size(field_count)*2,
+ &bitmaps, bitmap_buffer_size(field_count)*3,
NullS))
{
if (temp_pool_slot != MY_BIT_NONE)
@@ -10513,7 +10482,7 @@ TABLE *create_virtual_tmp_table(THD *thd
&share, sizeof(*share),
&field, (field_count + 1) * sizeof(Field*),
&blob_field, (field_count+1) *sizeof(uint),
- &bitmaps, bitmap_buffer_size(field_count)*2,
+ &bitmaps, bitmap_buffer_size(field_count)*3,
NullS))
return 0;
@@ -11477,6 +11446,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
return NESTED_LOOP_KILLED; /* purecov: inspected */
}
DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
+ update_virtual_fields(join_tab->table);
if (!select_cond || select_cond->val_int())
{
/*
@@ -11686,6 +11656,8 @@ flush_cached_records(JOIN *join,JOIN_TAB
return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
}
SQL_SELECT *select=join_tab->select;
+ if (rc == NESTED_LOOP_OK)
+ update_virtual_fields(join_tab->table);
if (rc == NESTED_LOOP_OK &&
(!join_tab->cache.select || !join_tab->cache.select->skip_record()))
{
@@ -11869,6 +11841,7 @@ join_read_system(JOIN_TAB *tab)
empty_record(table); // Make empty record
return -1;
}
+ update_virtual_fields(table);
store_record(table,record[1]);
}
else if (!table->status) // Only happens with left join
@@ -11917,6 +11890,7 @@ join_read_const(JOIN_TAB *tab)
return report_error(table, error);
return -1;
}
+ update_virtual_fields(table);
store_record(table,record[1]);
}
else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join
@@ -12176,6 +12150,7 @@ join_read_next(READ_RECORD *info)
int error;
if ((error= info->file->ha_index_next(info->record)))
return report_error(info->table, error);
+
return 0;
}
@@ -12203,6 +12178,7 @@ join_read_last(JOIN_TAB *tab)
error= table->file->prepare_index_scan();
if (error || (error= tab->table->file->ha_index_last(tab->table->record[0])))
return report_error(table, error);
+
return 0;
}
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_show.cc 2009-11-12 04:31:28 +0000
@@ -1186,6 +1186,19 @@ int store_create_info(THD *thd, TABLE_LI
field->sql_type(type);
packet->append(type.ptr(), type.length(), system_charset_info);
+ if (field->vcol_info)
+ {
+ packet->append(STRING_WITH_LEN(" AS ("));
+ packet->append(field->vcol_info->expr_str.str,
+ field->vcol_info->expr_str.length,
+ system_charset_info);
+ packet->append(STRING_WITH_LEN(")"));
+ if (field->stored_in_db)
+ packet->append(STRING_WITH_LEN(" PERSISTENT"));
+ else
+ packet->append(STRING_WITH_LEN(" VIRTUAL"));
+ }
+
if (field->has_charset() &&
!(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
{
@@ -1216,7 +1229,8 @@ int store_create_info(THD *thd, TABLE_LI
packet->append(STRING_WITH_LEN(" NULL"));
}
- if (get_field_default_value(thd, table, field, &def_value, 1))
+ if (!field->vcol_info &&
+ get_field_default_value(thd, table, field, &def_value, 1))
{
packet->append(STRING_WITH_LEN(" DEFAULT "));
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
@@ -4221,6 +4235,8 @@ static int get_schema_column_record(THD
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
cs);
+ if (field->vcol_info)
+ table->field[16]->store(STRING_WITH_LEN("VIRTUAL"), cs);
table->field[18]->store(field->comment.str, field->comment.length, cs);
if (schema_table_store_record(thd, table))
@@ -5996,6 +6012,12 @@ TABLE *create_schema_table(THD *thd, TAB
{
DBUG_RETURN(0);
}
+ /*
+ Create a type holder, as we want the type of the item to defined
+ the type of the object, not the value
+ */
+ if (!(item= new Item_type_holder(thd, item)))
+ DBUG_RETURN(0);
item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
item->decimals= fields_info->field_length%10;
item->max_length= (fields_info->field_length/100)%100;
@@ -7491,8 +7513,6 @@ bool show_create_trigger(THD *thd, const
/* Perform closing actions and return error status. */
}
- DBUG_ASSERT(num_tables == 1);
-
Table_triggers_list *triggers= lst->table->triggers;
if (!triggers)
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_table.cc 2009-11-12 04:31:28 +0000
@@ -72,7 +72,7 @@ static void wait_for_kill_signal(THD *th
@brief Helper function for explain_filename
*/
static char* add_identifier(char *to_p, const char * end_p,
- const char* name, uint name_len, int errcode)
+ const char* name, uint name_len, bool add_quotes)
{
uint res;
uint errors;
@@ -92,18 +92,44 @@ static char* add_identifier(char *to_p,
res= strconvert(&my_charset_filename, conv_name, system_charset_info,
conv_string, FN_REFLEN, &errors);
if (!res || errors)
+ {
+ DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)", conv_name, res, errors));
conv_name= name;
+ }
else
{
DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string));
conv_name= conv_string;
}
- if (errcode)
- to_p+= my_snprintf(to_p, end_p - to_p, ER(errcode), conv_name);
+ if (add_quotes && (end_p - to_p > 2))
+ {
+ *(to_p++)= '`';
+ while (*conv_name && (end_p - to_p - 1) > 0)
+ {
+ uint length= my_mbcharlen(system_charset_info, *conv_name);
+ if (!length)
+ length= 1;
+ if (length == 1 && *conv_name == '`')
+ {
+ if ((end_p - to_p) < 3)
+ break;
+ *(to_p++)= '`';
+ *(to_p++)= *(conv_name++);
+ }
+ else if (((long) length) < (end_p - to_p))
+ {
+ to_p= strnmov(to_p, conv_name, length);
+ conv_name+= length;
+ }
+ else
+ break; /* string already filled */
+ }
+ to_p= strnmov(to_p, "`", end_p - to_p);
+ }
else
- to_p+= my_snprintf(to_p, end_p - to_p, "`%s`", conv_name);
- return to_p;
+ to_p= strnmov(to_p, conv_name, end_p - to_p);
+ DBUG_RETURN(to_p);
}
@@ -135,6 +161,8 @@ static char* add_identifier(char *to_p,
[,[ Temporary| Renamed] Partition `p`
[, Subpartition `sp`]] *|
(| is really a /, and it is all in one line)
+ EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING ->
+ same as above but no quotes are added.
@retval Length of returned string
*/
@@ -245,28 +273,39 @@ uint explain_filename(const char *from,
part_name_len-= 5;
}
}
+ else
+ table_name_len= strlen(table_name);
if (db_name)
{
if (explain_mode == EXPLAIN_ALL_VERBOSE)
{
- to_p= add_identifier(to_p, end_p, db_name, db_name_len,
- ER_DATABASE_NAME);
+ to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p);
+ *(to_p++)= ' ';
+ to_p= add_identifier(to_p, end_p, db_name, db_name_len, 1);
to_p= strnmov(to_p, ", ", end_p - to_p);
}
else
{
- to_p= add_identifier(to_p, end_p, db_name, db_name_len, 0);
+ to_p= add_identifier(to_p, end_p, db_name, db_name_len,
+ (explain_mode !=
+ EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
to_p= strnmov(to_p, ".", end_p - to_p);
}
}
if (explain_mode == EXPLAIN_ALL_VERBOSE)
- to_p= add_identifier(to_p, end_p, table_name, table_name_len,
- ER_TABLE_NAME);
+ {
+ to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p);
+ *(to_p++)= ' ';
+ to_p= add_identifier(to_p, end_p, table_name, table_name_len, 1);
+ }
else
- to_p= add_identifier(to_p, end_p, table_name, table_name_len, 0);
+ to_p= add_identifier(to_p, end_p, table_name, table_name_len,
+ (explain_mode !=
+ EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
if (part_name)
{
- if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT ||
+ explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)
to_p= strnmov(to_p, " /* ", end_p - to_p);
else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE)
to_p= strnmov(to_p, " ", end_p - to_p);
@@ -280,15 +319,22 @@ uint explain_filename(const char *from,
to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p);
to_p= strnmov(to_p, " ", end_p - to_p);
}
+ to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p);
+ *(to_p++)= ' ';
to_p= add_identifier(to_p, end_p, part_name, part_name_len,
- ER_PARTITION_NAME);
+ (explain_mode !=
+ EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
if (subpart_name)
{
to_p= strnmov(to_p, ", ", end_p - to_p);
+ to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p);
+ *(to_p++)= ' ';
to_p= add_identifier(to_p, end_p, subpart_name, subpart_name_len,
- ER_SUBPARTITION_NAME);
+ (explain_mode !=
+ EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
}
- if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT ||
+ explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)
to_p= strnmov(to_p, " */", end_p - to_p);
}
DBUG_PRINT("exit", ("to '%s'", to));
@@ -2441,7 +2487,8 @@ int prepare_create_field(Create_field *s
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
}
- if (!(sql_field->flags & NOT_NULL_FLAG))
+ if (!(sql_field->flags & NOT_NULL_FLAG) ||
+ (sql_field->vcol_info)) /* Make virtual columns allow NULL values */
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
@@ -2755,6 +2802,8 @@ mysql_prepare_create_table(THD *thd, HA_
null_fields--;
sql_field->flags= dup_field->flags;
sql_field->interval= dup_field->interval;
+ sql_field->vcol_info= dup_field->vcol_info;
+ sql_field->stored_in_db= dup_field->stored_in_db;
it2.remove(); // Remove first (create) definition
select_field_pos--;
break;
@@ -2787,7 +2836,23 @@ mysql_prepare_create_table(THD *thd, HA_
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
- record_offset+= sql_field->pack_length;
+ /*
+ For now skip fields that are not physically stored in the database
+ (virtual fields) and update their offset later
+ (see the next loop).
+ */
+ if (sql_field->stored_in_db)
+ record_offset+= sql_field->pack_length;
+ }
+ /* Update virtual fields' offset*/
+ it.rewind();
+ while ((sql_field=it++))
+ {
+ if (!sql_field->stored_in_db)
+ {
+ sql_field->offset= record_offset;
+ record_offset+= sql_field->pack_length;
+ }
}
if (timestamps_with_niladic > 1)
{
@@ -2837,6 +2902,8 @@ mysql_prepare_create_table(THD *thd, HA_
if (key->type == Key::FOREIGN_KEY)
{
fk_key_count++;
+ if (((Foreign_key *)key)->validate(alter_info->create_list))
+ DBUG_RETURN(TRUE);
Foreign_key *fk_key= (Foreign_key*) key;
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
@@ -3123,6 +3190,17 @@ mysql_prepare_create_table(THD *thd, HA_
}
}
#endif
+ if (!sql_field->stored_in_db)
+ {
+ /* Key fields must always be physically stored. */
+ my_error(ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (key->type == Key::PRIMARY && sql_field->vcol_info)
+ {
+ my_error(ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
if (!(sql_field->flags & NOT_NULL_FLAG))
{
if (key->type == Key::PRIMARY)
@@ -3476,6 +3554,41 @@ void sp_prepare_create_field(THD *thd, C
/*
+ Write CREATE TABLE binlog
+
+ SYNOPSIS
+ write_create_table_bin_log()
+ thd Thread object
+ create_info Create information
+ internal_tmp_table Set to 1 if this is an internal temporary table
+
+ DESCRIPTION
+ This function only is called in mysql_create_table_no_lock and
+ mysql_create_table
+
+ RETURN VALUES
+ NONE
+ */
+static inline void write_create_table_bin_log(THD *thd,
+ const HA_CREATE_INFO *create_info,
+ bool internal_tmp_table)
+{
+ /*
+ Don't write statement if:
+ - It is an internal temporary table,
+ - Row-based logging is used and it we are creating a temporary table, or
+ - The binary log is not open.
+ Otherwise, the statement shall be binlogged.
+ */
+ if (!internal_tmp_table &&
+ (!thd->current_stmt_binlog_row_based ||
+ (thd->current_stmt_binlog_row_based &&
+ !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+}
+
+
+/*
Create a table
SYNOPSIS
@@ -3739,6 +3852,7 @@ bool mysql_create_table_no_lock(THD *thd
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
error= 0;
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
goto err;
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -3866,18 +3980,7 @@ bool mysql_create_table_no_lock(THD *thd
thd->thread_specific_used= TRUE;
}
- /*
- Don't write statement if:
- - It is an internal temporary table,
- - Row-based logging is used and it we are creating a temporary table, or
- - The binary log is not open.
- Otherwise, the statement shall be binlogged.
- */
- if (!internal_tmp_table &&
- (!thd->current_stmt_binlog_row_based ||
- (thd->current_stmt_binlog_row_based &&
- !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
error= FALSE;
unlock_and_end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -3893,6 +3996,7 @@ warn:
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
create_info->table_existed= 1; // Mark that table existed
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
goto unlock_and_end;
}
@@ -3944,6 +4048,7 @@ bool mysql_create_table(THD *thd, const
table_name);
create_info->table_existed= 1;
result= FALSE;
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
}
else
{
@@ -5285,6 +5390,24 @@ bool mysql_create_like_table(THD* thd, T
goto err; /* purecov: inspected */
}
+goto binlog;
+
+table_exists:
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ my_snprintf(warn_buff, sizeof(warn_buff),
+ ER(ER_TABLE_EXISTS_ERROR), table_name);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR,warn_buff);
+ }
+ else
+ {
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+ goto err;
+ }
+
+binlog:
DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
/*
@@ -5348,20 +5471,6 @@ bool mysql_create_like_table(THD* thd, T
write_bin_log(thd, TRUE, thd->query, thd->query_length);
res= FALSE;
- goto err;
-
-table_exists:
- if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- {
- char warn_buff[MYSQL_ERRMSG_SIZE];
- my_snprintf(warn_buff, sizeof(warn_buff),
- ER(ER_TABLE_EXISTS_ERROR), table_name);
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_TABLE_EXISTS_ERROR,warn_buff);
- res= FALSE;
- }
- else
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
err:
if (name_lock)
@@ -5644,6 +5753,19 @@ compare_tables(TABLE *table,
DBUG_RETURN(0);
}
+ /*
+ Check if the altered column is computed and either
+ is stored or is used in the partitioning expression.
+ TODO: Mark such a column with an alter flag only if
+ the defining expression has changed.
+ */
+ if (field->vcol_info &&
+ (field->stored_in_db || field->vcol_info->is_in_partitioning_expr()))
+ {
+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
+ DBUG_RETURN(0);
+ }
+
/* Don't pack rows in old tables if the user has requested this. */
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
(tmp_new_field->flags & BLOB_FLAG) ||
@@ -6008,6 +6130,13 @@ mysql_prepare_alter_table(THD *thd, TABL
if (def)
{ // Field is changed
def->field=field;
+ if (field->stored_in_db != def->stored_in_db)
+ {
+ my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
+ MYF(0),
+ "Changing the STORED status");
+ goto err;
+ }
if (!def->after)
{
new_create_list.push_back(def);
@@ -6220,6 +6349,9 @@ mysql_prepare_alter_table(THD *thd, TABL
Key *key;
while ((key=key_it++)) // Add new keys
{
+ if (key->type == Key::FOREIGN_KEY &&
+ ((Foreign_key *)key)->validate(new_create_list))
+ goto err;
if (key->type != Key::FOREIGN_KEY)
new_key_list.push_back(key);
if (key->name &&
@@ -7600,6 +7732,7 @@ copy_data_between_tables(TABLE *from,TAB
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
+ to->mark_virtual_columns_for_write();
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
errpos= 4;
if (ignore)
@@ -7614,6 +7747,7 @@ copy_data_between_tables(TABLE *from,TAB
error= 1;
break;
}
+ update_virtual_fields(from);
thd->row_count++;
/* Return error if source table isn't empty. */
if (error_if_not_empty)
@@ -7634,6 +7768,12 @@ copy_data_between_tables(TABLE *from,TAB
copy_ptr->do_copy(copy_ptr);
}
prev_insert_id= to->file->next_insert_id;
+ update_virtual_fields(to, TRUE);
+ if (thd->is_error())
+ {
+ error= 1;
+ break;
+ }
error=to->file->ha_write_row(to->record[0]);
to->auto_increment_field_not_null= FALSE;
if (error)
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2009-10-19 17:14:48 +0000
+++ b/sql/sql_update.cc 2009-11-12 04:31:28 +0000
@@ -730,6 +730,7 @@ int mysql_update(THD *thd,
break;
}
}
+ table->auto_increment_field_not_null= FALSE;
dup_key_found= 0;
/*
Caching the killed status to pass as the arg to query event constuctor;
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2009-09-07 20:50:10 +0000
+++ b/sql/sql_view.cc 2009-10-15 21:38:29 +0000
@@ -1032,7 +1032,8 @@ bool mysql_make_view(THD *thd, File_pars
TABLE_LIST *top_view= table->top_table();
bool parse_status;
bool result, view_is_mergeable;
- TABLE_LIST *view_main_select_tables;
+ TABLE_LIST *UNINIT_VAR(view_main_select_tables);
+
DBUG_ENTER("mysql_make_view");
DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name));
@@ -1309,7 +1310,6 @@ bool mysql_make_view(THD *thd, File_pars
old_lex->set_stmt_unsafe();
view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
lex->can_be_merged());
- LINT_INIT(view_main_select_tables);
if (view_is_mergeable)
{
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2009-10-19 17:14:48 +0000
+++ b/sql/sql_yacc.yy 2009-11-12 04:31:28 +0000
@@ -549,6 +549,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token ALGORITHM_SYM
%token ALL /* SQL-2003-R */
%token ALTER /* SQL-2003-R */
+%token ALWAYS_SYM
%token ANALYZE_SYM
%token AND_AND_SYM /* OPERATOR */
%token AND_SYM /* SQL-2003-R */
@@ -716,6 +717,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token FULLTEXT_SYM
%token FUNCTION_SYM /* SQL-2003-R */
%token GE
+%token GENERATED_SYM
%token GEOMETRYCOLLECTION
%token GEOMETRY_SYM
%token GET_FORMAT /* MYSQL-FUNC */
@@ -894,11 +896,13 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token PAGE_CHECKSUM_SYM
%token PARAM_MARKER
%token PARSER_SYM
+%token PARSE_VCOL_EXPR_SYM
%token PARTIAL /* SQL-2003-N */
%token PARTITIONING_SYM
%token PARTITIONS_SYM
%token PARTITION_SYM /* SQL-2003-R */
%token PASSWORD
+%token PERSISTENT_SYM
%token PHASE_SYM
%token PLUGINS_SYM
%token PLUGIN_SYM
@@ -1095,6 +1099,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token VARIANCE_SYM
%token VARYING /* SQL-2003-R */
%token VAR_SAMP_SYM
+%token VIRTUAL_SYM
%token VIEW_SYM /* SQL-2003-N */
%token WAIT_SYM
%token WARNINGS
@@ -1154,7 +1159,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
text_string opt_gconcat_separator
%type <num>
- type int_type real_type order_dir lock_option
+ type int_type real_type order_dir lock_option field_def
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog
delete_option opt_temporary all_or_any opt_distinct
@@ -1310,6 +1315,8 @@ bool my_yyoverflow(short **a, YYSTYPE **
init_key_options key_options key_opts key_opt key_using_alg
server_def server_options_list server_option
definer_opt no_definer definer
+ parse_vcol_expr vcol_opt_specifier vcol_opt_attribute
+ vcol_opt_attribute_list vcol_attribute
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1441,6 +1448,7 @@ statement:
| lock
| optimize
| keycache
+ | parse_vcol_expr
| partition_entry
| preload
| prepare
@@ -1819,15 +1827,16 @@ server_option:
;
event_tail:
- EVENT_SYM opt_if_not_exists sp_name
+ remember_name EVENT_SYM opt_if_not_exists sp_name
{
THD *thd= YYTHD;
LEX *lex=Lex;
- lex->create_info.options= $2;
+ lex->stmt_definition_begin= $1;
+ lex->create_info.options= $3;
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
- lex->event_parse_data->identifier= $3;
+ lex->event_parse_data->identifier= $4;
lex->event_parse_data->on_completion=
Event_parse_data::ON_COMPLETION_DROP;
@@ -3764,8 +3773,8 @@ partitioning:
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
{
- my_error(ER_FEATURE_DISABLED, MYF(0),
- "partitioning", "--with-partition");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition");
MYSQL_YYABORT;
}
lex->part_info= new partition_info();
@@ -4770,8 +4779,9 @@ field_spec:
lex->default_value= lex->on_update_value= 0;
lex->comment=null_lex_str;
lex->charset=NULL;
+ lex->vcol_info= 0;
}
- type opt_attribute
+ field_def
{
LEX *lex=Lex;
if (add_field_to_list(lex->thd, &$1, (enum enum_field_types) $3,
@@ -4779,11 +4789,101 @@ field_spec:
lex->default_value, lex->on_update_value,
&lex->comment,
lex->change,&lex->interval_list,lex->charset,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info))
MYSQL_YYABORT;
}
;
+field_def:
+ type opt_attribute {}
+ | type opt_generated_always AS '(' virtual_column_func ')'
+ vcol_opt_specifier
+ vcol_opt_attribute
+ {
+ $$= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
+ Lex->vcol_info->set_field_type((enum enum_field_types) $1);
+ }
+ ;
+
+opt_generated_always:
+ /* empty */
+ | GENERATED_SYM ALWAYS_SYM {}
+ ;
+
+vcol_opt_specifier:
+ /* empty */
+ {
+ Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ }
+ | VIRTUAL_SYM
+ {
+ Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ }
+ | PERSISTENT_SYM
+ {
+ Lex->vcol_info->set_stored_in_db_flag(TRUE);
+ }
+ ;
+
+vcol_opt_attribute:
+ /* empty */ {}
+ | vcol_opt_attribute_list {}
+ ;
+
+vcol_opt_attribute_list:
+ vcol_opt_attribute_list vcol_attribute {}
+ | vcol_attribute
+ ;
+
+vcol_attribute:
+ UNIQUE_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= UNIQUE_FLAG;
+ lex->alter_info.flags|= ALTER_ADD_INDEX;
+ }
+ | UNIQUE_SYM KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= UNIQUE_KEY_FLAG;
+ lex->alter_info.flags|= ALTER_ADD_INDEX;
+ }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
+ ;
+
+parse_vcol_expr:
+ PARSE_VCOL_EXPR_SYM '(' virtual_column_func ')'
+ {
+ /*
+ "PARSE_VCOL_EXPR" can only be used by the SQL server
+ when reading a '*.frm' file.
+ Prevent the end user from invoking this command.
+ */
+ if (!Lex->parse_vcol_expr)
+ {
+ my_message(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+virtual_column_func:
+ remember_name expr remember_end
+ {
+ Lex->vcol_info= new Virtual_column_info();
+ if (!Lex->vcol_info)
+ {
+ mem_alloc_error(sizeof(Virtual_column_info));
+ MYSQL_YYABORT;
+ }
+ uint expr_len= (uint)($3 - $1) - 1;
+ Lex->vcol_info->expr_str.str= (char* ) sql_memdup($1 + 1, expr_len);
+ Lex->vcol_info->expr_str.length= expr_len;
+ Lex->vcol_info->expr_item= $2;
+ }
+ ;
+
type:
int_type opt_field_length field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
@@ -5871,8 +5971,9 @@ alter_list_item:
lex->comment=null_lex_str;
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->vcol_info= 0;
}
- type opt_attribute
+ field_def
{
LEX *lex=Lex;
if (add_field_to_list(lex->thd,&$3,
@@ -5881,7 +5982,8 @@ alter_list_item:
lex->default_value, lex->on_update_value,
&lex->comment,
$3.str, &lex->interval_list, lex->charset,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info))
MYSQL_YYABORT;
}
opt_place
@@ -9101,7 +9203,8 @@ procedure_clause:
MYSQL_YYABORT;
}
- if (&lex->select_lex != lex->current_select)
+ if (&lex->select_lex != lex->current_select ||
+ lex->select_lex.get_table_list()->derived)
{
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
MYSQL_YYABORT;
@@ -11473,6 +11576,7 @@ keyword_sp:
| AGAINST {}
| AGGREGATE_SYM {}
| ALGORITHM_SYM {}
+ | ALWAYS_SYM {}
| ANY_SYM {}
| AT_SYM {}
| AUTHORS_SYM {}
@@ -11543,6 +11647,7 @@ keyword_sp:
| FIRST_SYM {}
| FIXED_SYM {}
| FRAC_SECOND_SYM {}
+ | GENERATED_SYM {}
| GEOMETRY_SYM {}
| GEOMETRYCOLLECTION {}
| GET_FORMAT {}
@@ -11631,6 +11736,7 @@ keyword_sp:
| PARTITIONING_SYM {}
| PARTITIONS_SYM {}
| PASSWORD {}
+ | PERSISTENT_SYM {}
| PHASE_SYM {}
| PLUGIN_SYM {}
| PLUGINS_SYM {}
@@ -11726,6 +11832,7 @@ keyword_sp:
| USE_FRM {}
| VARIABLES {}
| VIEW_SYM {}
+ | VIRTUAL_SYM {}
| VALUE_SYM {}
| WARNINGS {}
| WAIT_SYM {}
@@ -13386,6 +13493,7 @@ sf_tail:
lex->length= lex->dec= NULL;
lex->interval_list.empty();
lex->type= 0;
+ lex->vcol_info= 0;
}
type /* $11 */
{ /* $12 */
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2009-10-19 17:14:48 +0000
+++ b/sql/table.cc 2009-11-12 04:31:28 +0000
@@ -33,6 +33,12 @@ LEX_STRING GENERAL_LOG_NAME= {C_STRING_W
/* SLOW_LOG name */
LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
+/*
+ Keyword added as a prefix when parsing the defining expression for a
+ virtual column read from the column definition saved in the frm file
+*/
+LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
+
/* Functions defined in this file */
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
@@ -663,10 +669,11 @@ static int open_binary_frm(THD *thd, TAB
uint interval_count, interval_parts, read_length, int_length;
uint db_create_options, keys, key_parts, n_length;
uint key_info_length, com_length, null_bit_pos;
+ uint vcol_screen_length;
uint extra_rec_buf_length;
uint i,j;
bool use_hash;
- char *keynames, *names, *comment_pos;
+ char *keynames, *names, *comment_pos, *vcol_screen_pos;
uchar *record;
uchar *disk_buff, *strpos, *null_flags, *null_pos;
ulong pos, record_offset, *rec_per_key, rec_buff_length;
@@ -836,6 +843,7 @@ static int open_binary_frm(THD *thd, TAB
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
share->reclength = uint2korr((head+16));
+ share->stored_rec_length= share->reclength;
if (*(head+26) == 1)
share->system= 1; /* one-record-database */
#ifdef HAVE_CRYPTED_FRM
@@ -914,6 +922,15 @@ static int open_binary_frm(THD *thd, TAB
we unlock the old value of share->db_plugin before
replacing it with a globally locked version of tmp_plugin
*/
+ /* Check if the partitioning engine is ready */
+ if (!plugin_is_ready(&name, MYSQL_STORAGE_ENGINE_PLUGIN))
+ {
+ error= 8;
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition");
+ my_free(buff, MYF(0));
+ goto err;
+ }
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
@@ -1040,24 +1057,28 @@ static int open_binary_frm(THD *thd, TAB
int_length= uint2korr(head+274);
share->null_fields= uint2korr(head+282);
com_length= uint2korr(head+284);
+ vcol_screen_length= uint2korr(head+286);
+ share->vfields= 0;
+ share->stored_fields= share->fields;
share->comment.length= (int) (head[46]);
share->comment.str= strmake_root(&share->mem_root, (char*) head+47,
share->comment.length);
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length));
-
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
if (!(field_ptr = (Field **)
alloc_root(&share->mem_root,
(uint) ((share->fields+1)*sizeof(Field*)+
interval_count*sizeof(TYPELIB)+
(share->fields+interval_parts+
keys+3)*sizeof(char *)+
- (n_length+int_length+com_length)))))
+ (n_length+int_length+com_length+
+ vcol_screen_length)))))
goto err; /* purecov: inspected */
share->field= field_ptr;
read_length=(uint) (share->fields * field_pack_length +
- pos+ (uint) (n_length+int_length+com_length));
+ pos+ (uint) (n_length+int_length+com_length+
+ vcol_screen_length));
if (read_string(file,(uchar**) &disk_buff,read_length))
goto err; /* purecov: inspected */
#ifdef HAVE_CRYPTED_FRM
@@ -1078,7 +1099,11 @@ static int open_binary_frm(THD *thd, TAB
memcpy((char*) names, strpos+(share->fields*field_pack_length),
(uint) (n_length+int_length));
comment_pos= names+(n_length+int_length);
- memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
+ memcpy(comment_pos, disk_buff+read_length-com_length-vcol_screen_length,
+ com_length);
+ vcol_screen_pos= names+(n_length+int_length+com_length);
+ memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
+ vcol_screen_length);
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
if (share->fieldnames.count != share->fields)
@@ -1146,10 +1171,14 @@ static int open_binary_frm(THD *thd, TAB
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;
LEX_STRING comment;
+ Virtual_column_info *vcol_info= 0;
+ bool fld_stored_in_db= TRUE;
if (new_frm_ver >= 3)
{
@@ -1184,6 +1213,18 @@ static int open_binary_frm(THD *thd, TAB
goto err;
}
}
+
+ if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ {
+ DBUG_ASSERT(interval_nr); // Expect non-null expression
+ /*
+ 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)
{
comment.str= (char*) "";
@@ -1195,6 +1236,34 @@ static int open_binary_frm(THD *thd, TAB
comment.length= comment_length;
comment_pos+= comment_length;
}
+
+ if (vcol_info_length)
+ {
+ /*
+ Get virtual column data stored in the .frm file as follows:
+ byte 1 = 1 (always 1 to allow for future extensions)
+ byte 2 = sql_type
+ byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
+ byte 4-... = virtual column expression (text data)
+ */
+ vcol_info= new Virtual_column_info();
+ if ((uint)vcol_screen_pos[0] != 1)
+ {
+ error= 4;
+ goto err;
+ }
+ field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
+ fld_stored_in_db= (bool) (uint) vcol_screen_pos[2];
+ vcol_expr_length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE;
+ if (!(vcol_info->expr_str.str=
+ (char *)memdup_root(&share->mem_root,
+ vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE,
+ vcol_expr_length)))
+ goto err;
+ vcol_info->expr_str.length= vcol_expr_length;
+ vcol_screen_pos+= vcol_info_length;
+ share->vfields++;
+ }
}
else
{
@@ -1285,6 +1354,8 @@ static int open_binary_frm(THD *thd, TAB
reg_field->field_index= i;
reg_field->comment=comment;
+ reg_field->vcol_info= vcol_info;
+ reg_field->stored_in_db= fld_stored_in_db;
if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
{
if ((null_bit_pos+= field_length & 7) > 7)
@@ -1309,8 +1380,17 @@ static int open_binary_frm(THD *thd, TAB
if (use_hash)
(void) my_hash_insert(&share->name_hash,
(uchar*) field_ptr); // never fail
+ if (!reg_field->stored_in_db)
+ {
+ share->stored_fields--;
+ if (share->stored_rec_length>=recpos)
+ share->stored_rec_length= recpos-1;
+ }
}
*field_ptr=0; // End marker
+ /* Sanity checks: */
+ DBUG_ASSERT(share->fields>=share->stored_fields);
+ DBUG_ASSERT(share->reclength>=share->stored_rec_length);
/* Fix key->name and key_part->field */
if (key_parts)
@@ -1610,6 +1690,297 @@ static int open_binary_frm(THD *thd, TAB
DBUG_RETURN(error);
} /* open_binary_frm */
+/*
+ @brief
+ Clear GET_FIXED_FIELDS_FLAG in all fields of a table
+
+ @param
+ table The table for whose fields the flags are to be cleared
+
+ @note
+ This routine is used for error handling purposes.
+
+ @return
+ none
+*/
+
+static void clear_field_flag(TABLE *table)
+{
+ Field **ptr;
+ DBUG_ENTER("clear_field_flag");
+
+ for (ptr= table->field; *ptr; ptr++)
+ (*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ @brief
+ Perform semantic analysis of the defining expression for a virtual column
+
+ @param
+ thd The thread object
+ @param
+ table The table containing the virtual column
+ @param
+ vcol_field The virtual field whose defining expression is to be analyzed
+
+ @details
+ The function performs semantic analysis of the defining expression for
+ the virtual column vcol_field. The expression is used to compute the
+ values of this column.
+
+ @note
+ The function exploits the fact that the fix_fields method sets the flag
+ GET_FIXED_FIELDS_FLAG for all fields in the item tree.
+ This flag must always be unset before returning from this function
+ since it is used for other purposes as well.
+
+ @retval
+ TRUE An error occurred, something was wrong with the function
+ @retval
+ FALSE Otherwise
+*/
+
+bool fix_vcol_expr(THD *thd,
+ TABLE *table,
+ Field *vcol_field)
+{
+ Virtual_column_info *vcol_info= vcol_field->vcol_info;
+ Item* func_expr= vcol_info->expr_item;
+ uint dir_length, home_dir_length;
+ bool result= TRUE;
+ TABLE_LIST tables;
+ TABLE_LIST *save_table_list, *save_first_table, *save_last_table;
+ int error;
+ Name_resolution_context *context;
+ const char *save_where;
+ char* db_name;
+ char db_name_string[FN_REFLEN];
+ bool save_use_only_table_context;
+ Field **ptr, *field;
+ enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
+ DBUG_ASSERT(func_expr);
+ DBUG_ENTER("fix_vcol_expr");
+
+ /*
+ Set-up the TABLE_LIST object to be a list with a single table
+ Set the object to zero to create NULL pointers and set alias
+ and real name to table name and get database name from file name.
+ */
+
+ bzero((void*)&tables, sizeof(TABLE_LIST));
+ tables.alias= tables.table_name= (char*) table->s->table_name.str;
+ tables.table= table;
+ tables.next_local= 0;
+ tables.next_name_resolution_table= 0;
+ strmov(db_name_string, table->s->normalized_path.str);
+ dir_length= dirname_length(db_name_string);
+ db_name_string[dir_length - 1]= 0;
+ home_dir_length= dirname_length(db_name_string);
+ db_name= &db_name_string[home_dir_length];
+ tables.db= db_name;
+
+ thd->mark_used_columns= MARK_COLUMNS_NONE;
+
+ context= thd->lex->current_context();
+ table->map= 1; //To ensure correct calculation of const item
+ table->get_fields_in_item_tree= TRUE;
+ save_table_list= context->table_list;
+ save_first_table= context->first_name_resolution_table;
+ save_last_table= context->last_name_resolution_table;
+ context->table_list= &tables;
+ context->first_name_resolution_table= &tables;
+ context->last_name_resolution_table= NULL;
+ func_expr->walk(&Item::change_context_processor, 0, (uchar*) context);
+ save_where= thd->where;
+ thd->where= "virtual column function";
+
+ /* Save the context before fixing the fields*/
+ save_use_only_table_context= thd->lex->use_only_table_context;
+ thd->lex->use_only_table_context= TRUE;
+ /* Fix fields referenced to by the virtual column function */
+ error= func_expr->fix_fields(thd, (Item**)0);
+ /* Restore the original context*/
+ thd->lex->use_only_table_context= save_use_only_table_context;
+ context->table_list= save_table_list;
+ context->first_name_resolution_table= save_first_table;
+ context->last_name_resolution_table= save_last_table;
+
+ if (unlikely(error))
+ {
+ DBUG_PRINT("info",
+ ("Field in virtual column expression does not belong to the table"));
+ goto end;
+ }
+ thd->where= save_where;
+#ifdef PARANOID
+ /*
+ Walk through the Item tree checking if all items are valid
+ to be part of the virtual column
+ */
+ error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
+ if (error)
+ {
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
+ goto end;
+ }
+#endif
+ if (unlikely(func_expr->const_item()))
+ {
+ my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
+ goto end;
+ }
+ /* Ensure that this virtual column is not based on another virtual field. */
+ ptr= table->field;
+ while ((field= *(ptr++)))
+ {
+ if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
+ (field->vcol_info))
+ {
+ my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
+ goto end;
+ }
+ }
+ result= FALSE;
+
+end:
+
+ /* Clear GET_FIXED_FIELDS_FLAG for the fields of the table */
+ clear_field_flag(table);
+
+ table->get_fields_in_item_tree= FALSE;
+ thd->mark_used_columns= save_mark_used_columns;
+ table->map= 0; //Restore old value
+
+ DBUG_RETURN(result);
+}
+
+/*
+ @brief
+ Unpack the definition of a virtual column from its linear representation
+
+ @parm
+ thd The thread object
+ @param
+ table The table containing the virtual column
+ @param
+ field The field for the virtual
+ @param
+ vcol_expr The string representation of the defining expression
+ @param[out]
+ error_reported The flag to inform the caller that no other error
+ messages are to be generated
+
+ @details
+ The function takes string representation 'vcol_expr' of the defining
+ expression for the virtual field 'field' of the table 'table' and
+ parses it, building an item object for it. The pointer to this item is
+ placed into in field->vcol_info.expr_item. After this the function performs
+ semantic analysis of the item by calling the the function fix_vcol_expr.
+ Since the defining expression is part of the table definition the item
+ for it is created in table->memroot within a separate Query_arena.
+ The free_list of this arena is saved in field->vcol_info.item_free_list
+ to be freed when the table defition is removed from the TABLE_SHARE cache.
+
+ @note
+ Before passing 'vcol_expr" to the parser the function embraces it in
+ parenthesis and prepands it a special keyword.
+
+ @retval
+ FALSE If a success
+ @retval
+ TRUE Otherwise
+*/
+bool unpack_vcol_info_from_frm(THD *thd,
+ TABLE *table,
+ Field *field,
+ LEX_STRING *vcol_expr,
+ bool *error_reported)
+{
+ bool rc= FALSE;
+ DBUG_ENTER("unpack_vcol_info_from_frm");
+ DBUG_ASSERT(vcol_expr);
+
+ /*
+ Step 1: Construct the input string for the parser.
+ The string to be parsed has to be of the following format:
+ "PARSE_VCOL_EXPR (<expr_string_from_frm>)".
+ */
+ char *vcol_expr_str;
+ int str_len= 0;
+ CHARSET_INFO *old_character_set_client;
+
+ if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
+ vcol_expr->length +
+ parse_vcol_keyword.length + 3)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ memcpy(vcol_expr_str,
+ (char*) parse_vcol_keyword.str,
+ parse_vcol_keyword.length);
+ str_len= parse_vcol_keyword.length;
+ memcpy(vcol_expr_str + str_len, "(", 1);
+ str_len++;
+ memcpy(vcol_expr_str + str_len,
+ (char*) vcol_expr->str,
+ vcol_expr->length);
+ str_len+= vcol_expr->length;
+ memcpy(vcol_expr_str + str_len, ")", 1);
+ str_len++;
+ memcpy(vcol_expr_str + str_len, "\0", 1);
+ str_len++;
+ Parser_state parser_state(thd, vcol_expr_str, str_len);
+
+ /*
+ Step 2: Setup thd for parsing.
+ */
+ Query_arena *backup_stmt_arena_ptr= thd->stmt_arena;
+ Query_arena backup_arena;
+ Query_arena vcol_arena(&table->mem_root, Query_arena::INITIALIZED);
+ thd->set_n_backup_active_arena(&vcol_arena, &backup_arena);
+ thd->stmt_arena= &vcol_arena;
+
+ thd->lex->parse_vcol_expr= TRUE;
+ old_character_set_client= thd->variables.character_set_client;
+
+ /*
+ Step 3: Use the parser to build an Item object from vcol_expr_str.
+ */
+ if (parse_sql(thd, &parser_state, NULL))
+ {
+ goto err;
+ }
+ /* From now on use vcol_info generated by the parser. */
+ field->vcol_info= thd->lex->vcol_info;
+
+ /* Validate the Item tree. */
+ if (fix_vcol_expr(thd, table, field))
+ {
+ *error_reported= TRUE;
+ field->vcol_info= 0;
+ goto err;
+ }
+ field->vcol_info->item_free_list= thd->free_list;
+ goto end;
+
+err:
+ rc= TRUE;
+ thd->lex->parse_vcol_expr= FALSE;
+ thd->free_items();
+end:
+ thd->stmt_arena= backup_stmt_arena_ptr;
+ thd->restore_active_arena(&vcol_arena, &backup_arena);
+ thd->variables.character_set_client= old_character_set_client;
+
+ DBUG_RETURN(rc);
+}
+
+/*
+ Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
+*/
/*
Open a table based on a TABLE_SHARE
@@ -1644,7 +2015,7 @@ int open_table_from_share(THD *thd, TABL
uint records, i, bitmap_size;
bool error_reported= FALSE;
uchar *record, *bitmaps;
- Field **field_ptr;
+ Field **field_ptr, **vfield_ptr;
DBUG_ENTER("open_table_from_share");
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
share->table_name.str, (long) outparam));
@@ -1798,6 +2169,34 @@ int open_table_from_share(THD *thd, TABL
}
}
+ /*
+ Process virtual columns, if any.
+ */
+ if (!(vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
+ (uint) ((share->vfields+1)*
+ sizeof(Field*)))))
+ goto err;
+
+ outparam->vfield= vfield_ptr;
+
+ for (field_ptr= outparam->field; *field_ptr; field_ptr++)
+ {
+ if ((*field_ptr)->vcol_info)
+ {
+ if (unpack_vcol_info_from_frm(thd,
+ outparam,
+ *field_ptr,
+ &(*field_ptr)->vcol_info->expr_str,
+ &error_reported))
+ {
+ error= 4; // in case no error is reported
+ goto err;
+ }
+ *(vfield_ptr++)= *field_ptr;
+ }
+ }
+ *vfield_ptr= 0; // End marker
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (share->partition_info_len && outparam->file)
{
@@ -1865,10 +2264,24 @@ partititon_err:
}
#endif
+ /* Check virtual columns against table's storage engine. */
+ if (share->vfields &&
+ ((outparam->file &&
+ !outparam->file->check_if_supported_virtual_columns()) ||
+ (!outparam->file && share->db_type() &&
+ share->db_type()->db_type == DB_TYPE_CSV_DB))) // Workaround for CSV
+ {
+ my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
+ MYF(0),
+ "Specified storage engine");
+ error_reported= TRUE;
+ goto err;
+ }
+
/* Allocate bitmaps */
bitmap_size= share->column_bitmap_size;
- if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*3)))
+ if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*4)))
goto err;
bitmap_init(&outparam->def_read_set,
(my_bitmap_map*) bitmaps, share->fields, FALSE);
@@ -1876,6 +2289,8 @@ partititon_err:
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE);
bitmap_init(&outparam->tmp_set,
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE);
+ bitmap_init(&outparam->vcol_set,
+ (my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE);
outparam->default_column_bitmaps();
/* The table struct is now initialized; Open the table */
@@ -1979,7 +2394,11 @@ int closefrm(register TABLE *table, bool
if (table->field)
{
for (Field **ptr=table->field ; *ptr ; ptr++)
+ {
+ if ((*ptr)->vcol_info)
+ free_items((*ptr)->vcol_info->item_free_list);
delete *ptr;
+ }
table->field= 0;
}
delete table->file;
@@ -4315,6 +4734,7 @@ void st_table::clear_column_bitmaps()
bitmap_clear_all(&table->def_write_set);
*/
bzero((char*) def_read_set.bitmap, s->column_bitmap_size*2);
+ bzero((char*) def_read_set.bitmap, s->column_bitmap_size*4);
column_bitmaps_set(&def_read_set, &def_write_set);
}
@@ -4400,7 +4820,14 @@ void st_table::mark_columns_used_by_inde
KEY_PART_INFO *key_part_end= (key_part +
key_info[index].key_parts);
for (;key_part != key_part_end; key_part++)
+ {
bitmap_set_bit(bitmap, key_part->fieldnr-1);
+ if (key_part->field->vcol_info &&
+ key_part->field->vcol_info->expr_item)
+ key_part->field->vcol_info->
+ expr_item->walk(&Item::register_field_in_bitmap,
+ 1, (uchar *) bitmap);
+ }
}
@@ -4527,6 +4954,8 @@ void st_table::mark_columns_needed_for_u
file->column_bitmaps_signal();
}
}
+ /* Mark all virtual columns needed for update */
+ mark_virtual_columns_for_write();
DBUG_VOID_RETURN;
}
@@ -4553,9 +4982,100 @@ void st_table::mark_columns_needed_for_i
}
if (found_next_number_field)
mark_auto_increment_column();
+ /* Mark virtual columns for insert */
+ mark_virtual_columns_for_write();
+}
+
+
+/*
+ @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 st_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_item;
+ DBUG_ASSERT(vcol_item);
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ }
+ return res;
}
+/*
+ @brief Mark virtual columns for update/insert commands
+
+ @details
+ The function marks virtual columns used in a update/insert commands
+ in the vcol_set bitmap.
+ If a virtual column is from write_set it is always marked in vcol_set.
+ If a stored virtual column is not from write_set but it is computed
+ through columns from write_set it is also marked in vcol_set, and,
+ besides, it is added to write_set.
+
+ @return void
+
+ @note
+ Let table t1 have columns a,b,c and let column c be a stored virtual
+ column computed through columns a and b. Then for the query
+ UPDATE t1 SET a=1
+ column c will be placed into vcol_set and into write_set while
+ column b will be placed into read_set.
+ If column c was a virtual column, but not a stored virtual column
+ then it would not be added to any of the sets. Column b would not
+ be added to read_set either.
+*/
+
+void st_table::mark_virtual_columns_for_write(void)
+{
+ Field **vfield_ptr, *tmp_vfield;
+ bool bitmap_updated= FALSE;
+
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ tmp_vfield= *vfield_ptr;
+ if (bitmap_is_set(write_set, tmp_vfield->field_index))
+ bitmap_updated= mark_virtual_col(tmp_vfield);
+ else if (tmp_vfield->stored_in_db)
+ {
+ MY_BITMAP *save_read_set;
+ Item *vcol_item= tmp_vfield->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ bitmap_clear_all(&tmp_set);
+ save_read_set= read_set;
+ read_set= &tmp_set;
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ read_set= save_read_set;
+ bitmap_intersect(&tmp_set, write_set);
+ if (!bitmap_is_clear_all(&tmp_set))
+ {
+ bitmap_set_bit(write_set, tmp_vfield->field_index);
+ mark_virtual_col(tmp_vfield);
+ bitmap_updated= TRUE;
+ }
+ }
+ }
+ if (bitmap_updated)
+ file->column_bitmaps_signal();
+}
+
/**
@brief Check if this is part of a MERGE table with attached children.
@@ -4563,7 +5083,7 @@ void st_table::mark_columns_needed_for_i
@retval TRUE children are attached
@retval FALSE no MERGE part or children not attached
- @detail
+ @details
A MERGE table consists of a parent TABLE and zero or more child
TABLEs. Each of these TABLEs is called a part of a MERGE table.
*/
@@ -4809,6 +5329,54 @@ size_t max_row_length(TABLE *table, cons
return length;
}
+/*
+ @brief Compute values for virtual columns used in query
+
+ @param table The TABLE object
+ @param for_write Requests to compute only fields needed for write
+
+ @details
+ The function computes the values of the virtual columns of the table and
+ stores them in the table record buffer.
+ Only fields from vcol_set are computed, and, when the flag for_write is not
+ set to TRUE, a virtual field is computed only if it's not stored.
+ The flag for_write is set to TRUE for row insert/update operations.
+
+ @retval
+ 0 Success
+ @retval
+ >0 Error occurred when storing a virtual field value
+*/
+
+int update_virtual_fields(TABLE *table, bool for_write)
+{
+ DBUG_ENTER("update_virtual_fields");
+ Field **vfield_ptr, *vfield;
+ int error= 0;
+ if (!table || !table->vfield)
+ DBUG_RETURN(0);
+
+ /* Iterate over virtual fields in the table */
+ for (vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++)
+ {
+ vfield= (*vfield_ptr);
+ DBUG_ASSERT(vfield->vcol_info && vfield->vcol_info->expr_item);
+ /* Only update those fields that are marked in the vcol_set bitmap */
+ if (bitmap_is_set(&table->vcol_set, vfield->field_index) &&
+ (for_write || !vfield->stored_in_db))
+ {
+ /* Compute the actual value of the virtual fields */
+ error= vfield->vcol_info->expr_item->save_in_field(vfield, 0);
+ DBUG_PRINT("info", ("field '%s' - updated", vfield->field_name));
+ }
+ else
+ {
+ DBUG_PRINT("info", ("field '%s' - skipped", vfield->field_name));
+ }
+ }
+ DBUG_RETURN(0);
+}
+
/*****************************************************************************
** Instansiate templates
*****************************************************************************/
=== modified file 'sql/table.h'
--- a/sql/table.h 2009-10-19 17:14:48 +0000
+++ b/sql/table.h 2009-11-12 04:31:28 +0000
@@ -352,6 +352,8 @@ typedef struct st_table_share
ulong version, mysql_version;
ulong timestamp_offset; /* Set to offset+1 of record */
ulong reclength; /* Recordlength */
+ /* Stored record length. No generated-only virtual fields are included */
+ ulong stored_rec_length;
plugin_ref db_plugin; /* storage engine plugin */
inline handlerton *db_type() const /* table_type for handler */
@@ -372,6 +374,8 @@ typedef struct st_table_share
uint key_block_size; /* create key_block_size, if used */
uint null_bytes, last_null_bit_pos;
uint fields; /* Number of fields */
+ /* Number of stored fields, generated-only virtual fields are not included */
+ uint stored_fields;
uint rec_buff_length; /* Size of table->record[] buffer */
uint keys, key_parts;
uint max_key_length, max_unique_length, total_key_length;
@@ -393,6 +397,7 @@ typedef struct st_table_share
uint error, open_errno, errarg; /* error from open_table_def() */
uint column_bitmap_size;
uchar frm_version;
+ uint vfields; /* Number of computed (virtual) fields */
bool null_field_first;
bool system; /* Set if system table (one record) */
bool crypted; /* If .frm file is crypted */
@@ -657,6 +662,7 @@ struct st_table {
Field *next_number_field; /* Set if next_number is activated */
Field *found_next_number_field; /* Set on open */
Field_timestamp *timestamp_field;
+ Field **vfield; /* Pointer to virtual fields*/
/* Table's triggers, 0 if there are no of them */
Table_triggers_list *triggers;
@@ -666,6 +672,7 @@ struct st_table {
uchar *null_flags;
my_bitmap_map *bitmap_init_value;
MY_BITMAP def_read_set, def_write_set, tmp_set; /* containers */
+ MY_BITMAP vcol_set; /* set of used virtual columns */
MY_BITMAP *read_set, *write_set; /* Active column sets */
/*
The ID of the query that opened and is using this table. Has different
@@ -819,6 +826,8 @@ struct st_table {
void mark_columns_needed_for_update(void);
void mark_columns_needed_for_delete(void);
void mark_columns_needed_for_insert(void);
+ bool mark_virtual_col(Field *field);
+ void mark_virtual_columns_for_write(void);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{
=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc 2009-09-07 20:50:10 +0000
+++ b/sql/unireg.cc 2009-10-16 22:57:48 +0000
@@ -583,7 +583,7 @@ static bool pack_header(uchar *forminfo,
{
uint length,int_count,int_length,no_empty, int_parts;
uint time_stamp_pos,null_fields;
- ulong reclength, totlength, n_length, com_length;
+ ulong reclength, totlength, n_length, com_length, vcol_info_length;
DBUG_ENTER("pack_header");
if (create_fields.elements > MAX_FIELDS)
@@ -594,8 +594,8 @@ static bool pack_header(uchar *forminfo,
totlength= 0L;
reclength= data_offset;
- no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
- com_length=0;
+ no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
+ com_length=vcol_info_length=0;
n_length=2L;
/* Check fields */
@@ -623,6 +623,30 @@ static bool pack_header(uchar *forminfo,
field->field_name, tmp_len);
field->comment.length= tmp_len;
}
+ if (field->vcol_info)
+ {
+ tmp_len=
+ system_charset_info->cset->charpos(system_charset_info,
+ field->vcol_info->expr_str.str,
+ field->vcol_info->expr_str.str +
+ field->vcol_info->expr_str.length,
+ VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
+
+ if (tmp_len < field->vcol_info->expr_str.length)
+ {
+ my_error(ER_WRONG_STRING_LENGTH, MYF(0),
+ field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION",
+ (uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
+ DBUG_RETURN(1);
+ }
+ /*
+ Sum up the length of the expression string and the length of the
+ mandatory header to the total length of info on the defining
+ expressions saved in the frm file for virtual columns.
+ */
+ vcol_info_length+= field->vcol_info->expr_str.length+
+ (uint)FRM_VCOL_HEADER_SIZE;
+ }
totlength+= field->length;
com_length+= field->comment.length;
@@ -642,8 +666,6 @@ static bool pack_header(uchar *forminfo,
!time_stamp_pos)
time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
length=field->pack_length;
- /* Ensure we don't have any bugs when generating offsets */
- DBUG_ASSERT(reclength == field->offset + data_offset);
if ((uint) field->offset+ (uint) data_offset+ length > reclength)
reclength=(uint) (field->offset+ data_offset + length);
n_length+= (ulong) strlen(field->field_name)+1;
@@ -710,7 +732,8 @@ static bool pack_header(uchar *forminfo,
/* Hack to avoid bugs with small static rows in MySQL */
reclength=max(file->min_record_length(table_options),reclength);
if (info_length+(ulong) create_fields.elements*FCOMP+288+
- n_length+int_length+com_length > 65535L || int_count > 255)
+ n_length+int_length+com_length+vcol_info_length > 65535L ||
+ int_count > 255)
{
my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
DBUG_RETURN(1);
@@ -718,7 +741,7 @@ static bool pack_header(uchar *forminfo,
bzero((char*)forminfo,288);
length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
- com_length);
+ com_length+vcol_info_length);
int2store(forminfo,length);
forminfo[256] = (uint8) screens;
int2store(forminfo+258,create_fields.elements);
@@ -735,7 +758,8 @@ static bool pack_header(uchar *forminfo,
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length);
- /* Up to forminfo+288 is free to use for additional information */
+ int2store(forminfo+286,vcol_info_length);
+ /* forminfo+288 is free to use for additional information */
DBUG_RETURN(0);
} /* pack_header */
@@ -774,7 +798,7 @@ static bool pack_fields(File file, List<
ulong data_offset)
{
reg2 uint i;
- uint int_count, comment_length=0;
+ uint int_count, comment_length= 0, vcol_info_length=0;
uchar buff[MAX_FIELD_WIDTH];
Create_field *field;
DBUG_ENTER("pack_fields");
@@ -787,6 +811,7 @@ static bool pack_fields(File file, List<
while ((field=it++))
{
uint recpos;
+ uint cur_vcol_expr_len= 0;
buff[0]= (uchar) field->row;
buff[1]= (uchar) field->col;
buff[2]= (uchar) field->sc_length;
@@ -809,6 +834,17 @@ static bool pack_fields(File file, List<
buff[14]= (uchar) field->charset->number;
else
buff[14]= 0; // Numerical
+ if (field->vcol_info)
+ {
+ /*
+ Use the interval_id place in the .frm file to store the length of
+ the additional data saved for the virtual field
+ */
+ buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length +
+ (uint)FRM_VCOL_HEADER_SIZE;
+ vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE;
+ buff[13]= (uchar) MYSQL_TYPE_VIRTUAL;
+ }
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
@@ -903,6 +939,34 @@ static bool pack_fields(File file, List<
DBUG_RETURN(1);
}
}
+ if (vcol_info_length)
+ {
+ it.rewind();
+ int_count=0;
+ while ((field=it++))
+ {
+ /*
+ Pack each virtual field as follows:
+ byte 1 = 1 (always 1 to allow for future extensions)
+ byte 2 = sql_type
+ byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
+ byte 4-... = virtual column expression (text data)
+ */
+ if (field->vcol_info && field->vcol_info->expr_str.length)
+ {
+ buff[0]= (uchar)1;
+ buff[1]= (uchar) field->sql_type;
+ buff[2]= (uchar) field->stored_in_db;
+ if (my_write(file, buff, 3, MYF_RW))
+ DBUG_RETURN(1);
+ if (my_write(file,
+ (uchar*) field->vcol_info->expr_str.str,
+ field->vcol_info->expr_str.length,
+ MYF_RW))
+ DBUG_RETURN(1);
+ }
+ }
+ }
DBUG_RETURN(0);
}
=== modified file 'sql/unireg.h'
--- a/sql/unireg.h 2009-09-07 20:50:10 +0000
+++ b/sql/unireg.h 2009-10-16 22:57:48 +0000
@@ -212,6 +212,13 @@
#define DEFAULT_KEY_CACHE_NAME "default"
+/* The length of the header part for each virtual column in the .frm file */
+#define FRM_VCOL_HEADER_SIZE 3
+
+/* Maximum length of the defining expression for a virtual columns */
+#define VIRTUAL_COLUMN_EXPRESSION_MAXLEN 255 - FRM_VCOL_HEADER_SIZE
+
+
/* Include prototypes for unireg */
#include "mysqld_error.h"
=== added file 'storage/federated/README'
--- a/storage/federated/README 1970-01-01 00:00:00 +0000
+++ b/storage/federated/README 2009-10-30 18:50:56 +0000
@@ -0,0 +1,7 @@
+The files in this directory are not used by MariaDB
+
+MariaDB uses the new federated storage engine that can be found in the
+federatedx directory.
+
+This directory is only kept around to make it easy to merge code from the
+MySQL source repositories that uses the old and disabled federated code.
=== renamed file 'storage/federated/plug.in' => 'storage/federated/plug.in.disabled'
=== added directory 'storage/federatedx'
=== added file 'storage/federatedx/AUTHORS'
--- a/storage/federatedx/AUTHORS 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/AUTHORS 2009-10-30 18:50:56 +0000
@@ -0,0 +1,11 @@
+FederatedX
+
+Patrick Galbraith <patg(a)patg.net> - Federated
+
+Pluggable Storage Engine Skeleton setup
+
+Brian Aker <brian(a)mysql.com> | <brian(a)tangent.org> - Original Design
+Calvin Sun - Windows Support
+Brian Miezejewski - Bug fixes
+Antony T Curtis - Help in inital development, transactions and various help
+Michael Widenius - Bug fixes and some simple early optimizations
=== added file 'storage/federatedx/CMakeLists.txt'
--- a/storage/federatedx/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/CMakeLists.txt 2009-11-03 14:39:54 +0000
@@ -0,0 +1,3 @@
+INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
+SET(FEDERATEDX_SOURCES ha_federatedx.cc federatedx_txn.cc federatedx_io.cc federatedx_io_null.cc federatedx_io_mysql.cc)
+MYSQL_STORAGE_ENGINE(FEDERATEDX)
=== added file 'storage/federatedx/ChangeLog'
--- a/storage/federatedx/ChangeLog 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ChangeLog 2009-10-30 18:50:56 +0000
@@ -0,0 +1,18 @@
+0.2 - Thu March 8 00:00:00 EST 2008
+
+ - Fixed bug #30051 "CREATE TABLE does not connect and check existence of remote table"
+ Modified "real_connect" to take a share and create flag to in order to not rely
+ on any settings that are later instantiated and/or set by get_share
+ Also, put logic in the code to not attempt this if a localhost. There's an annoying
+ functionality that if federated tries to connect to itself during creater table, you
+ get 1159 error (timeout) - only when local. This prevents having this functionality
+ and is probably part of the reason it was removed.
+
+0.1 - Thu Feb 1 00:00:00 EST 2008
+
+ - This is the FederatedX Storage Engine,
+ first release.
+ - Added documentation
+ - Added simple test and README file to explain
+ how to run the test
+ - Added FAQ
=== added file 'storage/federatedx/FAQ'
--- a/storage/federatedx/FAQ 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/FAQ 2009-10-30 18:50:56 +0000
@@ -0,0 +1,40 @@
+Q. What is the FederatedX pluggable storage engine?
+
+A. It is a fork of the Federated Storage Engine that Brian Aker and I
+(Patrick Galbraith) developed originally . It is a storage engine that
+uses a client connection to a remote MySQL data source as its data
+source instead of a local file on disk.
+
+Q. Why did you fork from Federated?
+
+A. To enhance the storage engine independently of the
+MySQL Server release schedule. Many people have been
+mentioning their dissatisfaction with the limitations
+of Federated. I think the engine is a great concept and
+have a sense of obligation to continue to improve it.
+There are some patches already that are in dire need
+of being applied and tested.
+
+Q. What do you plan to do with FederatedX?
+
+A. Many things need addressing:
+
+- Outstanding bugs
+- How do deal with huge result sets
+- Pushdown conditions (being able to pass things like LIMIT
+ to the remote connection to keep from returning huge
+ result sets).
+- Better transactional support
+- Other connection mechanisms (ODBC, JDBC, native drivers
+ of other RDBMSs)
+
+Q. What FederatedX is and is not?
+
+A. FederatedX is not yet a complete "federated" solution in
+ the sense that other venders have developed (IBM, etc). It
+ is essentially a networked storage engine. It is my hope
+ to make it a real federated solution.
+
+Q. In which MySQL distributions/forks/branches can I find FederateX
+
+A. MariaDB (http://www.mariadb.com)
=== added file 'storage/federatedx/Makefile.am'
--- a/storage/federatedx/Makefile.am 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/Makefile.am 2009-11-01 15:09:55 +0000
@@ -0,0 +1,64 @@
+# Used to build Makefile.in
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+pkgplugindir = $(pkglibdir)/plugin
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir)
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_federatedx.h federatedx_probes.h
+
+EXTRA_LTLIBRARIES = ha_federatedx.la
+pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@
+ha_federatedx_la_LDFLAGS = -module -rpath $(pkgplugindir)
+ha_federatedx_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_federatedx_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_federatedx_la_SOURCES = ha_federatedx.cc
+
+
+EXTRA_LIBRARIES = libfederatedx.a
+noinst_LIBRARIES = @plugin_federated_static_target@
+libfederatedx_a_CXXFLAGS = $(AM_CFLAGS)
+libfederatedx_a_CFLAGS = $(AM_CFLAGS)
+libfederatedx_a_SOURCES= ha_federatedx.cc federatedx_txn.cc \
+ federatedx_io.cc federatedx_io_null.cc \
+ federatedx_io_mysql.cc
+
+EXTRA_DIST = CMakeLists.txt plug.in ha_federatedx.h \
+ federatedx_probes.h
+
+ha_federatedx_la_SOURCES = ha_federatedx.cc federatedx_txn.cc \
+ federatedx_io.cc federatedx_io_null.cc \
+ federatedx_io_mysql.cc $(top_srcdir)/mysys/string.c
+ha_federatedx_la_LIBADD =
+
+#DTRACE = @DTRACE@
+#DTRACEFLAGS = @DTRACEFLAGS@
+#DTRACEFILES = .libs/libfederatedx_engine_la-ha_federatedx.o
+
+# #if HAVE_DTRACE
+# # libfederatedx_engine_la_LIBADD += federatedx_probes.o
+# #endif
+
+# federatedx_probes.h: federatedx_probes.d
+# $(DTRACE) $(DTRACEFLAGS) -h -s federatedx_probes.d
+# mv federatedx_probes.h federatedx_probes.h.bak
+# sed "s/#include <unistd.h>//g" federatedx_probes.h.bak > federatedx_probes.h
+# rm federatedx_probes.h.bak
+
+#federatedx_probes.o:
+# $(DTRACE) $(DTRACEFLAGS) -G -s federatedx_probes.d $(DTRACEFILES)
+
+# End
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
=== added file 'storage/federatedx/README'
--- a/storage/federatedx/README 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/README 2009-10-30 18:50:56 +0000
@@ -0,0 +1,33 @@
+This is the FederatedX Storage Engine, developed as an external storage engine.
+
+NOTE:
+
+The following is only relevant if you use it for MySQL. MariaDB already comes
+with the latest version of FederatedX.
+
+To install, grab a copy of the mysql source code and run this:
+
+./configure --with-mysql=/path/to/src/mysql-5.x --libdir=/usr/local/lib/mysql/
+
+make install
+
+And then inside of MySQL:
+
+mysql> INSTALL PLUGIN federatedx SONAME 'libfederatedx_engine.so';
+
+mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="mysql://root@host/schema/table"
+
+or
+
+mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="server" CHARSET=latin1;
+
+You will probably need to edit the Makefile.am in the src/ tree if you want
+to build on anything other then Linux (and the Makefile assumes that the
+server was not compiled for debug). The reason for the two possible
+configure lines is that libdir is dependent on where MySQL was installed. If
+you run the "INSTALL PLUGIN ..." and you get a file not found, check that
+your configured this directory correctly.
+
+For Solaris you can enable DTrace probes by adding to configure
+--enable-dtrace
+
=== added file 'storage/federatedx/README.windows'
--- a/storage/federatedx/README.windows 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/README.windows 2009-10-30 18:50:56 +0000
@@ -0,0 +1,23 @@
+The following files are changed in order to build a new engine on Windows:
+
+- Update win\configure.js with
+case "WITH_FEDERATEDX_STORAGE_ENGINE":
+to make sure it will pass WITH_FEDERATEDX_STORAGE_ENGINE in.
+
+- Update CMakeFiles.txt under mysql root:
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ ADD_DEFINITIONS(-D WITH_FEDERATEDX_STORAGE_ENGINE)
+ SET (mysql_plugin_defs
+ "${mysql_plugin_defs},builtin_skeleton_plugin")
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
+
+ and,
+
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/skeleton/src)
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
+
+ - Update CMakeFiles.txt under sql:
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld skeleton)
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
=== added file 'storage/federatedx/TODO'
--- a/storage/federatedx/TODO 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/TODO 2009-10-30 18:50:56 +0000
@@ -0,0 +1,30 @@
+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
=== added file 'storage/federatedx/federatedx_io.cc'
--- a/storage/federatedx/federatedx_io.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+typedef federatedx_io *(*instantiate_io_type)(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+struct io_schemes_st
+{
+ const char *scheme;
+ instantiate_io_type instantiate;
+};
+
+
+static const io_schemes_st federated_io_schemes[] =
+{
+ { "mysql", &instantiate_io_mysql },
+ { "null", instantiate_io_null } /* must be last element */
+};
+
+const uint federated_io_schemes_count= array_elements(federated_io_schemes);
+
+federatedx_io::federatedx_io(FEDERATEDX_SERVER *aserver)
+ : server(aserver), owner_ptr(0), txn_next(0), idle_next(0),
+ active(FALSE), busy(FALSE), readonly(TRUE)
+{
+ DBUG_ENTER("federatedx_io::federatedx_io");
+ DBUG_ASSERT(server);
+
+ safe_mutex_assert_owner(&server->mutex);
+ server->io_count++;
+
+ DBUG_VOID_RETURN;
+}
+
+
+federatedx_io::~federatedx_io()
+{
+ DBUG_ENTER("federatedx_io::~federatedx_io");
+
+ server->io_count--;
+
+ DBUG_VOID_RETURN;
+}
+
+
+bool federatedx_io::handles_scheme(const char *scheme)
+{
+ const io_schemes_st *ptr = federated_io_schemes;
+ const io_schemes_st *end = ptr + array_elements(federated_io_schemes);
+ while (ptr != end && strcasecmp(scheme, ptr->scheme))
+ ++ptr;
+ return ptr != end;
+}
+
+
+federatedx_io *federatedx_io::construct(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ const io_schemes_st *ptr = federated_io_schemes;
+ const io_schemes_st *end = ptr + (array_elements(federated_io_schemes) - 1);
+ while (ptr != end && strcasecmp(server->scheme, ptr->scheme))
+ ++ptr;
+ return ptr->instantiate(server_root, server);
+}
+
+
=== added file 'storage/federatedx/federatedx_io_mysql.cc'
--- a/storage/federatedx/federatedx_io_mysql.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io_mysql.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,592 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+#define SAVEPOINT_REALIZED 1
+#define SAVEPOINT_RESTRICT 2
+#define SAVEPOINT_EMITTED 4
+
+
+typedef struct federatedx_savepoint
+{
+ ulong level;
+ uint flags;
+} SAVEPT;
+
+
+class federatedx_io_mysql :public federatedx_io
+{
+ MYSQL mysql; /* MySQL connection */
+ DYNAMIC_ARRAY savepoints;
+ bool requested_autocommit;
+ bool actual_autocommit;
+
+ int actual_query(const char *buffer, uint length);
+ bool test_all_restrict() const;
+public:
+ federatedx_io_mysql(FEDERATEDX_SERVER *);
+ ~federatedx_io_mysql();
+
+ int simple_query(const char *fmt, ...);
+ int query(const char *buffer, uint length);
+ virtual FEDERATEDX_IO_RESULT *store_result();
+
+ virtual size_t max_query_size() const;
+
+ virtual my_ulonglong affected_rows() const;
+ virtual my_ulonglong last_insert_id() const;
+
+ virtual int error_code();
+ virtual const char *error_str();
+
+ void reset();
+ int commit();
+ int rollback();
+
+ int savepoint_set(ulong sp);
+ ulong savepoint_release(ulong sp);
+ ulong savepoint_rollback(ulong sp);
+ void savepoint_restrict(ulong sp);
+
+ ulong last_savepoint() const;
+ ulong actual_savepoint() const;
+ bool is_autocommit() const;
+
+ bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag);
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column);
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const;
+};
+
+
+federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ return new (server_root) federatedx_io_mysql(server);
+}
+
+
+federatedx_io_mysql::federatedx_io_mysql(FEDERATEDX_SERVER *aserver)
+ : federatedx_io(aserver),
+ requested_autocommit(TRUE), actual_autocommit(TRUE)
+{
+ DBUG_ENTER("federatedx_io_mysql::federatedx_io_mysql");
+
+ bzero(&mysql, sizeof(MYSQL));
+ bzero(&savepoints, sizeof(DYNAMIC_ARRAY));
+
+ my_init_dynamic_array(&savepoints, sizeof(SAVEPT), 16, 16);
+
+ DBUG_VOID_RETURN;
+}
+
+
+federatedx_io_mysql::~federatedx_io_mysql()
+{
+ DBUG_ENTER("federatedx_io_mysql::~federatedx_io_mysql");
+
+ mysql_close(&mysql);
+ delete_dynamic(&savepoints);
+
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_io_mysql::reset()
+{
+ reset_dynamic(&savepoints);
+ set_active(FALSE);
+
+ requested_autocommit= TRUE;
+ mysql.reconnect= 1;
+}
+
+
+int federatedx_io_mysql::commit()
+{
+ int error= 0;
+ DBUG_ENTER("federatedx_io_mysql::commit");
+
+ if (!actual_autocommit && (error= actual_query("COMMIT", 6)))
+ rollback();
+
+ reset();
+
+ DBUG_RETURN(error);
+}
+
+int federatedx_io_mysql::rollback()
+{
+ int error= 0;
+ DBUG_ENTER("federatedx_io_mysql::rollback");
+
+ if (!actual_autocommit)
+ error= actual_query("ROLLBACK", 8);
+ else
+ error= ER_WARNING_NOT_COMPLETE_ROLLBACK;
+
+ reset();
+
+ DBUG_RETURN(error);
+}
+
+
+ulong federatedx_io_mysql::last_savepoint() const
+{
+ SAVEPT *savept= NULL;
+ DBUG_ENTER("federatedx_io_mysql::last_savepoint");
+
+ if (savepoints.elements)
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+
+ DBUG_RETURN(savept ? savept->level : 0);
+}
+
+
+ulong federatedx_io_mysql::actual_savepoint() const
+{
+ SAVEPT *savept= NULL;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::last_savepoint");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->flags & SAVEPOINT_REALIZED)
+ break;
+ savept= NULL;
+ }
+
+ DBUG_RETURN(savept ? savept->level : 0);
+}
+
+bool federatedx_io_mysql::is_autocommit() const
+{
+ return actual_autocommit;
+}
+
+
+int federatedx_io_mysql::savepoint_set(ulong sp)
+{
+ int error;
+ SAVEPT savept;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_set");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+ DBUG_ASSERT(sp > last_savepoint());
+
+ savept.level= sp;
+ savept.flags= 0;
+
+ if ((error= insert_dynamic(&savepoints, (uchar*) &savept) ? -1 : 0))
+ goto err;
+
+ set_active(TRUE);
+ mysql.reconnect= 0;
+ requested_autocommit= FALSE;
+
+err:
+ DBUG_RETURN(error);
+}
+
+
+ulong federatedx_io_mysql::savepoint_release(ulong sp)
+{
+ SAVEPT *savept, *last= NULL;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_release");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+
+ while (savepoints.elements)
+ {
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+ if (savept->level < sp)
+ break;
+ if ((savept->flags & (SAVEPOINT_REALIZED |
+ SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED)
+ last= savept;
+ savepoints.elements--;
+ }
+
+ if (last)
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length= my_snprintf(buffer, sizeof(buffer),
+ "RELEASE SAVEPOINT save%lu", last->level);
+ actual_query(buffer, length);
+ }
+
+ DBUG_RETURN(last_savepoint());
+}
+
+
+ulong federatedx_io_mysql::savepoint_rollback(ulong sp)
+{
+ SAVEPT *savept;
+ uint index;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_release");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+
+ while (savepoints.elements)
+ {
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+ if (savept->level <= sp)
+ break;
+ savepoints.elements--;
+ }
+
+ for (index= savepoints.elements, savept= NULL; index;)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->flags & SAVEPOINT_REALIZED)
+ break;
+ savept= NULL;
+ }
+
+ if (savept && !(savept->flags & SAVEPOINT_RESTRICT))
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length= my_snprintf(buffer, sizeof(buffer),
+ "ROLLBACK TO SAVEPOINT save%lu", savept->level);
+ actual_query(buffer, length);
+ }
+
+ DBUG_RETURN(last_savepoint());
+}
+
+
+void federatedx_io_mysql::savepoint_restrict(ulong sp)
+{
+ SAVEPT *savept;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_restrict");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->level > sp)
+ continue;
+ if (savept->level < sp)
+ break;
+ savept->flags|= SAVEPOINT_RESTRICT;
+ break;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+int federatedx_io_mysql::simple_query(const char *fmt, ...)
+{
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length, error;
+ va_list arg;
+ DBUG_ENTER("federatedx_io_mysql::simple_query");
+
+ va_start(arg, fmt);
+ length= my_vsnprintf(buffer, sizeof(buffer), fmt, arg);
+ va_end(arg);
+
+ error= query(buffer, length);
+
+ DBUG_RETURN(error);
+}
+
+
+bool federatedx_io_mysql::test_all_restrict() const
+{
+ bool result= FALSE;
+ SAVEPT *savept;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::test_all_restrict");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if ((savept->flags & (SAVEPOINT_REALIZED |
+ SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED ||
+ (savept->flags & SAVEPOINT_EMITTED))
+ DBUG_RETURN(FALSE);
+ if (savept->flags & SAVEPOINT_RESTRICT)
+ result= TRUE;
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_io_mysql::query(const char *buffer, uint length)
+{
+ int error;
+ bool wants_autocommit= requested_autocommit | is_readonly();
+ DBUG_ENTER("federatedx_io_mysql::query");
+
+ if (!wants_autocommit && test_all_restrict())
+ wants_autocommit= TRUE;
+
+ if (wants_autocommit != actual_autocommit)
+ {
+ if ((error= actual_query(wants_autocommit ? "SET AUTOCOMMIT=1"
+ : "SET AUTOCOMMIT=0", 16)))
+ DBUG_RETURN(error);
+ mysql.reconnect= wants_autocommit ? 1 : 0;
+ actual_autocommit= wants_autocommit;
+ }
+
+ if (!actual_autocommit && last_savepoint() != actual_savepoint())
+ {
+ SAVEPT *savept= dynamic_element(&savepoints, savepoints.elements - 1,
+ SAVEPT *);
+ if (!(savept->flags & SAVEPOINT_RESTRICT))
+ {
+ char buf[STRING_BUFFER_USUAL_SIZE];
+ int len= my_snprintf(buf, sizeof(buf),
+ "SAVEPOINT save%lu", savept->level);
+ if ((error= actual_query(buf, len)))
+ DBUG_RETURN(error);
+ set_active(TRUE);
+ savept->flags|= SAVEPOINT_EMITTED;
+ }
+ savept->flags|= SAVEPOINT_REALIZED;
+ }
+
+ if (!(error= actual_query(buffer, length)))
+ set_active(is_active() || !actual_autocommit);
+
+ DBUG_RETURN(error);
+}
+
+
+int federatedx_io_mysql::actual_query(const char *buffer, uint length)
+{
+ int error;
+ DBUG_ENTER("federatedx_io_mysql::actual_query");
+
+ if (!mysql.master)
+ {
+ if (!(mysql_init(&mysql)))
+ DBUG_RETURN(-1);
+
+ /*
+ BUG# 17044 Federated Storage Engine is not UTF8 clean
+ Add set names to whatever charset the table is at open
+ of table
+ */
+ /* this sets the csname like 'set names utf8' */
+ mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, get_charsetname());
+
+ if (!mysql_real_connect(&mysql,
+ get_hostname(),
+ get_username(),
+ get_password(),
+ get_database(),
+ get_port(),
+ get_socket(), 0))
+ DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
+ mysql.reconnect= 1;
+ }
+
+ error= mysql_real_query(&mysql, buffer, length);
+
+ DBUG_RETURN(error);
+}
+
+size_t federatedx_io_mysql::max_query_size() const
+{
+ return mysql.net.max_packet_size;
+}
+
+
+my_ulonglong federatedx_io_mysql::affected_rows() const
+{
+ return mysql.affected_rows;
+}
+
+
+my_ulonglong federatedx_io_mysql::last_insert_id() const
+{
+ return mysql.last_used_con->insert_id;
+}
+
+
+int federatedx_io_mysql::error_code()
+{
+ return mysql_errno(&mysql);
+}
+
+
+const char *federatedx_io_mysql::error_str()
+{
+ return mysql_error(&mysql);
+}
+
+
+FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result()
+{
+ FEDERATEDX_IO_RESULT *result;
+ DBUG_ENTER("federatedx_io_mysql::store_result");
+
+ result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql);
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_io_mysql::free_result(FEDERATEDX_IO_RESULT *io_result)
+{
+ mysql_free_result((MYSQL_RES *) io_result);
+}
+
+
+unsigned int federatedx_io_mysql::get_num_fields(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_num_fields((MYSQL_RES *) io_result);
+}
+
+
+my_ulonglong federatedx_io_mysql::get_num_rows(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_num_rows((MYSQL_RES *) io_result);
+}
+
+
+FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result)
+{
+ return (FEDERATEDX_IO_ROW *) mysql_fetch_row((MYSQL_RES *) io_result);
+}
+
+
+ulong *federatedx_io_mysql::fetch_lengths(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_fetch_lengths((MYSQL_RES *) io_result);
+}
+
+
+const char *federatedx_io_mysql::get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column)
+{
+ return ((MYSQL_ROW)row)[column];
+}
+
+
+bool federatedx_io_mysql::is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const
+{
+ return !((MYSQL_ROW)row)[column];
+}
+
+bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
+ const char *table_name,
+ uint table_name_length, uint flag)
+{
+ char status_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ FEDERATEDX_IO_RESULT *result= 0;
+ FEDERATEDX_IO_ROW *row;
+ String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin);
+ int error;
+
+ status_query_string.length(0);
+ status_query_string.append(STRING_WITH_LEN("SHOW TABLE STATUS LIKE "));
+ append_ident(&status_query_string, table_name,
+ table_name_length, value_quote_char);
+
+ if (query(status_query_string.ptr(), status_query_string.length()))
+ goto error;
+
+ status_query_string.length(0);
+
+ result= store_result();
+
+ /*
+ We're going to use fields num. 4, 12 and 13 of the resultset,
+ so make sure we have these fields.
+ */
+ if (!result || (get_num_fields(result) < 14))
+ goto error;
+
+ if (!get_num_rows(result))
+ goto error;
+
+ if (!(row= fetch_row(result)))
+ goto error;
+
+ /*
+ deleted is set in ha_federatedx::info
+ */
+ /*
+ need to figure out what this means as far as federatedx is concerned,
+ since we don't have a "file"
+
+ data_file_length = ?
+ index_file_length = ?
+ delete_length = ?
+ */
+ if (!is_column_null(row, 4))
+ stats->records= (ha_rows) my_strtoll10(get_column_data(row, 4),
+ (char**) 0, &error);
+ if (!is_column_null(row, 5))
+ stats->mean_rec_length= (ulong) my_strtoll10(get_column_data(row, 5),
+ (char**) 0, &error);
+
+ stats->data_file_length= stats->records * stats->mean_rec_length;
+
+ if (!is_column_null(row, 12))
+ stats->update_time= (time_t) my_strtoll10(get_column_data(row, 12),
+ (char**) 0, &error);
+ if (!is_column_null(row, 13))
+ stats->check_time= (time_t) my_strtoll10(get_column_data(row, 13),
+ (char**) 0, &error);
+
+ free_result(result);
+ return 0;
+
+error:
+ free_result(result);
+ return 1;
+}
=== added file 'storage/federatedx/federatedx_io_null.cc'
--- a/storage/federatedx/federatedx_io_null.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io_null.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,277 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+#define SAVEPOINT_REALIZED 1
+#define SAVEPOINT_RESTRICT 2
+#define SAVEPOINT_EMITTED 4
+
+
+typedef struct federatedx_savepoint
+{
+ ulong level;
+ uint flags;
+} SAVEPT;
+
+
+class federatedx_io_null :public federatedx_io
+{
+public:
+ federatedx_io_null(FEDERATEDX_SERVER *);
+ ~federatedx_io_null();
+
+ int query(const char *buffer, uint length);
+ virtual FEDERATEDX_IO_RESULT *store_result();
+
+ virtual size_t max_query_size() const;
+
+ virtual my_ulonglong affected_rows() const;
+ virtual my_ulonglong last_insert_id() const;
+
+ virtual int error_code();
+ virtual const char *error_str();
+
+ void reset();
+ int commit();
+ int rollback();
+
+ int savepoint_set(ulong sp);
+ ulong savepoint_release(ulong sp);
+ ulong savepoint_rollback(ulong sp);
+ void savepoint_restrict(ulong sp);
+
+ ulong last_savepoint() const;
+ ulong actual_savepoint() const;
+ bool is_autocommit() const;
+
+ bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag);
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column);
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const;
+};
+
+
+federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ return new (server_root) federatedx_io_null(server);
+}
+
+
+federatedx_io_null::federatedx_io_null(FEDERATEDX_SERVER *aserver)
+ : federatedx_io(aserver)
+{
+}
+
+
+federatedx_io_null::~federatedx_io_null()
+{
+}
+
+
+void federatedx_io_null::reset()
+{
+}
+
+
+int federatedx_io_null::commit()
+{
+ return 0;
+}
+
+int federatedx_io_null::rollback()
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::last_savepoint() const
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::actual_savepoint() const
+{
+ return 0;
+}
+
+bool federatedx_io_null::is_autocommit() const
+{
+ return 0;
+}
+
+
+int federatedx_io_null::savepoint_set(ulong sp)
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::savepoint_release(ulong sp)
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::savepoint_rollback(ulong sp)
+{
+ return 0;
+}
+
+
+void federatedx_io_null::savepoint_restrict(ulong sp)
+{
+}
+
+
+int federatedx_io_null::query(const char *buffer, uint length)
+{
+ return 0;
+}
+
+
+size_t federatedx_io_null::max_query_size() const
+{
+ return INT_MAX;
+}
+
+
+my_ulonglong federatedx_io_null::affected_rows() const
+{
+ return 0;
+}
+
+
+my_ulonglong federatedx_io_null::last_insert_id() const
+{
+ return 0;
+}
+
+
+int federatedx_io_null::error_code()
+{
+ return 0;
+}
+
+
+const char *federatedx_io_null::error_str()
+{
+ return "";
+}
+
+
+FEDERATEDX_IO_RESULT *federatedx_io_null::store_result()
+{
+ FEDERATEDX_IO_RESULT *result;
+ DBUG_ENTER("federatedx_io_null::store_result");
+
+ result= NULL;
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_io_null::free_result(FEDERATEDX_IO_RESULT *)
+{
+}
+
+
+unsigned int federatedx_io_null::get_num_fields(FEDERATEDX_IO_RESULT *)
+{
+ return 0;
+}
+
+
+my_ulonglong federatedx_io_null::get_num_rows(FEDERATEDX_IO_RESULT *)
+{
+ return 0;
+}
+
+
+FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *)
+{
+ return NULL;
+}
+
+
+ulong *federatedx_io_null::fetch_lengths(FEDERATEDX_IO_RESULT *)
+{
+ return NULL;
+}
+
+
+const char *federatedx_io_null::get_column_data(FEDERATEDX_IO_ROW *,
+ unsigned int)
+{
+ return "";
+}
+
+
+bool federatedx_io_null::is_column_null(const FEDERATEDX_IO_ROW *,
+ unsigned int) const
+{
+ return true;
+}
+
+bool federatedx_io_null::table_metadata(ha_statistics *stats,
+ const char *table_name,
+ uint table_name_length, uint flag)
+{
+ stats->records= (ha_rows) 0;
+ stats->mean_rec_length= (ulong) 0;
+ stats->data_file_length= 0;
+
+ stats->update_time= (time_t) 0;
+ stats->check_time= (time_t) 0;
+
+ return 0;
+}
=== added file 'storage/federatedx/federatedx_probes.h'
--- a/storage/federatedx/federatedx_probes.h 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_probes.h 2009-10-30 18:50:56 +0000
@@ -0,0 +1,45 @@
+/*
+ * Generated by dtrace(1M).
+ */
+
+#ifndef _FEDERATED_PROBES_H
+#define _FEDERATED_PROBES_H
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if _DTRACE_VERSION
+
+#define FEDERATED_CLOSE() \
+ __dtrace_federated___close()
+#define FEDERATED_CLOSE_ENABLED() \
+ __dtraceenabled_federated___close()
+#define FEDERATED_OPEN() \
+ __dtrace_federated___open()
+#define FEDERATED_OPEN_ENABLED() \
+ __dtraceenabled_federated___open()
+
+
+extern void __dtrace_federated___close(void);
+extern int __dtraceenabled_federated___close(void);
+extern void __dtrace_federated___open(void);
+extern int __dtraceenabled_federated___open(void);
+
+#else
+
+#define FEDERATED_CLOSE()
+#define FEDERATED_CLOSE_ENABLED() (0)
+#define FEDERATED_OPEN()
+#define FEDERATED_OPEN_ENABLED() (0)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FEDERATED_PROBES_H */
=== added file 'storage/federatedx/federatedx_txn.cc'
--- a/storage/federatedx/federatedx_txn.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_txn.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,424 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+federatedx_txn::federatedx_txn()
+ : txn_list(0), savepoint_level(0), savepoint_stmt(0), savepoint_next(0)
+{
+ DBUG_ENTER("federatedx_txn::federatedx_txn");
+ DBUG_VOID_RETURN;
+}
+
+federatedx_txn::~federatedx_txn()
+{
+ DBUG_ENTER("federatedx_txn::~federatedx_txn");
+ DBUG_ASSERT(!txn_list);
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_txn::close(FEDERATEDX_SERVER *server)
+{
+ uint count= 0;
+ federatedx_io *io, **iop;
+ DBUG_ENTER("federatedx_txn::close");
+
+ DBUG_ASSERT(!server->use_count);
+ DBUG_PRINT("info",("use count: %u connections: %u",
+ server->use_count, server->io_count));
+
+ for (iop= &txn_list; (io= *iop);)
+ {
+ if (io->server != server)
+ iop= &io->txn_next;
+ else
+ {
+ *iop= io->txn_next;
+ io->txn_next= NULL;
+ io->busy= FALSE;
+
+ io->idle_next= server->idle_list;
+ server->idle_list= io;
+ }
+ }
+
+ while ((io= server->idle_list))
+ {
+ server->idle_list= io->idle_next;
+ delete io;
+ count++;
+ }
+
+ DBUG_PRINT("info",("closed %u connections, txn_list: %s", count,
+ txn_list ? "active": "empty"));
+ DBUG_VOID_RETURN;
+}
+
+
+int federatedx_txn::acquire(FEDERATEDX_SHARE *share, bool readonly,
+ federatedx_io **ioptr)
+{
+ federatedx_io *io;
+ FEDERATEDX_SERVER *server= share->s;
+ DBUG_ENTER("federatedx_txn::acquire");
+ DBUG_ASSERT(ioptr && server);
+
+ if (!(io= *ioptr))
+ {
+ /* check to see if we have an available IO connection */
+ for (io= txn_list; io; io= io->txn_next)
+ if (io->server == server)
+ break;
+
+ if (!io)
+ {
+ /* check to see if there are any unowned IO connections */
+ pthread_mutex_lock(&server->mutex);
+ if ((io= server->idle_list))
+ {
+ server->idle_list= io->idle_next;
+ io->idle_next= NULL;
+ }
+ else
+ io= federatedx_io::construct(&server->mem_root, server);
+
+ io->txn_next= txn_list;
+ txn_list= io;
+
+ pthread_mutex_unlock(&server->mutex);
+ }
+
+ if (io->busy)
+ *io->owner_ptr= NULL;
+
+ io->busy= TRUE;
+ io->owner_ptr= ioptr;
+ }
+
+ DBUG_ASSERT(io->busy && io->server == server);
+
+ io->readonly&= readonly;
+
+ DBUG_RETURN((*ioptr= io) ? 0 : -1);
+}
+
+
+void federatedx_txn::release(federatedx_io **ioptr)
+{
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::release");
+ DBUG_ASSERT(ioptr);
+
+ if ((io= *ioptr))
+ {
+ /* mark as available for reuse in this transaction */
+ io->busy= FALSE;
+ *ioptr= NULL;
+
+ DBUG_PRINT("info", ("active: %d autocommit: %d",
+ io->active, io->is_autocommit()));
+
+ if (io->is_autocommit())
+ io->active= FALSE;
+ }
+
+ release_scan();
+
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_txn::release_scan()
+{
+ uint count= 0, returned= 0;
+ federatedx_io *io, **pio;
+ DBUG_ENTER("federatedx_txn::release_scan");
+
+ /* return any inactive and idle connections to the server */
+ for (pio= &txn_list; (io= *pio); count++)
+ {
+ if (io->active || io->busy)
+ pio= &io->txn_next;
+ else
+ {
+ FEDERATEDX_SERVER *server= io->server;
+
+ /* unlink from list of connections bound to the transaction */
+ *pio= io->txn_next;
+ io->txn_next= NULL;
+
+ /* reset some values */
+ io->readonly= TRUE;
+
+ pthread_mutex_lock(&server->mutex);
+ io->idle_next= server->idle_list;
+ server->idle_list= io;
+ pthread_mutex_unlock(&server->mutex);
+ returned++;
+ }
+ }
+ DBUG_PRINT("info",("returned %u of %u connections(s)", returned, count));
+
+ DBUG_VOID_RETURN;
+}
+
+
+bool federatedx_txn::txn_begin()
+{
+ ulong level= 0;
+ DBUG_ENTER("federatedx_txn::txn_begin");
+
+ if (savepoint_next == 0)
+ {
+ savepoint_next++;
+ savepoint_level= savepoint_stmt= 0;
+ sp_acquire(&level);
+ }
+
+ DBUG_RETURN(level == 1);
+}
+
+
+int federatedx_txn::txn_commit()
+{
+ int error= 0;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::txn_commit");
+
+ if (savepoint_next)
+ {
+ DBUG_ASSERT(savepoint_stmt != 1);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ int rc= 0;
+
+ if (io->active)
+ rc= io->commit();
+ else
+ io->rollback();
+
+ if (io->active && rc)
+ error= -1;
+
+ io->reset();
+ }
+
+ release_scan();
+
+ savepoint_next= savepoint_stmt= savepoint_level= 0;
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int federatedx_txn::txn_rollback()
+{
+ int error= 0;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::txn_commit");
+
+ if (savepoint_next)
+ {
+ DBUG_ASSERT(savepoint_stmt != 1);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ int rc= io->rollback();
+
+ if (io->active && rc)
+ error= -1;
+
+ io->reset();
+ }
+
+ release_scan();
+
+ savepoint_next= savepoint_stmt= savepoint_level= 0;
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+bool federatedx_txn::sp_acquire(ulong *sp)
+{
+ bool rc= FALSE;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_acquire");
+ DBUG_ASSERT(sp && savepoint_next);
+
+ *sp= savepoint_level= savepoint_next++;
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ io->savepoint_set(savepoint_level);
+ rc= TRUE;
+ }
+
+ DBUG_RETURN(rc);
+}
+
+
+int federatedx_txn::sp_rollback(ulong *sp)
+{
+ ulong level, new_level= savepoint_level;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_rollback");
+ DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ if ((level= io->savepoint_rollback(*sp)) < new_level)
+ new_level= level;
+ }
+
+ savepoint_level= new_level;
+
+ DBUG_RETURN(0);
+}
+
+
+int federatedx_txn::sp_release(ulong *sp)
+{
+ ulong level, new_level= savepoint_level;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_release");
+ DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ if ((level= io->savepoint_release(*sp)) < new_level)
+ new_level= level;
+ }
+
+ savepoint_level= new_level;
+ *sp= 0;
+
+ DBUG_RETURN(0);
+}
+
+
+bool federatedx_txn::stmt_begin()
+{
+ bool result= FALSE;
+ DBUG_ENTER("federatedx_txn::stmt_begin");
+
+ if (!savepoint_stmt)
+ {
+ if (!savepoint_next)
+ {
+ savepoint_next++;
+ savepoint_level= savepoint_stmt= 0;
+ }
+ result= sp_acquire(&savepoint_stmt);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_txn::stmt_commit()
+{
+ int result= 0;
+ DBUG_ENTER("federatedx_txn::stmt_commit");
+
+ if (savepoint_stmt == 1)
+ {
+ savepoint_stmt= 0;
+ result= txn_commit();
+ }
+ else
+ if (savepoint_stmt)
+ result= sp_release(&savepoint_stmt);
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_txn::stmt_rollback()
+{
+ int result= 0;
+ DBUG_ENTER("federated:txn::stmt_rollback");
+
+ if (savepoint_stmt == 1)
+ {
+ savepoint_stmt= 0;
+ result= txn_rollback();
+ }
+ else
+ if (savepoint_stmt)
+ {
+ result= sp_rollback(&savepoint_stmt);
+ sp_release(&savepoint_stmt);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_txn::stmt_autocommit()
+{
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::stmt_autocommit");
+
+ for (io= txn_list; savepoint_stmt && io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ io->savepoint_restrict(savepoint_stmt);
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
=== added file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2009-11-03 11:08:09 +0000
@@ -0,0 +1,3493 @@
+/*
+Copyright (c) 2008, Patrick Galbraith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of Patrick Galbraith nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*
+
+ FederatedX Pluggable Storage Engine
+
+ ha_federatedx.cc - FederatedX Pluggable Storage Engine
+ Patrick Galbraith, 2008
+
+ This is a handler which uses a foreign database as the data file, as
+ opposed to a handler like MyISAM, which uses .MYD files locally.
+
+ How this handler works
+ ----------------------------------
+ Normal database files are local and as such: You create a table called
+ 'users', a file such as 'users.MYD' is created. A handler reads, inserts,
+ deletes, updates data in this file. The data is stored in particular format,
+ so to read, that data has to be parsed into fields, to write, fields have to
+ be stored in this format to write to this data file.
+
+ With FederatedX storage engine, there will be no local files
+ for each table's data (such as .MYD). A foreign database will store
+ the data that would normally be in this file. This will necessitate
+ the use of MySQL client API to read, delete, update, insert this
+ data. The data will have to be retrieve via an SQL call "SELECT *
+ FROM users". Then, to read this data, it will have to be retrieved
+ via mysql_fetch_row one row at a time, then converted from the
+ column in this select into the format that the handler expects.
+
+ The create table will simply create the .frm file, and within the
+ "CREATE TABLE" SQL, there SHALL be any of the following :
+
+ connection=scheme://username:password@hostname:port/database/tablename
+ connection=scheme://username@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+
+ - OR -
+
+ As of 5.1 federatedx now allows you to use a non-url
+ format, taking advantage of mysql.servers:
+
+ connection="connection_one"
+ connection="connection_one/table_foo"
+
+ An example would be:
+
+ connection=mysql://username:password@hostname:port/database/tablename
+
+ or, if we had:
+
+ create server 'server_one' foreign data wrapper 'mysql' options
+ (HOST '127.0.0.1',
+ DATABASE 'db1',
+ USER 'root',
+ PASSWORD '',
+ PORT 3306,
+ SOCKET '',
+ OWNER 'root');
+
+ CREATE TABLE federatedx.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(64) NOT NULL default ''
+ )
+ ENGINE="FEDERATEDX" DEFAULT CHARSET=latin1
+ CONNECTION='server_one';
+
+ So, this will have been the equivalent of
+
+ CONNECTION="mysql://root@127.0.0.1:3306/db1/t1"
+
+ Then, we can also change the server to point to a new schema:
+
+ ALTER SERVER 'server_one' options(DATABASE 'db2');
+
+ All subsequent calls will now be against db2.t1! Guess what? You don't
+ have to perform an alter table!
+
+ This connecton="connection string" is necessary for the handler to be
+ able to connect to the foreign server, either by URL, or by server
+ name.
+
+
+ The basic flow is this:
+
+ SQL calls issues locally ->
+ mysql handler API (data in handler format) ->
+ mysql client API (data converted to SQL calls) ->
+ foreign database -> mysql client API ->
+ convert result sets (if any) to handler format ->
+ handler API -> results or rows affected to local
+
+ What this handler does and doesn't support
+ ------------------------------------------
+ * Tables MUST be created on the foreign server prior to any action on those
+ tables via the handler, first version. IMPORTANT: IF you MUST use the
+ federatedx storage engine type on the REMOTE end, MAKE SURE [ :) ] That
+ the table you connect to IS NOT a table pointing BACK to your ORIGNAL
+ table! You know and have heard the screaching of audio feedback? You
+ know putting two mirror in front of each other how the reflection
+ continues for eternity? Well, need I say more?!
+ * There will not be support for transactions.
+ * There is no way for the handler to know if the foreign database or table
+ has changed. The reason for this is that this database has to work like a
+ data file that would never be written to by anything other than the
+ database. The integrity of the data in the local table could be breached
+ if there was any change to the foreign database.
+ * Support for SELECT, INSERT, UPDATE , DELETE, indexes.
+ * No ALTER TABLE, DROP TABLE or any other Data Definition Language calls.
+ * Prepared statements will not be used in the first implementation, it
+ remains to to be seen whether the limited subset of the client API for the
+ server supports this.
+ * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its
+ implementation.
+ * This will not work with the query cache.
+
+ Method calls
+
+ A two column table, with one record:
+
+ (SELECT)
+
+ "SELECT * FROM foo"
+ ha_federatedx::info
+ ha_federatedx::scan_time:
+ ha_federatedx::rnd_init: share->select_query SELECT * FROM foo
+ ha_federatedx::extra
+
+ <for every row of data retrieved>
+ ha_federatedx::rnd_next
+ ha_federatedx::convert_row_to_internal_format
+ ha_federatedx::rnd_next
+ </for every row of data retrieved>
+
+ ha_federatedx::rnd_end
+ ha_federatedx::extra
+ ha_federatedx::reset
+
+ (INSERT)
+
+ "INSERT INTO foo (id, ts) VALUES (2, now());"
+
+ ha_federatedx::write_row
+
+ ha_federatedx::reset
+
+ (UPDATE)
+
+ "UPDATE foo SET ts = now() WHERE id = 1;"
+
+ ha_federatedx::index_init
+ ha_federatedx::index_read
+ ha_federatedx::index_read_idx
+ ha_federatedx::rnd_next
+ ha_federatedx::convert_row_to_internal_format
+ ha_federatedx::update_row
+
+ ha_federatedx::extra
+ ha_federatedx::extra
+ ha_federatedx::extra
+ ha_federatedx::external_lock
+ ha_federatedx::reset
+
+
+ How do I use this handler?
+ --------------------------
+
+ <insert text about plugin storage engine>
+
+ Next, to use this handler, it's very simple. You must
+ have two databases running, either both on the same host, or
+ on different hosts.
+
+ One the server that will be connecting to the foreign
+ host (client), you create your table as such:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="FEDERATEDX"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:9306/federatedx/test_federatedx';
+
+ Notice the "COMMENT" and "ENGINE" field? This is where you
+ respectively set the engine type, "FEDERATEDX" and foreign
+ host information, this being the database your 'client' database
+ will connect to and use as the "data file". Obviously, the foreign
+ database is running on port 9306, so you want to start up your other
+ database so that it is indeed on port 9306, and your federatedx
+ database on a port other than that. In my setup, I use port 5554
+ for federatedx, and port 5555 for the foreign database.
+
+ Then, on the foreign database:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="<NAME>" <-- whatever you want, or not specify
+ DEFAULT CHARSET=latin1 ;
+
+ This table is exactly the same (and must be exactly the same),
+ except that it is not using the federatedx handler and does
+ not need the URL.
+
+
+ How to see the handler in action
+ --------------------------------
+
+ When developing this handler, I compiled the federatedx database with
+ debugging:
+
+ ./configure --with-federatedx-storage-engine
+ --prefix=/home/mysql/mysql-build/federatedx/ --with-debug
+
+ Once compiled, I did a 'make install' (not for the purpose of installing
+ the binary, but to install all the files the binary expects to see in the
+ diretory I specified in the build with --prefix,
+ "/home/mysql/mysql-build/federatedx".
+
+ Then, I started the foreign server:
+
+ /usr/local/mysql/bin/mysqld_safe
+ --user=mysql --log=/tmp/mysqld.5555.log -P 5555
+
+ Then, I went back to the directory containing the newly compiled mysqld,
+ <builddir>/sql/, started up gdb:
+
+ gdb ./mysqld
+
+ Then, withn the (gdb) prompt:
+ (gdb) run --gdb --port=5554 --socket=/tmp/mysqld.5554 --skip-innodb --debug
+
+ Next, I open several windows for each:
+
+ 1. Tail the debug trace: tail -f /tmp/mysqld.trace|grep ha_fed
+ 2. Tail the SQL calls to the foreign database: tail -f /tmp/mysqld.5555.log
+ 3. A window with a client open to the federatedx server on port 5554
+ 4. A window with a client open to the federatedx server on port 5555
+
+ I would create a table on the client to the foreign server on port
+ 5555, and then to the federatedx server on port 5554. At this point,
+ I would run whatever queries I wanted to on the federatedx server,
+ just always remembering that whatever changes I wanted to make on
+ the table, or if I created new tables, that I would have to do that
+ on the foreign server.
+
+ Another thing to look for is 'show variables' to show you that you have
+ support for federatedx handler support:
+
+ show variables like '%federat%'
+
+ and:
+
+ show storage engines;
+
+ Both should display the federatedx storage handler.
+
+
+ Testing
+ -------
+
+ Testing for FederatedX as a pluggable storage engine for
+ now is a manual process that I intend to build a test
+ suite that works for all pluggable storage engines.
+
+ How to test
+
+ 1. cp fed.dat /tmp
+ (make sure you have access to "test". Use a user that has
+ super privileges for now)
+ 2. mysql -f -u root test < federated.test > federated.myresult 2>&1
+ 3. diff federated.result federated.myresult (there _should_ be no differences)
+
+
+*/
+
+
+#define MYSQL_SERVER 1q
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#include <mysql/plugin.h>
+
+/* Variables for federatedx share methods */
+static HASH federatedx_open_tables; // To track open tables
+static HASH federatedx_open_servers; // To track open servers
+pthread_mutex_t federatedx_mutex; // To init the hash
+const char ident_quote_char= '`'; // Character for quoting
+ // identifiers
+const char value_quote_char= '\''; // Character for quoting
+ // literals
+static const int bulk_padding= 64; // bytes "overhead" in packet
+
+/* Variables used when chopping off trailing characters */
+static const uint sizeof_trailing_comma= sizeof(", ") - 1;
+static const uint sizeof_trailing_closeparen= sizeof(") ") - 1;
+static const uint sizeof_trailing_and= sizeof(" AND ") - 1;
+static const uint sizeof_trailing_where= sizeof(" WHERE ") - 1;
+
+/* Static declaration for handerton */
+static handler *federatedx_create_handler(handlerton *hton,
+ TABLE_SHARE *table,
+ MEM_ROOT *mem_root);
+
+/* FederatedX storage engine handlerton */
+
+static handler *federatedx_create_handler(handlerton *hton,
+ TABLE_SHARE *table,
+ MEM_ROOT *mem_root)
+{
+ return new (mem_root) ha_federatedx(hton, table);
+}
+
+
+/* Function we use in the creation of our hash to get key */
+
+static uchar *
+federatedx_share_get_key(FEDERATEDX_SHARE *share, size_t *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= share->share_key_length;
+ return (uchar*) share->share_key;
+}
+
+
+static uchar *
+federatedx_server_get_key(FEDERATEDX_SERVER *server, size_t *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= server->key_length;
+ return server->key;
+}
+
+
+/*
+ Initialize the federatedx handler.
+
+ SYNOPSIS
+ federatedx_db_init()
+ p Handlerton
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+int federatedx_db_init(void *p)
+{
+ DBUG_ENTER("federatedx_db_init");
+ handlerton *federatedx_hton= (handlerton *)p;
+ federatedx_hton->state= SHOW_OPTION_YES;
+ /* This is no longer needed for plugin storage engines */
+ federatedx_hton->db_type= DB_TYPE_DEFAULT;
+ federatedx_hton->savepoint_offset= sizeof(ulong);
+ federatedx_hton->close_connection= ha_federatedx::disconnect;
+ federatedx_hton->savepoint_set= ha_federatedx::savepoint_set;
+ federatedx_hton->savepoint_rollback= ha_federatedx::savepoint_rollback;
+ federatedx_hton->savepoint_release= ha_federatedx::savepoint_release;
+ federatedx_hton->commit= ha_federatedx::commit;
+ federatedx_hton->rollback= ha_federatedx::rollback;
+ federatedx_hton->create= federatedx_create_handler;
+ federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION;
+
+ if (pthread_mutex_init(&federatedx_mutex, MY_MUTEX_INIT_FAST))
+ goto error;
+ if (!hash_init(&federatedx_open_tables, &my_charset_bin, 32, 0, 0,
+ (hash_get_key) federatedx_share_get_key, 0, 0) &&
+ !hash_init(&federatedx_open_servers, &my_charset_bin, 32, 0, 0,
+ (hash_get_key) federatedx_server_get_key, 0, 0))
+ {
+ DBUG_RETURN(FALSE);
+ }
+
+ VOID(pthread_mutex_destroy(&federatedx_mutex));
+error:
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Release the federatedx handler.
+
+ SYNOPSIS
+ federatedx_db_end()
+
+ RETURN
+ FALSE OK
+*/
+
+int federatedx_done(void *p)
+{
+ hash_free(&federatedx_open_tables);
+ hash_free(&federatedx_open_servers);
+ VOID(pthread_mutex_destroy(&federatedx_mutex));
+
+ return 0;
+}
+
+/**
+ @brief Append identifiers to the string.
+
+ @param[in,out] string The target string.
+ @param[in] name Identifier name
+ @param[in] length Length of identifier name in bytes
+ @param[in] quote_char Quote char to use for quoting identifier.
+
+ @return Operation Status
+ @retval FALSE OK
+ @retval TRUE There was an error appending to the string.
+
+ @note This function is based upon the append_identifier() function
+ in sql_show.cc except that quoting always occurs.
+*/
+
+bool append_ident(String *string, const char *name, uint length,
+ const char quote_char)
+{
+ bool result;
+ uint clen;
+ const char *name_end;
+ DBUG_ENTER("append_ident");
+
+ if (quote_char)
+ {
+ string->reserve(length * 2 + 2);
+ if ((result= string->append("e_char, 1, system_charset_info)))
+ goto err;
+
+ for (name_end= name+length; name < name_end; name+= clen)
+ {
+ uchar c= *(uchar *) name;
+ if (!(clen= my_mbcharlen(system_charset_info, c)))
+ clen= 1;
+ if (clen == 1 && c == (uchar) quote_char &&
+ (result= string->append("e_char, 1, system_charset_info)))
+ goto err;
+ if ((result= string->append(name, clen, string->charset())))
+ goto err;
+ }
+ result= string->append("e_char, 1, system_charset_info);
+ }
+ else
+ result= string->append(name, length, system_charset_info);
+
+err:
+ DBUG_RETURN(result);
+}
+
+
+static int parse_url_error(FEDERATEDX_SHARE *share, TABLE *table, int error_num)
+{
+ char buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ int buf_len;
+ DBUG_ENTER("ha_federatedx parse_url_error");
+
+ buf_len= min(table->s->connect_string.length,
+ FEDERATEDX_QUERY_BUFFER_SIZE-1);
+ strmake(buf, table->s->connect_string.str, buf_len);
+ my_error(error_num, MYF(0), buf);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ retrieve server object which contains server meta-data
+ from the system table given a server's name, set share
+ connection parameter members
+*/
+int get_connection(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share)
+{
+ int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ FOREIGN_SERVER *server, server_buffer;
+ DBUG_ENTER("ha_federatedx::get_connection");
+
+ /*
+ get_server_by_name() clones the server if exists and allocates
+ copies of strings in the supplied mem_root
+ */
+ if (!(server=
+ get_server_by_name(mem_root, share->connection_string, &server_buffer)))
+ {
+ DBUG_PRINT("info", ("get_server_by_name returned > 0 error condition!"));
+ /* need to come up with error handling */
+ error_num=1;
+ goto error;
+ }
+ DBUG_PRINT("info", ("get_server_by_name returned server at %lx",
+ (long unsigned int) server));
+
+ /*
+ Most of these should never be empty strings, error handling will
+ need to be implemented. Also, is this the best way to set the share
+ members? Is there some allocation needed? In running this code, it works
+ except there are errors in the trace file of the share being overrun
+ at the address of the share.
+ */
+ share->server_name_length= server->server_name_length;
+ share->server_name= server->server_name;
+ share->username= server->username;
+ share->password= server->password;
+ share->database= server->db;
+#ifndef I_AM_PARANOID
+ share->port= server->port > 0 && server->port < 65536 ?
+#else
+ share->port= server->port > 1023 && server->port < 65536 ?
+#endif
+ (ushort) server->port : MYSQL_PORT;
+ share->hostname= server->host;
+ if (!(share->socket= server->socket) &&
+ !strcmp(share->hostname, my_localhost))
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ share->scheme= server->scheme;
+
+ DBUG_PRINT("info", ("share->username: %s", share->username));
+ DBUG_PRINT("info", ("share->password: %s", share->password));
+ DBUG_PRINT("info", ("share->hostname: %s", share->hostname));
+ DBUG_PRINT("info", ("share->database: %s", share->database));
+ DBUG_PRINT("info", ("share->port: %d", share->port));
+ DBUG_PRINT("info", ("share->socket: %s", share->socket));
+ DBUG_RETURN(0);
+
+error:
+ my_sprintf(error_buffer,
+ (error_buffer, "server name: '%s' doesn't exist!",
+ share->connection_string));
+ my_error(error_num, MYF(0), error_buffer);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ Parse connection info from table->s->connect_string
+
+ SYNOPSIS
+ parse_url()
+ mem_root MEM_ROOT pointer for memory allocation
+ share pointer to FEDERATEDX share
+ table pointer to current TABLE class
+ table_create_flag determines what error to throw
+
+ DESCRIPTION
+ Populates the share with information about the connection
+ to the foreign database that will serve as the data source.
+ This string must be specified (currently) in the "CONNECTION" field,
+ listed in the CREATE TABLE statement.
+
+ This string MUST be in the format of any of these:
+
+ CONNECTION="scheme://username:password@hostname:port/database/table"
+ CONNECTION="scheme://username@hostname/database/table"
+ CONNECTION="scheme://username@hostname:port/database/table"
+ CONNECTION="scheme://username:password@hostname/database/table"
+
+ _OR_
+
+ CONNECTION="connection name"
+
+
+
+ An Example:
+
+ CREATE TABLE t1 (id int(32))
+ ENGINE="FEDERATEDX"
+ CONNECTION="mysql://joe:joespass@192.168.1.111:9308/federatedx/testtable";
+
+ CREATE TABLE t2 (
+ id int(4) NOT NULL auto_increment,
+ name varchar(32) NOT NULL,
+ PRIMARY KEY(id)
+ ) ENGINE="FEDERATEDX" CONNECTION="my_conn";
+
+ ***IMPORTANT***
+ Currently, the FederatedX Storage Engine only supports connecting to another
+ Database ("scheme" of "mysql"). Connections using JDBC as well as
+ other connectors are in the planning stage.
+
+
+ 'password' and 'port' are both optional.
+
+ RETURN VALUE
+ 0 success
+ error_num particular error code
+
+*/
+
+static int parse_url(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share, TABLE *table,
+ uint table_create_flag)
+{
+ uint error_num= (table_create_flag ?
+ ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE :
+ ER_FOREIGN_DATA_STRING_INVALID);
+ DBUG_ENTER("ha_federatedx::parse_url");
+
+ share->port= 0;
+ share->socket= 0;
+ DBUG_PRINT("info", ("share at %lx", (long unsigned int) share));
+ DBUG_PRINT("info", ("Length: %u", (uint) table->s->connect_string.length));
+ DBUG_PRINT("info", ("String: '%.*s'", (int) table->s->connect_string.length,
+ table->s->connect_string.str));
+ share->connection_string= strmake_root(mem_root, table->s->connect_string.str,
+ table->s->connect_string.length);
+
+ DBUG_PRINT("info",("parse_url alloced share->connection_string %lx",
+ (long unsigned int) share->connection_string));
+
+ DBUG_PRINT("info",("share->connection_string: %s",share->connection_string));
+ /*
+ No :// or @ in connection string. Must be a straight connection name of
+ either "servername" or "servername/tablename"
+ */
+ if ((!strstr(share->connection_string, "://") &&
+ (!strchr(share->connection_string, '@'))))
+ {
+
+ DBUG_PRINT("info",
+ ("share->connection_string: %s internal format "
+ "share->connection_string: %lx",
+ share->connection_string,
+ (ulong) share->connection_string));
+
+ /* ok, so we do a little parsing, but not completely! */
+ share->parsed= FALSE;
+ /*
+ If there is a single '/' in the connection string, this means the user is
+ specifying a table name
+ */
+
+ if ((share->table_name= strchr(share->connection_string, '/')))
+ {
+ *share->table_name++= '\0';
+ share->table_name_length= strlen(share->table_name);
+
+ DBUG_PRINT("info",
+ ("internal format, parsed table_name "
+ "share->connection_string: %s share->table_name: %s",
+ share->connection_string, share->table_name));
+
+ /*
+ there better not be any more '/'s !
+ */
+ if (strchr(share->table_name, '/'))
+ goto error;
+ }
+ /*
+ Otherwise, straight server name, use tablename of federatedx table
+ as remote table name
+ */
+ else
+ {
+ /*
+ Connection specifies everything but, resort to
+ expecting remote and foreign table names to match
+ */
+ share->table_name= strmake_root(mem_root, table->s->table_name.str,
+ (share->table_name_length=
+ table->s->table_name.length));
+ DBUG_PRINT("info",
+ ("internal format, default table_name "
+ "share->connection_string: %s share->table_name: %s",
+ share->connection_string, share->table_name));
+ }
+
+ if ((error_num= get_connection(mem_root, share)))
+ goto error;
+ }
+ else
+ {
+ share->parsed= TRUE;
+ // Add a null for later termination of table name
+ share->connection_string[table->s->connect_string.length]= 0;
+ share->scheme= share->connection_string;
+ DBUG_PRINT("info",("parse_url alloced share->scheme: %lx",
+ (ulong) share->scheme));
+
+ /*
+ Remove addition of null terminator and store length
+ for each string in share
+ */
+ if (!(share->username= strstr(share->scheme, "://")))
+ goto error;
+ share->scheme[share->username - share->scheme]= '\0';
+
+ if (!federatedx_io::handles_scheme(share->scheme))
+ goto error;
+
+ share->username+= 3;
+
+ if (!(share->hostname= strchr(share->username, '@')))
+ goto error;
+ *share->hostname++= '\0'; // End username
+
+ if ((share->password= strchr(share->username, ':')))
+ {
+ *share->password++= '\0'; // End username
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
+ goto error;
+ /*
+ Found that if the string is:
+ user:@hostname:port/db/table
+ Then password is a null string, so set to NULL
+ */
+ if ((share->password[0] == '\0'))
+ share->password= NULL;
+ }
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
+ goto error;
+
+ if (!(share->database= strchr(share->hostname, '/')))
+ goto error;
+ *share->database++= '\0';
+
+ if ((share->sport= strchr(share->hostname, ':')))
+ {
+ *share->sport++= '\0';
+ if (share->sport[0] == '\0')
+ share->sport= NULL;
+ else
+ share->port= atoi(share->sport);
+ }
+
+ if (!(share->table_name= strchr(share->database, '/')))
+ goto error;
+ *share->table_name++= '\0';
+
+ share->table_name_length= strlen(share->table_name);
+
+ /* make sure there's not an extra / */
+ if ((strchr(share->table_name, '/')))
+ goto error;
+
+ if (share->hostname[0] == '\0')
+ share->hostname= NULL;
+
+ }
+ if (!share->port)
+ {
+ if (!share->hostname || strcmp(share->hostname, my_localhost) == 0)
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ else
+ share->port= MYSQL_PORT;
+ }
+
+ DBUG_PRINT("info",
+ ("scheme: %s username: %s password: %s hostname: %s "
+ "port: %d db: %s tablename: %s",
+ share->scheme, share->username, share->password,
+ share->hostname, share->port, share->database,
+ share->table_name));
+
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(parse_url_error(share, table, error_num));
+}
+
+/*****************************************************************************
+** FEDERATEDX tables
+*****************************************************************************/
+
+ha_federatedx::ha_federatedx(handlerton *hton,
+ TABLE_SHARE *table_arg)
+ :handler(hton, table_arg),
+ txn(0), io(0), stored_result(0)
+{
+ bzero(&bulk_insert, sizeof(bulk_insert));
+}
+
+
+/*
+ Convert MySQL result set row to handler internal format
+
+ SYNOPSIS
+ convert_row_to_internal_format()
+ record Byte pointer to record
+ row MySQL result set row from fetchrow()
+ result Result set to use
+
+ DESCRIPTION
+ This method simply iterates through a row returned via fetchrow with
+ values from a successful SELECT , and then stores each column's value
+ in the field object via the field object pointer (pointing to the table's
+ array of field object pointers). This is how the handler needs the data
+ to be stored to then return results back to the user
+
+ RETURN VALUE
+ 0 After fields have had field values stored from record
+*/
+
+uint ha_federatedx::convert_row_to_internal_format(uchar *record,
+ FEDERATEDX_IO_ROW *row,
+ FEDERATEDX_IO_RESULT *result)
+{
+ ulong *lengths;
+ Field **field;
+ int column= 0;
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
+ DBUG_ENTER("ha_federatedx::convert_row_to_internal_format");
+
+ lengths= io->fetch_lengths(result);
+
+ for (field= table->field; *field; field++, column++)
+ {
+ /*
+ index variable to move us through the row at the
+ same iterative step as the field
+ */
+ my_ptrdiff_t old_ptr;
+ old_ptr= (my_ptrdiff_t) (record - table->record[0]);
+ (*field)->move_field_offset(old_ptr);
+ if (io->is_column_null(row, column))
+ (*field)->set_null();
+ else
+ {
+ if (bitmap_is_set(table->read_set, (*field)->field_index))
+ {
+ (*field)->set_notnull();
+ (*field)->store(io->get_column_data(row, column), lengths[column], &my_charset_bin);
+ }
+ }
+ (*field)->move_field_offset(-old_ptr);
+ }
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_name(String *to, KEY_PART_INFO *part)
+{
+ DBUG_ENTER("emit_key_part_name");
+ if (append_ident(to, part->field->field_name,
+ strlen(part->field->field_name), ident_quote_char))
+ DBUG_RETURN(1); // Out of memory
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_element(String *to, KEY_PART_INFO *part,
+ bool needs_quotes, bool is_like,
+ const uchar *ptr, uint len)
+{
+ Field *field= part->field;
+ DBUG_ENTER("emit_key_part_element");
+
+ if (needs_quotes && to->append(STRING_WITH_LEN("'")))
+ DBUG_RETURN(1);
+
+ if (part->type == HA_KEYTYPE_BIT)
+ {
+ char buff[STRING_BUFFER_USUAL_SIZE], *buf= buff;
+
+ *buf++= '0';
+ *buf++= 'x';
+ buf= octet2hex(buf, (char*) ptr, len);
+ if (to->append((char*) buff, (uint)(buf - buff)))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_BLOB_PART)
+ {
+ String blob;
+ uint blob_length= uint2korr(ptr);
+ blob.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ blob_length, &my_charset_bin);
+ if (append_escaped(to, &blob))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ String varchar;
+ uint var_length= uint2korr(ptr);
+ varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ var_length, &my_charset_bin);
+ if (append_escaped(to, &varchar))
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ char strbuff[MAX_FIELD_WIDTH];
+ String str(strbuff, sizeof(strbuff), part->field->charset()), *res;
+
+ res= field->val_str(&str, ptr);
+
+ if (field->result_type() == STRING_RESULT)
+ {
+ if (append_escaped(to, res))
+ DBUG_RETURN(1);
+ }
+ else if (to->append(res->ptr(), res->length()))
+ DBUG_RETURN(1);
+ }
+
+ if (is_like && to->append(STRING_WITH_LEN("%")))
+ DBUG_RETURN(1);
+
+ if (needs_quotes && to->append(STRING_WITH_LEN("'")))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Create a WHERE clause based off of values in keys
+ Note: This code was inspired by key_copy from key.cc
+
+ SYNOPSIS
+ create_where_from_key ()
+ to String object to store WHERE clause
+ key_info KEY struct pointer
+ key byte pointer containing key
+ key_length length of key
+ range_type 0 - no range, 1 - min range, 2 - max range
+ (see enum range_operation)
+
+ DESCRIPTION
+ Using iteration through all the keys via a KEY_PART_INFO pointer,
+ This method 'extracts' the value of each key in the byte pointer
+ *key, and for each key found, constructs an appropriate WHERE clause
+
+ RETURN VALUE
+ 0 After all keys have been accounted for to create the WHERE clause
+ 1 No keys found
+
+ Range flags Table per Timour:
+
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_OR_NEXT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+
+ records_in_range:
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_EXACT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+ * "=" -> HA_READ_AFTER_KEY
+
+0 HA_READ_KEY_EXACT, Find first record else error
+1 HA_READ_KEY_OR_NEXT, Record or next record
+2 HA_READ_KEY_OR_PREV, Record or previous
+3 HA_READ_AFTER_KEY, Find next rec. after key-record
+4 HA_READ_BEFORE_KEY, Find next rec. before key-record
+5 HA_READ_PREFIX, Key which as same prefix
+6 HA_READ_PREFIX_LAST, Last key with the same prefix
+7 HA_READ_PREFIX_LAST_OR_PREV, Last or prev key with the same prefix
+
+Flags that I've found:
+
+id, primary key, varchar
+
+id = 'ccccc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 'ccccc'
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id < 'ccccc'
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 'ccccc'
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id >= 'ccccc'
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id like 'cc%cc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id < 'ccccc'
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 'aaaaa' and id < 'ccccc';
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+numeric keys:
+
+id = 4
+index_read_idx: start_key 0 end_key NULL
+
+id > 4
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4
+full table scan, select * from
+
+id > 2 and id < 8
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 8
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 8
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 8
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+multi keys (id int, name varchar, other varchar)
+
+id = 1;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 4;
+id > 2 and name = '333'; remote: id > 2
+id > 2 and name > '333'; remote: id > 2
+id > 2 and name > '333' and other < 'ddd'; remote: id > 2 no results
+id > 2 and name >= '333' and other < 'ddd'; remote: id > 2 1 result
+id >= 4 and name = 'eric was here' and other > 'eeee';
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4;
+id >= 2 and name = '333' and other < 'ddd';
+remote: `id` >= 2 AND `name` >= '333';
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4;
+id < 3 and name = '222' and other <= 'ccc'; remote: id < 3
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4;
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4;
+full table scan
+
+id > 2 and id < 4;
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 4;
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 4;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 4;
+id = 6 and name = 'eric was here' and other > 'eeee';
+remote: (`id` > 6 AND `name` > 'eric was here' AND `other` > 'eeee')
+AND (`id` <= 6) AND ( AND `name` <= 'eric was here')
+no results
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+Summary:
+
+* If the start key flag is 0 the max key flag shouldn't even be set,
+ and if it is, the query produced would be invalid.
+* Multipart keys, even if containing some or all numeric columns,
+ are treated the same as non-numeric keys
+
+ If the query is " = " (quotes or not):
+ - records in range start key flag HA_READ_KEY_EXACT,
+ end key flag HA_READ_AFTER_KEY (incorrect)
+ - any other: start key flag HA_READ_KEY_OR_NEXT,
+ end key flag HA_READ_AFTER_KEY (correct)
+
+* 'like' queries (of key)
+ - Numeric, full table scan
+ - Non-numeric
+ records_in_range: start_key 0 end_key 3
+ other : start_key 1 end_key 3
+
+* If the key flag is HA_READ_AFTER_KEY:
+ if start_key, append >
+ if end_key, append <=
+
+* If create_where_key was called by records_in_range:
+
+ - if the key is numeric:
+ start key flag is 0 when end key is NULL, end key flag is 3 or 4
+ - if create_where_key was called by any other function:
+ start key flag is 1 when end key is NULL, end key flag is 3 or 4
+ - if the key is non-numeric, or multipart
+ When the query is an exact match, the start key flag is 0,
+ end key flag is 3 for what should be a no-range condition where
+ you should have 0 and max key NULL, which it is if called by
+ read_range_first
+
+Conclusion:
+
+1. Need logic to determin if a key is min or max when the flag is
+HA_READ_AFTER_KEY, and handle appending correct operator accordingly
+
+2. Need a boolean flag to pass to create_where_from_key, used in the
+switch statement. Add 1 to the flag if:
+ - start key flag is HA_READ_KEY_EXACT and the end key is NULL
+
+*/
+
+bool ha_federatedx::create_where_from_key(String *to,
+ KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool from_records_in_range,
+ bool eq_range)
+{
+ bool both_not_null=
+ (start_key != NULL && end_key != NULL) ? TRUE : FALSE;
+ const uchar *ptr;
+ uint remainder, length;
+ char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info);
+ const key_range *ranges[2]= { start_key, end_key };
+ my_bitmap_map *old_map;
+ DBUG_ENTER("ha_federatedx::create_where_from_key");
+
+ tmp.length(0);
+ if (start_key == NULL && end_key == NULL)
+ DBUG_RETURN(1);
+
+ old_map= dbug_tmp_use_all_columns(table, table->write_set);
+ for (uint i= 0; i <= 1; i++)
+ {
+ bool needs_quotes;
+ KEY_PART_INFO *key_part;
+ if (ranges[i] == NULL)
+ continue;
+
+ if (both_not_null)
+ {
+ if (i > 0)
+ tmp.append(STRING_WITH_LEN(") AND ("));
+ else
+ tmp.append(STRING_WITH_LEN(" ("));
+ }
+
+ for (key_part= key_info->key_part,
+ remainder= key_info->key_parts,
+ length= ranges[i]->length,
+ ptr= ranges[i]->key; ;
+ remainder--,
+ key_part++)
+ {
+ Field *field= key_part->field;
+ uint store_length= key_part->store_length;
+ uint part_length= min(store_length, length);
+ needs_quotes= field->str_needs_quotes();
+ DBUG_DUMP("key, start of loop", ptr, length);
+
+ if (key_part->null_bit)
+ {
+ if (*ptr++)
+ {
+ /*
+ We got "IS [NOT] NULL" condition against nullable column. We
+ distinguish between "IS NOT NULL" and "IS NULL" by flag. For
+ "IS NULL", flag is set to HA_READ_KEY_EXACT.
+ */
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(ranges[i]->flag == HA_READ_KEY_EXACT ?
+ " IS NULL " : " IS NOT NULL "))
+ goto err;
+ /*
+ We need to adjust pointer and length to be prepared for next
+ key part. As well as check if this was last key part.
+ */
+ goto prepare_for_next_key_part;
+ }
+ }
+
+ if (tmp.append(STRING_WITH_LEN(" (")))
+ goto err;
+
+ switch (ranges[i]->flag) {
+ case HA_READ_KEY_EXACT:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_EXACT %d", i));
+ if (store_length >= length ||
+ !needs_quotes ||
+ key_part->type == HA_KEYTYPE_BIT ||
+ field->result_type() != STRING_RESULT)
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ goto err;
+
+ if (from_records_in_range)
+ {
+ if (tmp.append(STRING_WITH_LEN(" >= ")))
+ goto err;
+ }
+ else
+ {
+ if (tmp.append(STRING_WITH_LEN(" = ")))
+ goto err;
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ }
+ else
+ {
+ /* LIKE */
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" LIKE ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 1, ptr,
+ part_length))
+ goto err;
+ }
+ break;
+ case HA_READ_AFTER_KEY:
+ if (eq_range)
+ {
+ if (tmp.append("1=1")) // Dummy
+ goto err;
+ break;
+ }
+ DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i));
+ if (store_length >= length) /* end key */
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ goto err;
+
+ if (i > 0) /* end key */
+ {
+ if (tmp.append(STRING_WITH_LEN(" <= ")))
+ goto err;
+ }
+ else /* start key */
+ {
+ if (tmp.append(STRING_WITH_LEN(" > ")))
+ goto err;
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ {
+ goto err;
+ }
+ break;
+ }
+ case HA_READ_KEY_OR_NEXT:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_NEXT %d", i));
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" >= ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ case HA_READ_BEFORE_KEY:
+ DBUG_PRINT("info", ("federatedx HA_READ_BEFORE_KEY %d", i));
+ if (store_length >= length)
+ {
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" < ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ }
+ case HA_READ_KEY_OR_PREV:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_PREV %d", i));
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" <= ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ default:
+ DBUG_PRINT("info",("cannot handle flag %d", ranges[i]->flag));
+ goto err;
+ }
+ if (tmp.append(STRING_WITH_LEN(") ")))
+ goto err;
+
+prepare_for_next_key_part:
+ if (store_length >= length)
+ break;
+ DBUG_PRINT("info", ("remainder %d", remainder));
+ DBUG_ASSERT(remainder > 1);
+ length-= store_length;
+ /*
+ For nullable columns, null-byte is already skipped before, that is
+ ptr was incremented by 1. Since store_length still counts null-byte,
+ we need to subtract 1 from store_length.
+ */
+ ptr+= store_length - test(key_part->null_bit);
+ if (tmp.append(STRING_WITH_LEN(" AND ")))
+ goto err;
+
+ DBUG_PRINT("info",
+ ("create_where_from_key WHERE clause: %s",
+ tmp.c_ptr_quick()));
+ }
+ }
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+
+ if (both_not_null)
+ if (tmp.append(STRING_WITH_LEN(") ")))
+ DBUG_RETURN(1);
+
+ if (to->append(STRING_WITH_LEN(" WHERE ")))
+ DBUG_RETURN(1);
+
+ if (to->append(tmp))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+
+err:
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ DBUG_RETURN(1);
+}
+
+static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server,
+ FEDERATEDX_SHARE *share, CHARSET_INFO *table_charset)
+{
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String key(buffer, sizeof(buffer), &my_charset_bin);
+ String scheme(share->scheme, &my_charset_latin1);
+ String hostname(share->hostname, &my_charset_latin1);
+ String database(share->database, system_charset_info);
+ String username(share->username, system_charset_info);
+ String socket(share->socket ? share->socket : "", files_charset_info);
+ String password(share->password ? share->password : "", &my_charset_bin);
+ DBUG_ENTER("fill_server");
+
+ /* Do some case conversions */
+ scheme.reserve(scheme.length());
+ scheme.length(my_casedn_str(&my_charset_latin1, scheme.c_ptr_safe()));
+
+ hostname.reserve(hostname.length());
+ hostname.length(my_casedn_str(&my_charset_latin1, hostname.c_ptr_safe()));
+
+ if (lower_case_table_names)
+ {
+ database.reserve(database.length());
+ database.length(my_casedn_str(system_charset_info, database.c_ptr_safe()));
+ }
+
+#ifndef __WIN__
+ /*
+ TODO: there is no unix sockets under windows so the engine should be
+ revised about using sockets in such environment.
+ */
+ if (lower_case_file_system && socket.length())
+ {
+ socket.reserve(socket.length());
+ socket.length(my_casedn_str(files_charset_info, socket.c_ptr_safe()));
+ }
+#endif
+
+ /* start with all bytes zeroed */
+ bzero(server, sizeof(*server));
+
+ key.length(0);
+ key.reserve(scheme.length() + hostname.length() + database.length() +
+ socket.length() + username.length() + password.length() +
+ sizeof(int) + 8);
+ key.append(scheme);
+ key.q_append('\0');
+ server->hostname= (const char *) (intptr) key.length();
+ key.append(hostname);
+ key.q_append('\0');
+ server->database= (const char *) (intptr) key.length();
+ key.append(database);
+ key.q_append('\0');
+ key.q_append((uint32) share->port);
+ server->socket= (const char *) (intptr) key.length();
+ key.append(socket);
+ key.q_append('\0');
+ server->username= (const char *) (intptr) key.length();
+ key.append(username);
+ key.q_append('\0');
+ server->password= (const char *) (intptr) key.length();
+ key.append(password);
+
+ server->key_length= key.length();
+ server->key= (uchar *) memdup_root(mem_root, key.ptr(), key.length()+1);
+
+ /* pointer magic */
+ server->scheme+= (intptr) server->key;
+ server->hostname+= (intptr) server->key;
+ server->database+= (intptr) server->key;
+ server->username+= (intptr) server->key;
+ server->password+= (intptr) server->key;
+ server->socket+= (intptr) server->key;
+ server->port= share->port;
+
+ if (!share->socket)
+ server->socket= NULL;
+ if (!share->password)
+ server->password= NULL;
+
+ if (table_charset)
+ server->csname= strdup_root(mem_root, table_charset->csname);
+
+ DBUG_VOID_RETURN;
+}
+
+
+static FEDERATEDX_SERVER *get_server(FEDERATEDX_SHARE *share, TABLE *table)
+{
+ FEDERATEDX_SERVER *server= NULL, tmp_server;
+ MEM_ROOT mem_root;
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String key(buffer, sizeof(buffer), &my_charset_bin);
+ String scheme(share->scheme, &my_charset_latin1);
+ String hostname(share->hostname, &my_charset_latin1);
+ String database(share->database, system_charset_info);
+ String username(share->username, system_charset_info);
+ String socket(share->socket ? share->socket : "", files_charset_info);
+ String password(share->password ? share->password : "", &my_charset_bin);
+ DBUG_ENTER("ha_federated.cc::get_server");
+
+ safe_mutex_assert_owner(&federatedx_mutex);
+
+ init_alloc_root(&mem_root, 4096, 4096);
+
+ fill_server(&mem_root, &tmp_server, share, table ? table->s->table_charset : 0);
+
+ if (!(server= (FEDERATEDX_SERVER *) hash_search(&federatedx_open_servers,
+ tmp_server.key,
+ tmp_server.key_length)))
+ {
+ if (!table || !tmp_server.csname)
+ goto error;
+
+ if (!(server= (FEDERATEDX_SERVER *) memdup_root(&mem_root,
+ (char *) &tmp_server,
+ sizeof(*server))))
+ goto error;
+
+ server->mem_root= mem_root;
+
+ if (my_hash_insert(&federatedx_open_servers, (uchar*) server))
+ goto error;
+
+ pthread_mutex_init(&server->mutex, MY_MUTEX_INIT_FAST);
+ }
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
+ server->use_count++;
+
+ DBUG_RETURN(server);
+error:
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
+}
+
+
+/*
+ Example of simple lock controls. The "share" it creates is structure we will
+ pass to each federatedx handler. Do you have to have one of these? Well, you
+ have pieces that are used for locking, and they are needed to function.
+*/
+
+static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
+{
+ char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ Field **field;
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ FEDERATEDX_SHARE *share= NULL, tmp_share;
+ MEM_ROOT mem_root;
+ DBUG_ENTER("ha_federatedx.cc::get_share");
+
+ /*
+ In order to use this string, we must first zero it's length,
+ or it will contain garbage
+ */
+ query.length(0);
+
+ bzero(&tmp_share, sizeof(tmp_share));
+ init_alloc_root(&mem_root, 256, 0);
+
+ pthread_mutex_lock(&federatedx_mutex);
+
+ tmp_share.share_key= table_name;
+ tmp_share.share_key_length= strlen(table_name);
+ if (parse_url(&mem_root, &tmp_share, table, 0))
+ goto error;
+
+ /* TODO: change tmp_share.scheme to LEX_STRING object */
+ if (!(share= (FEDERATEDX_SHARE *) hash_search(&federatedx_open_tables,
+ (uchar*) tmp_share.share_key,
+ tmp_share.
+ share_key_length)))
+ {
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("SELECT "));
+ for (field= table->field; *field; field++)
+ {
+ append_ident(&query, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+ query.append(STRING_WITH_LEN(", "));
+ }
+ /* chops off trailing comma */
+ query.length(query.length() - sizeof_trailing_comma);
+
+ query.append(STRING_WITH_LEN(" FROM "));
+
+ append_ident(&query, tmp_share.table_name,
+ tmp_share.table_name_length, ident_quote_char);
+
+ if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
+ !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length() + 1)))
+ goto error;
+
+ share->mem_root= mem_root;
+
+ DBUG_PRINT("info",
+ ("share->select_query %s", share->select_query));
+
+ if (!(share->s= get_server(share, table)))
+ goto error;
+
+ if (my_hash_insert(&federatedx_open_tables, (uchar*) share))
+ goto error;
+ thr_lock_init(&share->lock);
+ }
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
+ share->use_count++;
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ DBUG_RETURN(share);
+
+error:
+ pthread_mutex_unlock(&federatedx_mutex);
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
+}
+
+
+static int free_server(federatedx_txn *txn, FEDERATEDX_SERVER *server)
+{
+ bool destroy;
+ DBUG_ENTER("free_server");
+
+ pthread_mutex_lock(&federatedx_mutex);
+ if ((destroy= !--server->use_count))
+ hash_delete(&federatedx_open_servers, (uchar*) server);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (destroy)
+ {
+ MEM_ROOT mem_root;
+
+ txn->close(server);
+
+ DBUG_ASSERT(server->io_count == 0);
+
+ pthread_mutex_destroy(&server->mutex);
+ mem_root= server->mem_root;
+ free_root(&mem_root, MYF(0));
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Free lock controls. We call this whenever we close a table.
+ If the table had the last reference to the share then we
+ free memory associated with it.
+*/
+
+static int free_share(federatedx_txn *txn, FEDERATEDX_SHARE *share)
+{
+ bool destroy;
+ DBUG_ENTER("free_share");
+
+ pthread_mutex_lock(&federatedx_mutex);
+ if ((destroy= !--share->use_count))
+ hash_delete(&federatedx_open_tables, (uchar*) share);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (destroy)
+ {
+ MEM_ROOT mem_root;
+ FEDERATEDX_SERVER *server= share->s;
+
+ thr_lock_delete(&share->lock);
+
+ mem_root= share->mem_root;
+ free_root(&mem_root, MYF(0));
+
+ free_server(txn, server);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+ha_rows ha_federatedx::records_in_range(uint inx, key_range *start_key,
+ key_range *end_key)
+{
+ /*
+
+ We really want indexes to be used as often as possible, therefore
+ we just need to hard-code the return value to a very low number to
+ force the issue
+
+*/
+ DBUG_ENTER("ha_federatedx::records_in_range");
+ DBUG_RETURN(FEDERATEDX_RECORDS_IN_RANGE);
+}
+/*
+ If frm_error() is called then we will use this to to find out
+ what file extentions exist for the storage engine. This is
+ also used by the default rename_table and delete_table method
+ in handler.cc.
+*/
+
+const char **ha_federatedx::bas_ext() const
+{
+ static const char *ext[]=
+ {
+ NullS
+ };
+ return ext;
+}
+
+
+federatedx_txn *ha_federatedx::get_txn(THD *thd, bool no_create)
+{
+ federatedx_txn **txnp= (federatedx_txn **) ha_data(thd);
+ if (!*txnp && !no_create)
+ *txnp= new federatedx_txn();
+ return *txnp;
+}
+
+
+int ha_federatedx::disconnect(handlerton *hton, MYSQL_THD thd)
+{
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ delete txn;
+ return 0;
+}
+
+
+/*
+ Used for opening tables. The name will be the name of the file.
+ A table is opened when it needs to be opened. For instance
+ when a request comes in for a select on the table (tables are not
+ open and closed for each request, they are cached).
+
+ Called from handler.cc by handler::ha_open(). The server opens
+ all tables by calling ha_open() which then calls the handler
+ specific open().
+*/
+
+int ha_federatedx::open(const char *name, int mode, uint test_if_locked)
+{
+ int error;
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::open");
+
+ if (!(share= get_share(name, table)))
+ DBUG_RETURN(1);
+ thr_lock_data_init(&share->lock, &lock, NULL);
+
+ DBUG_ASSERT(io == NULL);
+
+ txn= get_txn(thd);
+
+ if ((error= txn->acquire(share, TRUE, &io)))
+ {
+ free_share(txn, share);
+ DBUG_RETURN(error);
+ }
+
+ txn->release(&io);
+
+ ref_length= (table->s->primary_key != MAX_KEY ?
+ table->key_info[table->s->primary_key].key_length :
+ table->s->reclength);
+ DBUG_PRINT("info", ("ref_length: %u", ref_length));
+
+ reset();
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Closes a table. We call the free_share() function to free any resources
+ that we have allocated in the "shared" structure.
+
+ Called from sql_base.cc, sql_select.cc, and table.cc.
+ In sql_select.cc it is only used to close up temporary tables or during
+ the process where a temporary table is converted over to being a
+ myisam table.
+ For sql_base.cc look at close_data_tables().
+*/
+
+int ha_federatedx::close(void)
+{
+ int retval, error;
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::close");
+
+ /* free the result set */
+ if (stored_result)
+ retval= free_result();
+
+ /* Disconnect from mysql */
+ if ((txn= get_txn(thd, true)))
+ txn->release(&io);
+
+ DBUG_ASSERT(io == NULL);
+
+ if ((error= free_share(txn, share)))
+ retval= error;
+ DBUG_RETURN(retval);
+}
+
+/*
+
+ Checks if a field in a record is SQL NULL.
+
+ SYNOPSIS
+ field_in_record_is_null()
+ table TABLE pointer, MySQL table object
+ field Field pointer, MySQL field object
+ record char pointer, contains record
+
+ DESCRIPTION
+ This method uses the record format information in table to track
+ the null bit in record.
+
+ RETURN VALUE
+ 1 if NULL
+ 0 otherwise
+*/
+
+static inline uint field_in_record_is_null(TABLE *table,
+ Field *field,
+ char *record)
+{
+ int null_offset;
+ DBUG_ENTER("ha_federatedx::field_in_record_is_null");
+
+ if (!field->null_ptr)
+ DBUG_RETURN(0);
+
+ null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]);
+
+ if (record[null_offset] & field->null_bit)
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Construct the INSERT statement.
+
+ @details This method will construct the INSERT statement and appends it to
+ the supplied query string buffer.
+
+ @return
+ @retval FALSE No error
+ @retval TRUE Failure
+*/
+
+bool ha_federatedx::append_stmt_insert(String *query)
+{
+ char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ Field **field;
+ uint tmp_length;
+ bool added_field= FALSE;
+
+ /* The main insert query string */
+ String insert_string(insert_buffer, sizeof(insert_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::append_stmt_insert");
+
+ insert_string.length(0);
+
+ if (replace_duplicates)
+ insert_string.append(STRING_WITH_LEN("REPLACE INTO "));
+ else if (ignore_duplicates && !insert_dup_update)
+ insert_string.append(STRING_WITH_LEN("INSERT IGNORE INTO "));
+ else
+ insert_string.append(STRING_WITH_LEN("INSERT INTO "));
+ append_ident(&insert_string, share->table_name, share->table_name_length,
+ ident_quote_char);
+ tmp_length= insert_string.length();
+ insert_string.append(STRING_WITH_LEN(" ("));
+
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that match the current query id
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ /* append the field name */
+ append_ident(&insert_string, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic if *(fields + 1) to
+ make the following appends conditional as we don't know if the
+ next field is in the write set
+ */
+ insert_string.append(STRING_WITH_LEN(", "));
+ added_field= TRUE;
+ }
+ }
+
+ if (added_field)
+ {
+ /* Remove trailing comma. */
+ insert_string.length(insert_string.length() - sizeof_trailing_comma);
+ insert_string.append(STRING_WITH_LEN(") "));
+ }
+ else
+ {
+ /* If there were no fields, we don't want to add a closing paren. */
+ insert_string.length(tmp_length);
+ }
+
+ insert_string.append(STRING_WITH_LEN(" VALUES "));
+
+ DBUG_RETURN(query->append(insert_string));
+}
+
+
+/*
+ write_row() inserts a row. No extra() hint is given currently if a bulk load
+ is happeneding. buf() is a byte array of data. You can use the field
+ information to extract the data from the native byte array type.
+ Example of this would be:
+ for (Field **field=table->field ; *field ; field++)
+ {
+ ...
+ }
+
+ Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
+ sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::write_row(uchar *buf)
+{
+ char values_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ Field **field;
+ uint tmp_length;
+ int error= 0;
+ bool use_bulk_insert;
+ bool auto_increment_update_required= (table->next_number_field != NULL);
+
+ /* The string containing the values to be added to the insert */
+ String values_string(values_buffer, sizeof(values_buffer), &my_charset_bin);
+ /* The actual value of the field, to be added to the values_string */
+ String insert_field_value_string(insert_field_value_buffer,
+ sizeof(insert_field_value_buffer),
+ &my_charset_bin);
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+ DBUG_ENTER("ha_federatedx::write_row");
+
+ values_string.length(0);
+ insert_field_value_string.length(0);
+ ha_statistic_increment(&SSV::ha_write_count);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
+
+ /*
+ start both our field and field values strings
+ We must disable multi-row insert for "INSERT...ON DUPLICATE KEY UPDATE"
+ Ignore duplicates is always true when insert_dup_update is true.
+ When replace_duplicates == TRUE, we can safely enable multi-row insert.
+ When performing multi-row insert, we only collect the columns values for
+ the row. The start of the statement is only created when the first
+ row is copied in to the bulk_insert string.
+ */
+ if (!(use_bulk_insert= bulk_insert.str &&
+ (!insert_dup_update || replace_duplicates)))
+ append_stmt_insert(&values_string);
+
+ values_string.append(STRING_WITH_LEN(" ("));
+ tmp_length= values_string.length();
+
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that is part of the write set
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ if ((*field)->is_null())
+ values_string.append(STRING_WITH_LEN(" NULL "));
+ else
+ {
+ bool needs_quote= (*field)->str_needs_quotes();
+ (*field)->val_str(&insert_field_value_string);
+ if (needs_quote)
+ values_string.append(value_quote_char);
+ insert_field_value_string.print(&values_string);
+ if (needs_quote)
+ values_string.append(value_quote_char);
+
+ insert_field_value_string.length(0);
+ }
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic if *(fields + 1) to
+ make the following appends conditional as we don't know if the
+ next field is in the write set
+ */
+ values_string.append(STRING_WITH_LEN(", "));
+ }
+ }
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+
+ /*
+ if there were no fields, we don't want to add a closing paren
+ AND, we don't want to chop off the last char '('
+ insert will be "INSERT INTO t1 VALUES ();"
+ */
+ if (values_string.length() > tmp_length)
+ {
+ /* chops off trailing comma */
+ values_string.length(values_string.length() - sizeof_trailing_comma);
+ }
+ /* we always want to append this, even if there aren't any fields */
+ values_string.append(STRING_WITH_LEN(") "));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (use_bulk_insert)
+ {
+ /*
+ Send the current bulk insert out if appending the current row would
+ cause the statement to overflow the packet size, otherwise set
+ auto_increment_update_required to FALSE as no query was executed.
+ */
+ if (bulk_insert.length + values_string.length() + bulk_padding >
+ io->max_query_size() && bulk_insert.length)
+ {
+ error= io->query(bulk_insert.str, bulk_insert.length);
+ bulk_insert.length= 0;
+ }
+ else
+ auto_increment_update_required= FALSE;
+
+ if (bulk_insert.length == 0)
+ {
+ char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String insert_string(insert_buffer, sizeof(insert_buffer),
+ &my_charset_bin);
+ insert_string.length(0);
+ append_stmt_insert(&insert_string);
+ dynstr_append_mem(&bulk_insert, insert_string.ptr(),
+ insert_string.length());
+ }
+ else
+ dynstr_append_mem(&bulk_insert, ",", 1);
+
+ dynstr_append_mem(&bulk_insert, values_string.ptr(),
+ values_string.length());
+ }
+ else
+ {
+ error= io->query(values_string.ptr(), values_string.length());
+ }
+
+ if (error)
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ /*
+ If the table we've just written a record to contains an auto_increment
+ field, then store the last_insert_id() value from the foreign server
+ */
+ if (auto_increment_update_required)
+ {
+ update_auto_increment();
+
+ /* mysql_insert() uses this for protocol return value */
+ table->next_number_field->store(stats.auto_increment_value, 1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Prepares the storage engine for bulk inserts.
+
+ @param[in] rows estimated number of rows in bulk insert
+ or 0 if unknown.
+
+ @details Initializes memory structures required for bulk insert.
+*/
+
+void ha_federatedx::start_bulk_insert(ha_rows rows)
+{
+ uint page_size;
+ DBUG_ENTER("ha_federatedx::start_bulk_insert");
+
+ dynstr_free(&bulk_insert);
+
+ /**
+ We don't bother with bulk-insert semantics when the estimated rows == 1
+ The rows value will be 0 if the server does not know how many rows
+ would be inserted. This can occur when performing INSERT...SELECT
+ */
+
+ if (rows == 1)
+ DBUG_VOID_RETURN;
+
+ /*
+ Make sure we have an open connection so that we know the
+ maximum packet size.
+ */
+ if (txn->acquire(share, FALSE, &io))
+ DBUG_VOID_RETURN;
+
+ page_size= (uint) my_getpagesize();
+
+ if (init_dynamic_string(&bulk_insert, NULL, page_size, page_size))
+ DBUG_VOID_RETURN;
+
+ bulk_insert.length= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief End bulk insert.
+
+ @details This method will send any remaining rows to the remote server.
+ Finally, it will deinitialize the bulk insert data structure.
+
+ @return Operation status
+ @retval 0 No error
+ @retval != 0 Error occured at remote server. Also sets my_errno.
+*/
+
+int ha_federatedx::end_bulk_insert(bool abort)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::end_bulk_insert");
+
+ if (bulk_insert.str && bulk_insert.length && !abort)
+ {
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+ if (io->query(bulk_insert.str, bulk_insert.length))
+ error= stash_remote_error();
+ else
+ if (table->next_number_field)
+ update_auto_increment();
+ }
+
+ dynstr_free(&bulk_insert);
+
+ DBUG_RETURN(my_errno= error);
+}
+
+
+/*
+ ha_federatedx::update_auto_increment
+
+ This method ensures that last_insert_id() works properly. What it simply does
+ is calls last_insert_id() on the foreign database immediately after insert
+ (if the table has an auto_increment field) and sets the insert id via
+ thd->insert_id(ID)).
+*/
+void ha_federatedx::update_auto_increment(void)
+{
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::update_auto_increment");
+
+ ha_federatedx::info(HA_STATUS_AUTO);
+ thd->first_successful_insert_id_in_cur_stmt=
+ stats.auto_increment_value;
+ DBUG_PRINT("info",("last_insert_id: %ld", (long) stats.auto_increment_value));
+
+ DBUG_VOID_RETURN;
+}
+
+int ha_federatedx::optimize(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ int error= 0;
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::optimize");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("OPTIMIZE TABLE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ error= stash_remote_error();
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::repair(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ int error= 0;
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::repair");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("REPAIR TABLE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+ if (check_opt->flags & T_QUICK)
+ query.append(STRING_WITH_LEN(" QUICK"));
+ if (check_opt->flags & T_EXTEND)
+ query.append(STRING_WITH_LEN(" EXTENDED"));
+ if (check_opt->sql_flags & TT_USEFRM)
+ query.append(STRING_WITH_LEN(" USE_FRM"));
+
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ error= stash_remote_error();
+
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Yes, update_row() does what you expect, it updates a row. old_data will have
+ the previous row record in it, while new_data will have the newest data in
+ it.
+
+ Keep in mind that the server can do updates based on ordering if an ORDER BY
+ clause was used. Consecutive ordering is not guaranteed.
+ Currently new_data will not have an updated auto_increament record, or
+ and updated timestamp field. You can do these for federatedx by doing these:
+ if (table->timestamp_on_update_now)
+ update_timestamp(new_row+table->timestamp_on_update_now-1);
+ if (table->next_number_field && record == table->record[0])
+ update_auto_increment();
+
+ Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
+*/
+
+int ha_federatedx::update_row(const uchar *old_data, uchar *new_data)
+{
+ /*
+ This used to control how the query was built. If there was a
+ primary key, the query would be built such that there was a where
+ clause with only that column as the condition. This is flawed,
+ because if we have a multi-part primary key, it would only use the
+ first part! We don't need to do this anyway, because
+ read_range_first will retrieve the correct record, which is what
+ is used to build the WHERE clause. We can however use this to
+ append a LIMIT to the end if there is NOT a primary key. Why do
+ this? Because we only are updating one record, and LIMIT enforces
+ this.
+ */
+ bool has_a_primary_key= test(table->s->primary_key != MAX_KEY);
+
+ /*
+ buffers for following strings
+ */
+ char field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char update_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char where_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+
+ /* Work area for field values */
+ String field_value(field_value_buffer, sizeof(field_value_buffer),
+ &my_charset_bin);
+ /* stores the update query */
+ String update_string(update_buffer,
+ sizeof(update_buffer),
+ &my_charset_bin);
+ /* stores the WHERE clause */
+ String where_string(where_buffer,
+ sizeof(where_buffer),
+ &my_charset_bin);
+ uchar *record= table->record[0];
+ int error;
+ DBUG_ENTER("ha_federatedx::update_row");
+ /*
+ set string lengths to 0 to avoid misc chars in string
+ */
+ field_value.length(0);
+ update_string.length(0);
+ where_string.length(0);
+
+ if (ignore_duplicates)
+ update_string.append(STRING_WITH_LEN("UPDATE IGNORE "));
+ else
+ update_string.append(STRING_WITH_LEN("UPDATE "));
+ append_ident(&update_string, share->table_name,
+ share->table_name_length, ident_quote_char);
+ update_string.append(STRING_WITH_LEN(" SET "));
+
+ /*
+ In this loop, we want to match column names to values being inserted
+ (while building INSERT statement).
+
+ Iterate through table->field (new data) and share->old_field (old_data)
+ using the same index to create an SQL UPDATE statement. New data is
+ used to create SET field=value and old data is used to create WHERE
+ field=oldvalue
+ */
+
+ for (Field **field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ uint field_name_length= strlen((*field)->field_name);
+ append_ident(&update_string, (*field)->field_name, field_name_length,
+ ident_quote_char);
+ update_string.append(STRING_WITH_LEN(" = "));
+
+ if ((*field)->is_null())
+ update_string.append(STRING_WITH_LEN(" NULL "));
+ else
+ {
+ /* otherwise = */
+ my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
+ bool needs_quote= (*field)->str_needs_quotes();
+ (*field)->val_str(&field_value);
+ if (needs_quote)
+ update_string.append(value_quote_char);
+ field_value.print(&update_string);
+ if (needs_quote)
+ update_string.append(value_quote_char);
+ field_value.length(0);
+ tmp_restore_column_map(table->read_set, old_map);
+ }
+ update_string.append(STRING_WITH_LEN(", "));
+ }
+
+ if (bitmap_is_set(table->read_set, (*field)->field_index))
+ {
+ uint field_name_length= strlen((*field)->field_name);
+ append_ident(&where_string, (*field)->field_name, field_name_length,
+ ident_quote_char);
+ if (field_in_record_is_null(table, *field, (char*) old_data))
+ where_string.append(STRING_WITH_LEN(" IS NULL "));
+ else
+ {
+ bool needs_quote= (*field)->str_needs_quotes();
+ where_string.append(STRING_WITH_LEN(" = "));
+ (*field)->val_str(&field_value,
+ (old_data + (*field)->offset(record)));
+ if (needs_quote)
+ where_string.append(value_quote_char);
+ field_value.print(&where_string);
+ if (needs_quote)
+ where_string.append(value_quote_char);
+ field_value.length(0);
+ }
+ where_string.append(STRING_WITH_LEN(" AND "));
+ }
+ }
+
+ /* Remove last ', '. This works as there must be at least on updated field */
+ update_string.length(update_string.length() - sizeof_trailing_comma);
+
+ if (where_string.length())
+ {
+ /* chop off trailing AND */
+ where_string.length(where_string.length() - sizeof_trailing_and);
+ update_string.append(STRING_WITH_LEN(" WHERE "));
+ update_string.append(where_string);
+ }
+
+ /*
+ If this table has not a primary key, then we could possibly
+ update multiple rows. We want to make sure to only update one!
+ */
+ if (!has_a_primary_key)
+ update_string.append(STRING_WITH_LEN(" LIMIT 1"));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(update_string.ptr(), update_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ This will delete a row. 'buf' will contain a copy of the row to be =deleted.
+ The server will call this right after the current row has been called (from
+ either a previous rnd_next() or index call).
+ If you keep a pointer to the last row or can access a primary key it will
+ make doing the deletion quite a bit easier.
+ Keep in mind that the server does no guarentee consecutive deletions.
+ ORDER BY clauses can be used.
+
+ Called in sql_acl.cc and sql_udf.cc to manage internal table information.
+ Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select
+ it is used for removing duplicates while in insert it is used for REPLACE
+ calls.
+*/
+
+int ha_federatedx::delete_row(const uchar *buf)
+{
+ char delete_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char data_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String delete_string(delete_buffer, sizeof(delete_buffer), &my_charset_bin);
+ String data_string(data_buffer, sizeof(data_buffer), &my_charset_bin);
+ uint found= 0;
+ int error;
+ DBUG_ENTER("ha_federatedx::delete_row");
+
+ delete_string.length(0);
+ delete_string.append(STRING_WITH_LEN("DELETE FROM "));
+ append_ident(&delete_string, share->table_name,
+ share->table_name_length, ident_quote_char);
+ delete_string.append(STRING_WITH_LEN(" WHERE "));
+
+ for (Field **field= table->field; *field; field++)
+ {
+ Field *cur_field= *field;
+ found++;
+ if (bitmap_is_set(table->read_set, cur_field->field_index))
+ {
+ append_ident(&delete_string, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+ data_string.length(0);
+ if (cur_field->is_null())
+ {
+ delete_string.append(STRING_WITH_LEN(" IS NULL "));
+ }
+ else
+ {
+ bool needs_quote= cur_field->str_needs_quotes();
+ delete_string.append(STRING_WITH_LEN(" = "));
+ cur_field->val_str(&data_string);
+ if (needs_quote)
+ delete_string.append(value_quote_char);
+ data_string.print(&delete_string);
+ if (needs_quote)
+ delete_string.append(value_quote_char);
+ }
+ delete_string.append(STRING_WITH_LEN(" AND "));
+ }
+ }
+
+ // Remove trailing AND
+ delete_string.length(delete_string.length() - sizeof_trailing_and);
+ if (!found)
+ delete_string.length(delete_string.length() - sizeof_trailing_where);
+
+ delete_string.append(STRING_WITH_LEN(" LIMIT 1"));
+ DBUG_PRINT("info",
+ ("Delete sql: %s", delete_string.c_ptr_quick()));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(delete_string.ptr(), delete_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ stats.deleted+= (ha_rows) io->affected_rows();
+ stats.records-= (ha_rows) io->affected_rows();
+ DBUG_PRINT("info",
+ ("rows deleted %ld rows deleted for all time %ld",
+ (long) io->affected_rows(), (long) stats.deleted));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Positions an index cursor to the index specified in the handle. Fetches the
+ row if available. If the key value is null, begin at the first key of the
+ index. This method, which is called in the case of an SQL statement having
+ a WHERE clause on a non-primary key index, simply calls index_read_idx.
+*/
+
+int ha_federatedx::index_read(uchar *buf, const uchar *key,
+ uint key_len, ha_rkey_function find_flag)
+{
+ DBUG_ENTER("ha_federatedx::index_read");
+
+ if (stored_result)
+ (void) free_result();
+ DBUG_RETURN(index_read_idx_with_result_set(buf, active_index, key,
+ key_len, find_flag,
+ &stored_result));
+}
+
+
+/*
+ Positions an index cursor to the index specified in key. Fetches the
+ row if any. This is only used to read whole keys.
+
+ This method is called via index_read in the case of a WHERE clause using
+ a primary key index OR is called DIRECTLY when the WHERE clause
+ uses a PRIMARY KEY index.
+
+ NOTES
+ This uses an internal result set that is deleted before function
+ returns. We need to be able to be callable from ha_rnd_pos()
+*/
+
+int ha_federatedx::index_read_idx(uchar *buf, uint index, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ int retval;
+ FEDERATEDX_IO_RESULT *io_result;
+ DBUG_ENTER("ha_federatedx::index_read_idx");
+
+ if ((retval= index_read_idx_with_result_set(buf, index, key,
+ key_len, find_flag,
+ &io_result)))
+ DBUG_RETURN(retval);
+ /* io is correct, as index_read_idx_with_result_set was ok */
+ io->free_result(io_result);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ Create result set for rows matching query and return first row
+
+ RESULT
+ 0 ok In this case *result will contain the result set
+ table->status == 0
+ # error In this case *result will contain 0
+ table->status == STATUS_NOT_FOUND
+*/
+
+int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index,
+ const uchar *key,
+ uint key_len,
+ ha_rkey_function find_flag,
+ FEDERATEDX_IO_RESULT **result)
+{
+ int retval;
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char index_value[STRING_BUFFER_USUAL_SIZE];
+ char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String index_string(index_value,
+ sizeof(index_value),
+ &my_charset_bin);
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ key_range range;
+ DBUG_ENTER("ha_federatedx::index_read_idx_with_result_set");
+
+ *result= 0; // In case of errors
+ index_string.length(0);
+ sql_query.length(0);
+ ha_statistic_increment(&SSV::ha_read_key_count);
+
+ sql_query.append(share->select_query);
+
+ range.key= key;
+ range.length= key_len;
+ range.flag= find_flag;
+ create_where_from_key(&index_string,
+ &table->key_info[index],
+ &range,
+ NULL, 0, 0);
+ sql_query.append(index_string);
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ if (io->query(sql_query.ptr(), sql_query.length()))
+ {
+ my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
+ io->error_code(), io->error_str()));
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ if (!(*result= io->store_result()))
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+ if (!(retval= read_next(buf, *result)))
+ DBUG_RETURN(retval);
+
+ io->free_result(*result);
+ *result= 0;
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ my_error(retval, MYF(0), error_buffer);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ This method is used exlusevely by filesort() to check if we
+ can create sorting buffers of necessary size.
+ If the handler returns more records that it declares
+ here server can just crash on filesort().
+ We cannot guarantee that's not going to happen with
+ the FEDERATEDX engine, as we have records==0 always if the
+ client is a VIEW, and for the table the number of
+ records can inpredictably change during execution.
+ So we return maximum possible value here.
+*/
+
+ha_rows ha_federatedx::estimate_rows_upper_bound()
+{
+ return HA_POS_ERROR;
+}
+
+
+/* Initialized at each key walk (called multiple times unlike rnd_init()) */
+
+int ha_federatedx::index_init(uint keynr, bool sorted)
+{
+ DBUG_ENTER("ha_federatedx::index_init");
+ DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr));
+ active_index= keynr;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Read first range
+*/
+
+int ha_federatedx::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range_arg, bool sorted)
+{
+ char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ int retval;
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::read_range_first");
+
+ DBUG_ASSERT(!(start_key == NULL && end_key == NULL));
+
+ sql_query.length(0);
+ sql_query.append(share->select_query);
+ create_where_from_key(&sql_query,
+ &table->key_info[active_index],
+ start_key, end_key, 0, eq_range_arg);
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ if (stored_result)
+ {
+ io->free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (io->query(sql_query.ptr(), sql_query.length()))
+ {
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ sql_query.length(0);
+
+ if (!(stored_result= io->store_result()))
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+
+ retval= read_next(table->record[0], stored_result);
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(retval);
+}
+
+
+int ha_federatedx::read_range_next()
+{
+ int retval;
+ DBUG_ENTER("ha_federatedx::read_range_next");
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+}
+
+
+/* Used to read forward through the index. */
+int ha_federatedx::index_next(uchar *buf)
+{
+ DBUG_ENTER("ha_federatedx::index_next");
+ ha_statistic_increment(&SSV::ha_read_next_count);
+ DBUG_RETURN(read_next(buf, stored_result));
+}
+
+
+/*
+ rnd_init() is called when the system wants the storage engine to do a table
+ scan.
+
+ This is the method that gets data for the SELECT calls.
+
+ See the federatedx in the introduction at the top of this file to see when
+ rnd_init() is called.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::rnd_init(bool scan)
+{
+ DBUG_ENTER("ha_federatedx::rnd_init");
+ /*
+ The use of the 'scan' flag is incredibly important for this handler
+ to work properly, especially with updates containing WHERE clauses
+ using indexed columns.
+
+ When the initial query contains a WHERE clause of the query using an
+ indexed column, it's index_read_idx that selects the exact record from
+ the foreign database.
+
+ When there is NO index in the query, either due to not having a WHERE
+ clause, or the WHERE clause is using columns that are not indexed, a
+ 'full table scan' done by rnd_init, which in this situation simply means
+ a 'select * from ...' on the foreign table.
+
+ In other words, this 'scan' flag gives us the means to ensure that if
+ there is an index involved in the query, we want index_read_idx to
+ retrieve the exact record (scan flag is 0), and do not want rnd_init
+ to do a 'full table scan' and wipe out that result set.
+
+ Prior to using this flag, the problem was most apparent with updates.
+
+ An initial query like 'UPDATE tablename SET anything = whatever WHERE
+ indexedcol = someval', index_read_idx would get called, using a query
+ constructed with a WHERE clause built from the values of index ('indexcol'
+ in this case, having a value of 'someval'). mysql_store_result would
+ then get called (this would be the result set we want to use).
+
+ After this rnd_init (from sql_update.cc) would be called, it would then
+ unecessarily call "select * from table" on the foreign table, then call
+ mysql_store_result, which would wipe out the correct previous result set
+ from the previous call of index_read_idx's that had the result set
+ containing the correct record, hence update the wrong row!
+
+ */
+
+ if (scan)
+ {
+ int error;
+
+ if ((error= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(error);
+
+ if (stored_result)
+ {
+ io->free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (io->query(share->select_query,
+ strlen(share->select_query)))
+ goto error;
+
+ stored_result= io->store_result();
+ if (!stored_result)
+ goto error;
+ }
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(stash_remote_error());
+}
+
+
+int ha_federatedx::rnd_end()
+{
+ DBUG_ENTER("ha_federatedx::rnd_end");
+ DBUG_RETURN(index_end());
+}
+
+
+int ha_federatedx::free_result()
+{
+ int error;
+ DBUG_ASSERT(stored_result);
+ if ((error= txn->acquire(share, FALSE, &io)))
+ {
+ DBUG_ASSERT(0); // Fail when testing
+ return error;
+ }
+ io->free_result(stored_result);
+ stored_result= 0;
+ return 0;
+}
+
+int ha_federatedx::index_end(void)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::index_end");
+ if (stored_result)
+ error= free_result();
+ active_index= MAX_KEY;
+ DBUG_RETURN(error);
+}
+
+
+/*
+ This is called for each row of the table scan. When you run out of records
+ you should return HA_ERR_END_OF_FILE. Fill buff up with the row information.
+ The Field structure for the table is the key to getting data into buf
+ in a manner that will allow the server to understand it.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::rnd_next(uchar *buf)
+{
+ DBUG_ENTER("ha_federatedx::rnd_next");
+
+ if (stored_result == 0)
+ {
+ /*
+ Return value of rnd_init is not always checked (see records.cc),
+ so we can get here _even_ if there is _no_ pre-fetched result-set!
+ TODO: fix it. We can delete this in 5.1 when rnd_init() is checked.
+ */
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(read_next(buf, stored_result));
+}
+
+
+/*
+ ha_federatedx::read_next
+
+ reads from a result set and converts to mysql internal
+ format
+
+ SYNOPSIS
+ field_in_record_is_null()
+ buf byte pointer to record
+ result mysql result set
+
+ DESCRIPTION
+ This method is a wrapper method that reads one record from a result
+ set and converts it to the internal table format
+
+ RETURN VALUE
+ 1 error
+ 0 no error
+*/
+
+int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result)
+{
+ int retval;
+ FEDERATEDX_IO_ROW *row;
+ DBUG_ENTER("ha_federatedx::read_next");
+
+ table->status= STATUS_NOT_FOUND; // For easier return
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ /* Fetch a row, insert it back in a row format. */
+ if (!(row= io->fetch_row(result)))
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ if (!(retval= convert_row_to_internal_format(buf, row, result)))
+ table->status= 0;
+
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ store reference to current row so that we can later find it for
+ a re-read, update or delete.
+
+ In case of federatedx, a reference is either a primary key or
+ the whole record.
+
+ Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
+*/
+
+void ha_federatedx::position(const uchar *record)
+{
+ DBUG_ENTER("ha_federatedx::position");
+ if (table->s->primary_key != MAX_KEY)
+ key_copy(ref, (uchar *)record, table->key_info + table->s->primary_key,
+ ref_length);
+ else
+ memcpy(ref, record, ref_length);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This is like rnd_next, but you are given a position to use to determine the
+ row. The position will be of the type that you stored in ref.
+
+ This method is required for an ORDER BY
+
+ Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
+*/
+
+int ha_federatedx::rnd_pos(uchar *buf, uchar *pos)
+{
+ int result;
+ DBUG_ENTER("ha_federatedx::rnd_pos");
+ ha_statistic_increment(&SSV::ha_read_rnd_count);
+ if (table->s->primary_key != MAX_KEY)
+ {
+ /* We have a primary key, so use index_read_idx to find row */
+ result= index_read_idx(buf, table->s->primary_key, pos,
+ ref_length, HA_READ_KEY_EXACT);
+ }
+ else
+ {
+ /* otherwise, get the old record ref as obtained in ::position */
+ memcpy(buf, pos, ref_length);
+ result= 0;
+ }
+ table->status= result ? STATUS_NOT_FOUND : 0;
+ DBUG_RETURN(result);
+}
+
+
+/*
+ ::info() is used to return information to the optimizer.
+ Currently this table handler doesn't implement most of the fields
+ really needed. SHOW also makes use of this data
+ Another note, you will probably want to have the following in your
+ code:
+ if (records < 2)
+ records = 2;
+ The reason is that the server will optimize for cases of only a single
+ record. If in a table scan you don't know the number of records
+ it will probably be better to set records to two so you can return
+ as many records as you need.
+ Along with records a few more variables you may wish to set are:
+ records
+ deleted
+ data_file_length
+ index_file_length
+ delete_length
+ check_time
+ Take a look at the public variables in handler.h for more information.
+
+ Called in:
+ filesort.cc
+ ha_heap.cc
+ item_sum.cc
+ opt_sum.cc
+ sql_delete.cc
+ sql_delete.cc
+ sql_derived.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_table.cc
+ sql_union.cc
+ sql_update.cc
+
+*/
+
+int ha_federatedx::info(uint flag)
+{
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ uint error_code;
+ federatedx_io *tmp_io= 0;
+ DBUG_ENTER("ha_federatedx::info");
+
+ error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+
+ /* we want not to show table status if not needed to do so */
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO))
+ {
+ if ((error_code= txn->acquire(share, TRUE, &tmp_io)))
+ goto fail;
+ }
+
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST))
+ {
+ /*
+ size of IO operations (This is based on a good guess, no high science
+ involved)
+ */
+ if (flag & HA_STATUS_CONST)
+ stats.block_size= 4096;
+
+ if (tmp_io->table_metadata(&stats, share->table_name,
+ share->table_name_length, flag))
+ goto error;
+ }
+
+ if (flag & HA_STATUS_AUTO)
+ stats.auto_increment_value= tmp_io->last_insert_id();
+
+ /*
+ If ::info created it's own transaction, close it. This happens in case
+ of show table status;
+ */
+ txn->release(&tmp_io);
+
+ DBUG_RETURN(0);
+
+error:
+ if (tmp_io)
+ {
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ tmp_io->error_code(), tmp_io->error_str()));
+ my_error(error_code, MYF(0), error_buffer);
+ }
+ else
+ if (remote_error_number != -1 /* error already reported */)
+ {
+ error_code= remote_error_number;
+ my_error(error_code, MYF(0), ER(error_code));
+ }
+fail:
+ txn->release(&tmp_io);
+ DBUG_RETURN(error_code);
+}
+
+
+/**
+ @brief Handles extra signals from MySQL server
+
+ @param[in] operation Hint for storage engine
+
+ @return Operation Status
+ @retval 0 OK
+ */
+int ha_federatedx::extra(ha_extra_function operation)
+{
+ DBUG_ENTER("ha_federatedx::extra");
+ switch (operation) {
+ case HA_EXTRA_IGNORE_DUP_KEY:
+ ignore_duplicates= TRUE;
+ break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ insert_dup_update= FALSE;
+ ignore_duplicates= FALSE;
+ break;
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ replace_duplicates= TRUE;
+ break;
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ /*
+ We use this flag to ensure that we do not create an "INSERT IGNORE"
+ statement when inserting new rows into the remote table.
+ */
+ replace_duplicates= FALSE;
+ break;
+ case HA_EXTRA_INSERT_WITH_UPDATE:
+ insert_dup_update= TRUE;
+ break;
+ default:
+ /* do nothing */
+ DBUG_PRINT("info",("unhandled operation: %d", (uint) operation));
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Reset state of file to after 'open'.
+
+ @detail This function is called after every statement for all tables
+ used by that statement.
+
+ @return Operation status
+ @retval 0 OK
+*/
+
+int ha_federatedx::reset(void)
+{
+ insert_dup_update= FALSE;
+ ignore_duplicates= FALSE;
+ replace_duplicates= FALSE;
+ return 0;
+}
+
+
+/*
+ Used to delete all rows in a table. Both for cases of truncate and
+ for cases where the optimizer realizes that all rows will be
+ removed as a result of a SQL statement.
+
+ Called from item_sum.cc by Item_func_group_concat::clear(),
+ Item_sum_count_distinct::clear(), and Item_func_group_concat::clear().
+ Called from sql_delete.cc by mysql_delete().
+ Called from sql_select.cc by JOIN::reinit().
+ Called from sql_union.cc by st_select_lex_unit::exec().
+*/
+
+int ha_federatedx::delete_all_rows()
+{
+ char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ int error;
+ DBUG_ENTER("ha_federatedx::delete_all_rows");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("TRUNCATE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+
+ /* no need for savepoint in autocommit mode */
+ if (!(ha_thd()->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ txn->stmt_autocommit();
+
+ /*
+ TRUNCATE won't return anything in mysql_affected_rows
+ */
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ stats.deleted+= stats.records;
+ stats.records= 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ The idea with handler::store_lock() is the following:
+
+ The statement decided which locks we should need for the table
+ for updates/deletes/inserts we get WRITE locks, for SELECT... we get
+ read locks.
+
+ Before adding the lock into the table lock handler (see thr_lock.c)
+ mysqld calls store lock with the requested locks. Store lock can now
+ modify a write lock to a read lock (or some other lock), ignore the
+ lock (if we don't want to use MySQL table locks at all) or add locks
+ for many tables (like we do when we are using a MERGE handler).
+
+ Berkeley DB for federatedx changes all WRITE locks to TL_WRITE_ALLOW_WRITE
+ (which signals that we are doing WRITES, but we are still allowing other
+ reader's and writer's.
+
+ When releasing locks, store_lock() are also called. In this case one
+ usually doesn't have to do anything.
+
+ In some exceptional cases MySQL may send a request for a TL_IGNORE;
+ This means that we are requesting the same lock as last time and this
+ should also be ignored. (This may happen when someone does a flush
+ table when we have opened a part of the tables, in which case mysqld
+ closes and reopens the tables and tries to get the same locks at last
+ time). In the future we will probably try to remove this.
+
+ Called from lock.cc by get_lock_data().
+*/
+
+THR_LOCK_DATA **ha_federatedx::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ DBUG_ENTER("ha_federatedx::store_lock");
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ {
+ /*
+ Here is where we get into the guts of a row level lock.
+ If TL_UNLOCK is set
+ If we are not doing a LOCK TABLE or DISCARD/IMPORT
+ TABLESPACE, then allow multiple writers
+ */
+
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
+ lock_type <= TL_WRITE) && !thd->in_lock_tables)
+ lock_type= TL_WRITE_ALLOW_WRITE;
+
+ /*
+ In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+ MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+ would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+ to t2. Convert the lock to a normal read lock to allow
+ concurrent inserts to t2.
+ */
+
+ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
+ lock_type= TL_READ;
+
+ lock.type= lock_type;
+ }
+
+ *to++= &lock;
+
+ DBUG_RETURN(to);
+}
+
+
+static int test_connection(MYSQL_THD thd, federatedx_io *io,
+ FEDERATEDX_SHARE *share)
+{
+ char buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String str(buffer, sizeof(buffer), &my_charset_bin);
+ FEDERATEDX_IO_RESULT *resultset= NULL;
+ int retval;
+
+ str.length(0);
+ str.append(STRING_WITH_LEN("SELECT * FROM "));
+ append_identifier(thd, &str, share->table_name,
+ share->table_name_length);
+ str.append(STRING_WITH_LEN(" WHERE 1=0"));
+
+ if ((retval= io->query(str.ptr(), str.length())))
+ {
+ my_sprintf(buffer, (buffer,
+ "database: '%s' username: '%s' hostname: '%s'",
+ share->database, share->username, share->hostname));
+ DBUG_PRINT("info", ("error-code: %d", io->error_code()));
+ my_error(ER_CANT_CREATE_FEDERATED_TABLE, MYF(0), buffer);
+ }
+ else
+ resultset= io->store_result();
+
+ io->free_result(resultset);
+
+ return retval;
+}
+
+/*
+ create() does nothing, since we have no local setup of our own.
+ FUTURE: We should potentially connect to the foreign database and
+*/
+
+int ha_federatedx::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int retval;
+ THD *thd= current_thd;
+ FEDERATEDX_SHARE tmp_share; // Only a temporary share, to test the url
+ federatedx_txn *tmp_txn;
+ federatedx_io *tmp_io= NULL;
+ DBUG_ENTER("ha_federatedx::create");
+
+ if ((retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1)))
+ goto error;
+
+ /* loopback socket connections hang due to LOCK_open mutex */
+ if ((!tmp_share.hostname || !strcmp(tmp_share.hostname,my_localhost)) &&
+ !tmp_share.port)
+ goto error;
+
+ /*
+ If possible, we try to use an existing network connection to
+ the remote server. To ensure that no new FEDERATEDX_SERVER
+ instance is created, we pass NULL in get_server() TABLE arg.
+ */
+ pthread_mutex_lock(&federatedx_mutex);
+ tmp_share.s= get_server(&tmp_share, NULL);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (tmp_share.s)
+ {
+ tmp_txn= get_txn(thd);
+ if (!(retval= tmp_txn->acquire(&tmp_share, TRUE, &tmp_io)))
+ {
+ retval= test_connection(thd, tmp_io, &tmp_share);
+ tmp_txn->release(&tmp_io);
+ }
+ free_server(tmp_txn, tmp_share.s);
+ }
+ else
+ {
+ FEDERATEDX_SERVER server;
+
+#ifdef NOT_YET
+ /*
+ Bug#25679
+ Ensure that we do not hold the LOCK_open mutex while attempting
+ to establish FederatedX connection to guard against a trivial
+ Denial of Service scenerio.
+ */
+ safe_mutex_assert_not_owner(&LOCK_open);
+#endif
+
+ fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset);
+
+#ifndef DBUG_OFF
+ pthread_mutex_init(&server.mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_lock(&server.mutex);
+#endif
+
+ tmp_io= federatedx_io::construct(thd->mem_root, &server);
+
+ retval= test_connection(thd, tmp_io, &tmp_share);
+
+#ifndef DBUG_OFF
+ pthread_mutex_unlock(&server.mutex);
+ pthread_mutex_destroy(&server.mutex);
+#endif
+
+ delete tmp_io;
+ }
+
+error:
+ DBUG_RETURN(retval);
+
+}
+
+
+int ha_federatedx::stash_remote_error()
+{
+ DBUG_ENTER("ha_federatedx::stash_remote_error()");
+ if (!io)
+ DBUG_RETURN(remote_error_number);
+ remote_error_number= io->error_code();
+ strmake(remote_error_buf, io->error_str(), sizeof(remote_error_buf)-1);
+ if (remote_error_number == ER_DUP_ENTRY ||
+ remote_error_number == ER_DUP_KEY)
+ DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
+ DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM);
+}
+
+
+bool ha_federatedx::get_error_message(int error, String* buf)
+{
+ DBUG_ENTER("ha_federatedx::get_error_message");
+ DBUG_PRINT("enter", ("error: %d", error));
+ if (error == HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM)
+ {
+ buf->append(STRING_WITH_LEN("Error on remote system: "));
+ buf->qs_append(remote_error_number);
+ buf->append(STRING_WITH_LEN(": "));
+ buf->append(remote_error_buf);
+
+ remote_error_number= 0;
+ remote_error_buf[0]= '\0';
+ }
+ DBUG_PRINT("exit", ("message: %s", buf->ptr()));
+ DBUG_RETURN(FALSE);
+}
+
+
+int ha_federatedx::start_stmt(MYSQL_THD thd, thr_lock_type lock_type)
+{
+ DBUG_ENTER("ha_federatedx::start_stmt");
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if (!txn->in_transaction())
+ {
+ txn->stmt_begin();
+ trans_register_ha(thd, FALSE, ht);
+ }
+ DBUG_RETURN(0);
+}
+
+
+int ha_federatedx::external_lock(MYSQL_THD thd, int lock_type)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::external_lock");
+
+ if (lock_type == F_UNLCK)
+ txn->release(&io);
+ else
+ {
+ txn= get_txn(thd);
+ if (!(error= txn->acquire(share, lock_type == F_RDLCK, &io)) &&
+ (lock_type == F_WRLCK || !io->is_autocommit()))
+ {
+ if (!thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ {
+ txn->stmt_begin();
+ trans_register_ha(thd, FALSE, ht);
+ }
+ else
+ {
+ txn->txn_begin();
+ trans_register_ha(thd, TRUE, ht);
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv)
+{
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_set");
+
+ if (txn && txn->has_connections())
+ {
+ if (txn->txn_begin())
+ trans_register_ha(thd, TRUE, hton);
+
+ txn->sp_acquire((ulong *) sv);
+
+ DBUG_ASSERT(1 < *(ulong *) sv);
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv)
+ {
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_rollback");
+
+ if (txn)
+ error= txn->sp_rollback((ulong *) sv);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv)
+{
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_release");
+
+ if (txn)
+ error= txn->sp_release((ulong *) sv);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::commit(handlerton *hton, MYSQL_THD thd, bool all)
+{
+ int return_val;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::commit");
+
+ if (all)
+ return_val= txn->txn_commit();
+ else
+ return_val= txn->stmt_commit();
+
+ DBUG_PRINT("info", ("error val: %d", return_val));
+ DBUG_RETURN(return_val);
+}
+
+
+int ha_federatedx::rollback(handlerton *hton, MYSQL_THD thd, bool all)
+{
+ int return_val;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::rollback");
+
+ if (all)
+ return_val= txn->txn_rollback();
+ else
+ return_val= txn->stmt_rollback();
+
+ DBUG_PRINT("info", ("error val: %d", return_val));
+ DBUG_RETURN(return_val);
+}
+
+struct st_mysql_storage_engine federatedx_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federatedx_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith",
+ "FederatedX pluggable storage engine",
+ PLUGIN_LICENSE_GPL,
+ federatedx_db_init, /* Plugin Init */
+ federatedx_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
=== added file 'storage/federatedx/ha_federatedx.h'
--- a/storage/federatedx/ha_federatedx.h 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ha_federatedx.h 2009-10-30 18:50:56 +0000
@@ -0,0 +1,446 @@
+/*
+Copyright (c) 2008, Patrick Galbraith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the name of Patrick Galbraith nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+class federatedx_io;
+
+/*
+ FEDERATEDX_SERVER will eventually be a structure that will be shared among
+ all FEDERATEDX_SHARE instances so that the federated server can minimise
+ the number of open connections. This will eventually lead to the support
+ of reliable XA federated tables.
+*/
+typedef struct st_fedrated_server {
+ MEM_ROOT mem_root;
+ uint use_count, io_count;
+
+ uchar *key;
+ uint key_length;
+
+ const char *scheme;
+ const char *hostname;
+ const char *username;
+ const char *password;
+ const char *database;
+ const char *socket;
+ ushort port;
+
+ const char *csname;
+
+ pthread_mutex_t mutex;
+ federatedx_io *idle_list;
+} FEDERATEDX_SERVER;
+
+/*
+ Please read ha_exmple.cc before reading this file.
+ Please keep in mind that the federatedx storage engine implements all methods
+ that are required to be implemented. handler.h has a full list of methods
+ that you can implement.
+*/
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+#include <mysql.h>
+
+/*
+ handler::print_error has a case statement for error numbers.
+ This value is (10000) is far out of range and will envoke the
+ default: case.
+ (Current error range is 120-159 from include/my_base.h)
+*/
+#define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000
+
+#define FEDERATEDX_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5
+#define FEDERATEDX_RECORDS_IN_RANGE 2
+#define FEDERATEDX_MAX_KEY_LENGTH 3500 // Same as innodb
+
+/*
+ FEDERATEDX_SHARE is a structure that will be shared amoung all open handlers
+ The example implements the minimum of what you will probably need.
+*/
+typedef struct st_federatedx_share {
+ MEM_ROOT mem_root;
+
+ bool parsed;
+ /* this key is unique db/tablename */
+ const char *share_key;
+ /*
+ the primary select query to be used in rnd_init
+ */
+ char *select_query;
+ /*
+ remote host info, parse_url supplies
+ */
+ char *server_name;
+ char *connection_string;
+ char *scheme;
+ char *hostname;
+ char *username;
+ char *password;
+ char *database;
+ char *table_name;
+ char *table;
+ char *socket;
+ char *sport;
+ int share_key_length;
+ ushort port;
+
+ uint table_name_length, server_name_length, connect_string_length;
+ uint use_count;
+ THR_LOCK lock;
+ FEDERATEDX_SERVER *s;
+} FEDERATEDX_SHARE;
+
+
+typedef struct st_federatedx_result FEDERATEDX_IO_RESULT;
+typedef struct st_federatedx_row FEDERATEDX_IO_ROW;
+typedef ptrdiff_t FEDERATEDX_IO_OFFSET;
+
+class federatedx_io
+{
+ friend class federatedx_txn;
+ FEDERATEDX_SERVER * const server;
+ federatedx_io **owner_ptr;
+ federatedx_io *txn_next;
+ federatedx_io *idle_next;
+ bool active; /* currently participating in a transaction */
+ bool busy; /* in use by a ha_federated instance */
+ bool readonly;/* indicates that no updates have occurred */
+
+protected:
+ void set_active(bool new_active)
+ { active= new_active; }
+public:
+ federatedx_io(FEDERATEDX_SERVER *);
+ virtual ~federatedx_io();
+
+ bool is_readonly() const { return readonly; }
+ bool is_active() const { return active; }
+
+ const char * get_charsetname() const
+ { return server->csname ? server->csname : "latin1"; }
+
+ const char * get_hostname() const { return server->hostname; }
+ const char * get_username() const { return server->username; }
+ const char * get_password() const { return server->password; }
+ const char * get_database() const { return server->database; }
+ ushort get_port() const { return server->port; }
+ const char * get_socket() const { return server->socket; }
+
+ static bool handles_scheme(const char *scheme);
+ static federatedx_io *construct(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+
+ static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
+ { return alloc_root(mem_root, size); }
+ static void operator delete(void *ptr, size_t size)
+ { TRASH(ptr, size); }
+
+ virtual int query(const char *buffer, uint length)=0;
+ virtual FEDERATEDX_IO_RESULT *store_result()=0;
+
+ virtual size_t max_query_size() const=0;
+
+ virtual my_ulonglong affected_rows() const=0;
+ virtual my_ulonglong last_insert_id() const=0;
+
+ virtual int error_code()=0;
+ virtual const char *error_str()=0;
+
+ virtual void reset()=0;
+ virtual int commit()=0;
+ virtual int rollback()=0;
+
+ virtual int savepoint_set(ulong sp)=0;
+ virtual ulong savepoint_release(ulong sp)=0;
+ virtual ulong savepoint_rollback(ulong sp)=0;
+ virtual void savepoint_restrict(ulong sp)=0;
+
+ virtual ulong last_savepoint() const=0;
+ virtual ulong actual_savepoint() const=0;
+ virtual bool is_autocommit() const=0;
+
+ virtual bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag) = 0;
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column)=0;
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const=0;
+};
+
+
+class federatedx_txn
+{
+ federatedx_io *txn_list;
+ ulong savepoint_level;
+ ulong savepoint_stmt;
+ ulong savepoint_next;
+
+ void release_scan();
+public:
+ federatedx_txn();
+ ~federatedx_txn();
+
+ bool has_connections() const { return txn_list != NULL; }
+ bool in_transaction() const { return savepoint_next != 0; }
+ int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io);
+ void release(federatedx_io **io);
+ void close(FEDERATEDX_SERVER *);
+
+ bool txn_begin();
+ int txn_commit();
+ int txn_rollback();
+
+ bool sp_acquire(ulong *save);
+ int sp_rollback(ulong *save);
+ int sp_release(ulong *save);
+
+ bool stmt_begin();
+ int stmt_commit();
+ int stmt_rollback();
+ void stmt_autocommit();
+};
+
+
+/*
+ Class definition for the storage engine
+*/
+class ha_federatedx: public handler
+{
+ friend int federatedx_db_init(void *p);
+
+ THR_LOCK_DATA lock; /* MySQL lock */
+ FEDERATEDX_SHARE *share; /* Shared lock info */
+ federatedx_txn *txn;
+ federatedx_io *io;
+ FEDERATEDX_IO_RESULT *stored_result;
+ uint fetch_num; // stores the fetch num
+ FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position()
+ int remote_error_number;
+ char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ bool ignore_duplicates, replace_duplicates;
+ bool insert_dup_update;
+ DYNAMIC_STRING bulk_insert;
+
+private:
+ /*
+ return 0 on success
+ return errorcode otherwise
+ */
+ uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row,
+ FEDERATEDX_IO_RESULT *result);
+ bool create_where_from_key(String *to, KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool records_in_range, bool eq_range);
+ int stash_remote_error();
+
+ federatedx_txn *get_txn(THD *thd, bool no_create= FALSE);
+
+ static int disconnect(handlerton *hton, MYSQL_THD thd);
+ static int savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int commit(handlerton *hton, MYSQL_THD thd, bool all);
+ static int rollback(handlerton *hton, MYSQL_THD thd, bool all);
+
+ bool append_stmt_insert(String *query);
+
+ int read_next(uchar *buf, FEDERATEDX_IO_RESULT *result);
+ int index_read_idx_with_result_set(uchar *buf, uint index,
+ const uchar *key,
+ uint key_len,
+ ha_rkey_function find_flag,
+ FEDERATEDX_IO_RESULT **result);
+ int real_query(const char *query, uint length);
+ int real_connect(FEDERATEDX_SHARE *my_share, uint create_flag);
+public:
+ ha_federatedx(handlerton *hton, TABLE_SHARE *table_arg);
+ ~ha_federatedx() {}
+ /* The name that will be used for display purposes */
+ const char *table_type() const { return "FEDERATED"; }
+ /*
+ The name of the index type that will be used for display
+ don't implement this method unless you really have indexes
+ */
+ // perhaps get index type
+ const char *index_type(uint inx) { return "REMOTE"; }
+ const char **bas_ext() const;
+ /*
+ This is a list of flags that says what the storage engine
+ implements. The current table flags are documented in
+ handler.h
+ */
+ ulonglong table_flags() const
+ {
+ /* fix server to be able to get remote server table flags */
+ 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_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
+ HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
+ }
+ /*
+ This is a bitmap of flags that says how the storage engine
+ implements indexes. The current index flags are documented in
+ handler.h. If you do not implement indexes, just return zero
+ here.
+
+ part is the key part to check. First key part is 0
+ If all_parts it's set, MySQL want to know the flags for the combined
+ index up to and including 'part'.
+ */
+ /* fix server to be able to get remote server index flags */
+ ulong index_flags(uint inx, uint part, bool all_parts) const
+ {
+ return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
+ }
+ uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_parts() const { return MAX_REF_PARTS; }
+ uint max_supported_key_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
+ uint max_supported_key_part_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
+ /*
+ Called in test_quick_select to determine if indexes should be used.
+ Normally, we need to know number of blocks . For federatedx we need to
+ know number of blocks on remote side, and number of packets and blocks
+ on the network side (?)
+ Talk to Kostja about this - how to get the
+ number of rows * ...
+ disk scan time on other side (block size, size of the row) + network time ...
+ The reason for "records * 1000" is that such a large number forces
+ this to use indexes "
+ */
+ double scan_time()
+ {
+ DBUG_PRINT("info", ("records %lu", (ulong) stats.records));
+ return (double)(stats.records*1000);
+ }
+ /*
+ The next method will never be called if you do not implement indexes.
+ */
+ double read_time(uint index, uint ranges, ha_rows rows)
+ {
+ /*
+ Per Brian, this number is bugus, but this method must be implemented,
+ and at a later date, he intends to document this issue for handler code
+ */
+ return (double) rows / 20.0+1;
+ }
+
+ const key_map *keys_to_use_for_scanning() { return &key_map_full; }
+ /*
+ Everything below are methods that we implment in ha_federatedx.cc.
+
+ Most of these methods are not obligatory, skip them and
+ MySQL will treat them as not implemented
+ */
+ int open(const char *name, int mode, uint test_if_locked); // required
+ int close(void); // required
+
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert(bool abort);
+ int write_row(uchar *buf);
+ int update_row(const uchar *old_data, uchar *new_data);
+ int delete_row(const uchar *buf);
+ int index_init(uint keynr, bool sorted);
+ ha_rows estimate_rows_upper_bound();
+ int index_read(uchar *buf, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_idx(uchar *buf, uint idx, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_next(uchar *buf);
+ int index_end();
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
+ /*
+ unlike index_init(), rnd_init() can be called two times
+ without rnd_end() in between (it only makes sense if scan=1).
+ then the second call should prepare for the new table scan
+ (e.g if rnd_init allocates the cursor, second call should
+ position it to the start of the table, no need to deallocate
+ and allocate it again
+ */
+ int rnd_init(bool scan); //required
+ int rnd_end();
+ int rnd_next(uchar *buf); //required
+ int rnd_pos(uchar *buf, uchar *pos); //required
+ void position(const uchar *record); //required
+ int info(uint); //required
+ int extra(ha_extra_function operation);
+
+ void update_auto_increment(void);
+ int repair(THD* thd, HA_CHECK_OPT* check_opt);
+ int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+
+ int delete_all_rows(void);
+ int create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info); //required
+ ha_rows records_in_range(uint inx, key_range *start_key,
+ key_range *end_key);
+ uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type); //required
+ bool get_error_message(int error, String *buf);
+ int start_stmt(THD *thd, thr_lock_type lock_type);
+ int external_lock(THD *thd, int lock_type);
+ int reset(void);
+ int free_result(void);
+};
+
+extern const char ident_quote_char; // Character for quoting
+ // identifiers
+extern const char value_quote_char; // Character for quoting
+ // literals
+
+extern bool append_ident(String *string, const char *name, uint length,
+ const char quote_char);
+
+
+extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
=== added file 'storage/federatedx/plug.in'
--- a/storage/federatedx/plug.in 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/plug.in 2009-10-30 18:50:56 +0000
@@ -0,0 +1,5 @@
+MYSQL_STORAGE_ENGINE(federated,,[FederatedX Storage Engine],
+ [FederatedX Storage Engine], [max,max-no-ndb])
+MYSQL_PLUGIN_DYNAMIC(federated, [ha_federatedx.la])
+MYSQL_PLUGIN_STATIC(federated, [libfederatedx.a])
+MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federatedx.cc])
=== modified file 'storage/heap/hp_test2.c'
--- a/storage/heap/hp_test2.c 2008-03-29 08:02:54 +0000
+++ b/storage/heap/hp_test2.c 2009-08-28 16:21:54 +0000
@@ -62,11 +62,10 @@ int main(int argc, char *argv[])
HP_SHARE *tmp_share;
HP_KEYDEF keyinfo[MAX_KEYS];
HA_KEYSEG keyseg[MAX_KEYS*5];
- HEAP_PTR position;
+ HEAP_PTR UNINIT_VAR(position);
HP_CREATE_INFO hp_create_info;
CHARSET_INFO *cs= &my_charset_latin1;
MY_INIT(argv[0]); /* init my_sys library & pthreads */
- LINT_INIT(position);
filename= "test2";
filename2= "test2_2";
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2009-09-07 20:50:10 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2009-10-16 22:57:48 +0000
@@ -2577,12 +2577,12 @@ ha_innobase::open(
}
/* Create buffers for packing the fields of a record. Why
- table->reclength did not work here? Obviously, because char
+ table->stored_rec_length did not work here? Obviously, because char
fields when packed actually became 1 byte longer, when we also
stored the string length as the first byte. */
upd_and_key_val_buff_len =
- table->s->reclength + table->s->max_key_length
+ table->s->stored_rec_length + table->s->max_key_length
+ MAX_REF_PARTS * 3;
if (!(uchar*) my_multi_malloc(MYF(MY_WME),
&upd_buff, upd_and_key_val_buff_len,
@@ -2657,7 +2657,7 @@ retry:
prebuilt = row_create_prebuilt(ib_table);
- prebuilt->mysql_row_len = table->s->reclength;
+ prebuilt->mysql_row_len = table->s->stored_rec_length;;
prebuilt->default_rec = table->s->default_values;
ut_ad(prebuilt->default_rec);
@@ -3360,11 +3360,11 @@ build_template(
dict_index_t* clust_index;
mysql_row_templ_t* templ;
Field* field;
- ulint n_fields;
+ ulint n_fields, n_stored_fields;
ulint n_requested_fields = 0;
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
- ulint i;
+ ulint i, sql_idx, innodb_idx=0;
/* byte offset of the end of last requested column */
ulint mysql_prefix_len = 0;
@@ -3425,11 +3425,12 @@ build_template(
}
n_fields = (ulint)table->s->fields; /* number of columns */
+ n_stored_fields= (ulint)table->s->stored_fields; /* number of stored columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
mem_alloc_noninline(
- n_fields * sizeof(mysql_row_templ_t));
+ n_stored_fields * sizeof(mysql_row_templ_t));
}
prebuilt->template_type = templ_type;
@@ -3439,15 +3440,17 @@ build_template(
/* Note that in InnoDB, i is the column number. MySQL calls columns
'fields'. */
- for (i = 0; i < n_fields; i++) {
+ for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
templ = prebuilt->mysql_template + n_requested_fields;
- field = table->field[i];
+ field = table->field[sql_idx];
+ if (!field->stored_in_db)
+ goto skip_field;
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
/* Decide which columns we should fetch
and which we can skip. */
register const ibool index_contains_field =
- dict_index_contains_col_or_prefix(index, i);
+ dict_index_contains_col_or_prefix(index, innodb_idx);
if (!index_contains_field && prebuilt->read_just_key) {
/* If this is a 'key read', we do not need
@@ -3462,8 +3465,8 @@ build_template(
goto include_field;
}
- if (bitmap_is_set(table->read_set, i) ||
- bitmap_is_set(table->write_set, i)) {
+ if (bitmap_is_set(table->read_set, sql_idx) ||
+ bitmap_is_set(table->write_set, sql_idx)) {
/* This field is needed in the query */
goto include_field;
@@ -3471,7 +3474,7 @@ build_template(
if (fetch_primary_key_cols
&& dict_table_col_in_clustered_key(
- index->table, i)) {
+ index->table, innodb_idx)) {
/* This field is needed in the query */
goto include_field;
@@ -3484,14 +3487,14 @@ build_template(
include_field:
n_requested_fields++;
- templ->col_no = i;
+ templ->col_no = innodb_idx;
if (index == clust_index) {
templ->rec_field_no = dict_col_get_clust_pos_noninline(
- &index->table->cols[i], index);
+ &index->table->cols[innodb_idx], index);
} else {
templ->rec_field_no = dict_index_get_nth_col_pos(
- index, i);
+ index, innodb_idx);
}
if (templ->rec_field_no == ULINT_UNDEFINED) {
@@ -3517,7 +3520,7 @@ include_field:
mysql_prefix_len = templ->mysql_col_offset
+ templ->mysql_col_len;
}
- templ->type = index->table->cols[i].mtype;
+ templ->type = index->table->cols[innodb_idx].mtype;
templ->mysql_type = (ulint)field->type();
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
@@ -3526,16 +3529,18 @@ include_field:
}
templ->charset = dtype_get_charset_coll_noninline(
- index->table->cols[i].prtype);
- templ->mbminlen = index->table->cols[i].mbminlen;
- templ->mbmaxlen = index->table->cols[i].mbmaxlen;
- templ->is_unsigned = index->table->cols[i].prtype
+ index->table->cols[innodb_idx].prtype);
+ templ->mbminlen = index->table->cols[innodb_idx].mbminlen;
+ templ->mbmaxlen = index->table->cols[innodb_idx].mbmaxlen;
+ templ->is_unsigned = index->table->cols[innodb_idx].prtype
& DATA_UNSIGNED;
if (templ->type == DATA_BLOB) {
prebuilt->templ_contains_blob = TRUE;
}
skip_field:
- ;
+ if (field->stored_in_db) {
+ innodb_idx++;
+ }
}
prebuilt->n_template = n_requested_fields;
@@ -3998,7 +4003,7 @@ calc_row_difference(
ulint n_changed = 0;
dfield_t dfield;
dict_index_t* clust_index;
- uint i;
+ uint sql_idx, innodb_idx= 0;
n_fields = table->s->fields;
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
@@ -4006,8 +4011,10 @@ calc_row_difference(
/* We use upd_buff to convert changed fields */
buf = (byte*) upd_buff;
- for (i = 0; i < n_fields; i++) {
- field = table->field[i];
+ for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
+ field = table->field[sql_idx];
+ if (!field->stored_in_db)
+ continue;
o_ptr = (byte*) old_row + get_field_offset(table, field);
n_ptr = (byte*) new_row + get_field_offset(table, field);
@@ -4025,7 +4032,7 @@ calc_row_difference(
field_mysql_type = field->type();
- col_type = prebuilt->table->cols[i].mtype;
+ col_type = prebuilt->table->cols[innodb_idx].mtype;
switch (col_type) {
@@ -4080,7 +4087,7 @@ calc_row_difference(
/* Let us use a dummy dfield to make the conversion
from the MySQL column format to the InnoDB format */
- dict_col_copy_type_noninline(prebuilt->table->cols + i,
+ dict_col_copy_type_noninline(prebuilt->table->cols + innodb_idx,
&dfield.type);
if (n_len != UNIV_SQL_NULL) {
@@ -4101,9 +4108,11 @@ calc_row_difference(
ufield->exp = NULL;
ufield->field_no = dict_col_get_clust_pos_noninline(
- &prebuilt->table->cols[i], clust_index);
+ &prebuilt->table->cols[innodb_idx], clust_index);
n_changed++;
}
+ if (field->stored_in_db)
+ innodb_idx++;
}
uvect->n_fields = n_changed;
@@ -5088,7 +5097,7 @@ create_table_def(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
- table = dict_mem_table_create(table_name, 0, n_cols, flags);
+ table = dict_mem_table_create(table_name, 0, form->s->stored_fields, flags);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@@ -5097,6 +5106,8 @@ create_table_def(
for (i = 0; i < n_cols; i++) {
field = form->field[i];
+ if (!field->stored_in_db)
+ continue;
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
field);
@@ -5385,7 +5396,7 @@ ha_innobase::create(
}
#endif
- if (form->s->fields > 1000) {
+ if (form->s->stored_fields > 1000) {
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
but we play safe here */
@@ -5895,10 +5906,10 @@ ha_innobase::records_in_range(
KEY* key;
dict_index_t* index;
uchar* key_val_buff2 = (uchar*) my_malloc(
- table->s->reclength
+ table->s->stored_rec_length
+ table->s->max_key_length + 100,
MYF(MY_FAE));
- ulint buff2_len = table->s->reclength
+ ulint buff2_len = table->s->stored_rec_length
+ table->s->max_key_length + 100;
dtuple_t* range_start;
dtuple_t* range_end;
=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h 2009-04-24 11:28:46 +0000
+++ b/storage/innobase/handler/ha_innodb.h 2009-10-16 22:57:48 +0000
@@ -199,6 +199,7 @@ class ha_innobase: public handler
int cmp_ref(const uchar *ref1, const uchar *ref2);
bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
};
/* Some accessor functions which the InnoDB plugin needs, but which
=== modified file 'storage/myisam/ft_boolean_search.c'
--- a/storage/myisam/ft_boolean_search.c 2009-09-07 20:50:10 +0000
+++ b/storage/myisam/ft_boolean_search.c 2009-10-15 21:38:29 +0000
@@ -358,9 +358,8 @@ static int _ft2_search(FTB *ftb, FTB_WOR
int subkeys=1;
my_bool can_go_down;
MI_INFO *info=ftb->info;
- uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint UNINIT_VAR(off), extra=HA_FT_WLEN+info->s->base.rec_reflength;
uchar *lastkey_buf=ftbw->word+ftbw->off;
- LINT_INIT(off);
if (ftbw->flags & FTB_FLAG_TRUNC)
lastkey_buf+=ftbw->len;
=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc 2009-10-06 14:53:46 +0000
+++ b/storage/myisam/ha_myisam.cc 2009-10-17 19:12:28 +0000
@@ -252,7 +252,7 @@ int table2myisam(TABLE *table_arg, MI_KE
record= table_arg->record[0];
recpos= 0;
recinfo_pos= recinfo;
- while (recpos < (uint) share->reclength)
+ while (recpos < (uint) share->stored_rec_length)
{
Field **field, *found= 0;
minpos= share->reclength;
=== modified file 'storage/myisam/ha_myisam.h'
--- a/storage/myisam/ha_myisam.h 2009-09-07 20:50:10 +0000
+++ b/storage/myisam/ha_myisam.h 2009-10-16 22:57:48 +0000
@@ -133,6 +133,7 @@ class ha_myisam: public handler
int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
#ifdef HAVE_REPLICATION
int dump(THD* thd, int fd);
int net_read_dump(NET* net);
=== modified file 'storage/myisam/mi_check.c'
--- a/storage/myisam/mi_check.c 2009-06-29 21:03:30 +0000
+++ b/storage/myisam/mi_check.c 2009-10-15 21:38:29 +0000
@@ -140,11 +140,10 @@ int chk_del(HA_CHECK *param, register MI
{
reg2 ha_rows i;
uint delete_link_length;
- my_off_t empty,next_link,old_link;
+ my_off_t empty,next_link,UNINIT_VAR(old_link);
char buff[22],buff2[22];
DBUG_ENTER("chk_del");
- LINT_INIT(old_link);
param->record_checksum=0;
delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
info->s->rec_reflength+1);
@@ -940,11 +939,11 @@ static uint isam_key_length(MI_INFO *inf
int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend)
{
int error,got_error,flag;
- uint key,left_length,b_type,field;
+ uint key,UNINIT_VAR(left_length),b_type,field;
ha_rows records,del_blocks;
- my_off_t used,empty,pos,splits,start_recpos,
+ my_off_t used,empty,pos,splits,UNINIT_VAR(start_recpos),
del_length,link_used,start_block;
- uchar *record= 0, *to;
+ uchar *record= 0, *UNINIT_VAR(to);
char llbuff[22],llbuff2[22],llbuff3[22];
ha_checksum intern_record_checksum;
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
@@ -969,7 +968,6 @@ int chk_data_link(HA_CHECK *param, MI_IN
records=del_blocks=0;
used=link_used=splits=del_length=0;
intern_record_checksum=param->glob_crc=0;
- LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to);
got_error=error=0;
empty=info->s->pack.header_length;
@@ -1550,7 +1548,7 @@ int mi_repair(HA_CHECK *param, register
if (!param->using_global_keycache)
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
- param->use_buffers, 0, 0));
+ (size_t) param->use_buffers, 0, 0));
if (init_io_cache(¶m->read_cache,info->dfile,
(uint) param->read_buffer_length,
@@ -2227,9 +2225,8 @@ int mi_repair_by_sort(HA_CHECK *param, r
ulong *rec_per_key_part;
char llbuff[22];
MI_SORT_INFO sort_info;
- ulonglong key_map;
+ ulonglong UNINIT_VAR(key_map);
DBUG_ENTER("mi_repair_by_sort");
- LINT_INIT(key_map);
start_records=info->state->records;
got_error=1;
@@ -2651,11 +2648,10 @@ int mi_repair_parallel(HA_CHECK *param,
IO_CACHE new_data_cache; /* For non-quick repair. */
IO_CACHE_SHARE io_share;
MI_SORT_INFO sort_info;
- ulonglong key_map;
+ ulonglong UNINIT_VAR(key_map);
pthread_attr_t thr_attr;
ulong max_pack_reclength;
DBUG_ENTER("mi_repair_parallel");
- LINT_INIT(key_map);
start_records=info->state->records;
got_error=1;
@@ -3242,7 +3238,7 @@ static int sort_get_next_record(MI_SORT_
int parallel_flag;
uint found_record,b_type,left_length;
my_off_t pos;
- uchar *to;
+ uchar *UNINIT_VAR(to);
MI_BLOCK_INFO block_info;
MI_SORT_INFO *sort_info=sort_param->sort_info;
HA_CHECK *param=sort_info->param;
=== modified file 'storage/myisam/mi_create.c'
--- a/storage/myisam/mi_create.c 2009-01-15 22:25:53 +0000
+++ b/storage/myisam/mi_create.c 2009-10-15 21:38:29 +0000
@@ -38,7 +38,7 @@ int mi_create(const char *name,uint keys
MI_CREATE_INFO *ci,uint flags)
{
register uint i,j;
- File dfile,file;
+ File UNINIT_VAR(dfile),file;
int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
myf create_flag;
uint fields,length,max_key_length,packed,pack_bytes,pointer,real_length_diff,
=== modified file 'storage/myisam/mi_delete.c'
--- a/storage/myisam/mi_delete.c 2009-09-07 20:50:10 +0000
+++ b/storage/myisam/mi_delete.c 2009-10-15 21:38:29 +0000
@@ -221,7 +221,7 @@ static int d_search(register MI_INFO *in
uint length,nod_flag,search_key_length;
my_bool last_key;
uchar *leaf_buff,*keypos;
- my_off_t leaf_page,next_block;
+ my_off_t UNINIT_VAR(leaf_page),next_block;
uchar lastkey[HA_MAX_KEY_BUFF];
DBUG_ENTER("d_search");
DBUG_DUMP("page",(uchar*) anc_buff,mi_getint(anc_buff));
=== modified file 'storage/myisam/mi_dynrec.c'
--- a/storage/myisam/mi_dynrec.c 2009-09-07 20:50:10 +0000
+++ b/storage/myisam/mi_dynrec.c 2009-10-15 21:38:29 +0000
@@ -1419,16 +1419,14 @@ void _mi_store_blob_length(uchar *pos,ui
int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, uchar *buf)
{
int block_of_record;
- uint b_type,left_length;
- uchar *to;
+ uint b_type,UNINIT_VAR(left_length);
+ uchar *UNINIT_VAR(to);
MI_BLOCK_INFO block_info;
File file;
DBUG_ENTER("mi_read_dynamic_record");
if (filepos != HA_OFFSET_ERROR)
{
- LINT_INIT(to);
- LINT_INIT(left_length);
file=info->dfile;
block_of_record= 0; /* First block of record is numbered as zero. */
block_info.second_read= 0;
@@ -1697,13 +1695,12 @@ int _mi_read_rnd_dynamic_record(MI_INFO
{
int block_of_record, info_read, save_errno;
uint left_len,b_type;
- uchar *to;
+ uchar *UNINIT_VAR(to);
MI_BLOCK_INFO block_info;
MYISAM_SHARE *share=info->s;
DBUG_ENTER("_mi_read_rnd_dynamic_record");
info_read=0;
- LINT_INIT(to);
if (info->lock_type == F_UNLCK)
{
=== modified file 'storage/myisam/mi_open.c'
--- a/storage/myisam/mi_open.c 2009-09-07 20:50:10 +0000
+++ b/storage/myisam/mi_open.c 2009-10-15 21:38:29 +0000
@@ -709,7 +709,7 @@ err:
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
{
uint extra;
- uint32 old_length;
+ uint32 UNINIT_VAR(old_length);
LINT_INIT(old_length);
if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
=== modified file 'storage/myisam/mi_packrec.c'
--- a/storage/myisam/mi_packrec.c 2009-09-07 20:50:10 +0000
+++ b/storage/myisam/mi_packrec.c 2009-10-15 21:38:29 +0000
@@ -1364,7 +1364,7 @@ uint _mi_pack_get_block_info(MI_INFO *my
File file, my_off_t filepos)
{
uchar *header=info->header;
- uint head_length,ref_length;
+ uint head_length, UNINIT_VAR(ref_length);
LINT_INIT(ref_length);
if (file >= 0)
=== modified file 'storage/myisam/mi_search.c'
--- a/storage/myisam/mi_search.c 2009-05-19 09:28:05 +0000
+++ b/storage/myisam/mi_search.c 2009-10-15 21:38:29 +0000
@@ -28,9 +28,15 @@ int _mi_check_index(MI_INFO *info, int i
{
if (inx == -1) /* Use last index */
inx=info->lastinx;
- if (inx < 0 || ! mi_is_key_active(info->s->state.key_map, inx))
+ if (inx < 0)
{
- my_errno=HA_ERR_WRONG_INDEX;
+ my_errno= HA_ERR_WRONG_INDEX;
+ return -1;
+ }
+ if (!mi_is_key_active(info->s->state.key_map, inx))
+ {
+ my_errno= info->s->state.state.records ? HA_ERR_WRONG_INDEX :
+ HA_ERR_END_OF_FILE;
return -1;
}
if (info->lastinx != inx) /* Index changed */
@@ -240,12 +246,11 @@ int _mi_seq_search(MI_INFO *info, regist
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
uchar *buff, my_bool *last_key)
{
- int flag;
- uint nod_flag,length,not_used[2];
+ int UNINIT_VAR(flag);
+ uint nod_flag,UNINIT_VAR(length),not_used[2];
uchar t_buff[HA_MAX_KEY_BUFF],*end;
DBUG_ENTER("_mi_seq_search");
- LINT_INIT(flag); LINT_INIT(length);
end= page+mi_getint(page);
nod_flag=mi_test_if_nod(page);
page+=2+nod_flag;
=== modified file 'storage/myisam/mi_update.c'
--- a/storage/myisam/mi_update.c 2008-02-18 22:35:17 +0000
+++ b/storage/myisam/mi_update.c 2009-10-15 21:38:29 +0000
@@ -27,11 +27,8 @@ int mi_update(register MI_INFO *info, co
my_bool auto_key_changed=0;
ulonglong changed;
MYISAM_SHARE *share=info->s;
- ha_checksum old_checksum;
+ ha_checksum UNINIT_VAR(old_checksum);
DBUG_ENTER("mi_update");
- LINT_INIT(new_key);
- LINT_INIT(changed);
- LINT_INIT(old_checksum);
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
mi_print_error(info->s, HA_ERR_CRASHED);
=== modified file 'storage/myisam/sort.c'
--- a/storage/myisam/sort.c 2008-04-28 16:24:05 +0000
+++ b/storage/myisam/sort.c 2009-10-15 21:38:29 +0000
@@ -489,7 +489,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_p
{
MI_SORT_INFO *sort_info=sort_param->sort_info;
HA_CHECK *param=sort_info->param;
- ulong length, keys;
+ ulong UNINIT_VAR(length), keys;
ulong *rec_per_key_part=param->rec_per_key_part;
int got_error=sort_info->got_error;
uint i;
@@ -896,7 +896,7 @@ merge_buffers(MI_SORT_PARAM *info, uint
int error;
uint sort_length,maxcount;
ha_rows count;
- my_off_t to_start_filepos;
+ my_off_t UNINIT_VAR(to_start_filepos);
uchar *strpos;
BUFFPEK *buffpek,**refpek;
QUEUE queue;
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2009-09-17 23:01:09 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2009-10-15 21:38:29 +0000
@@ -147,7 +147,7 @@ static void split_file_name(const char *
extern "C" void myrg_print_wrong_table(const char *table_name)
{
- LEX_STRING db, name;
+ LEX_STRING db= {NULL, 0}, name;
char buf[FN_REFLEN];
split_file_name(table_name, &db, &name);
memcpy(buf, db.str, db.length);
=== modified file 'storage/myisammrg/myrg_open.c'
--- a/storage/myisammrg/myrg_open.c 2009-07-10 11:34:03 +0000
+++ b/storage/myisammrg/myrg_open.c 2009-08-28 16:21:54 +0000
@@ -37,7 +37,7 @@
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
int save_errno,errpos=0;
- uint files= 0, i, dir_length, length, key_parts, min_keys= 0;
+ uint files= 0, i, dir_length, length, UNINIT_VAR(key_parts), min_keys= 0;
ulonglong file_offset=0;
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
MYRG_INFO *m_info=0;
@@ -49,8 +49,6 @@ MYRG_INFO *myrg_open(const char *name, i
my_bool bad_children= FALSE;
DBUG_ENTER("myrg_open");
- LINT_INIT(key_parts);
-
bzero((char*) &file,sizeof(file));
if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,
MY_UNPACK_FILENAME|MY_APPEND_EXT),
=== modified file 'storage/myisammrg/myrg_rkey.c'
--- a/storage/myisammrg/myrg_rkey.c 2008-03-29 08:02:54 +0000
+++ b/storage/myisammrg/myrg_rkey.c 2009-08-28 16:21:54 +0000
@@ -38,16 +38,13 @@
int myrg_rkey(MYRG_INFO *info,uchar *buf,int inx, const uchar *key,
key_part_map keypart_map, enum ha_rkey_function search_flag)
{
- uchar *key_buff;
- uint pack_key_length;
- uint16 last_used_keyseg;
+ uchar *UNINIT_VAR(key_buff);
+ uint UNINIT_VAR(pack_key_length);
+ uint16 UNINIT_VAR(last_used_keyseg);
MYRG_TABLE *table;
MI_INFO *mi;
int err;
DBUG_ENTER("myrg_rkey");
- LINT_INIT(key_buff);
- LINT_INIT(pack_key_length);
- LINT_INIT(last_used_keyseg);
if (_myrg_init_queue(info,inx,search_flag))
DBUG_RETURN(my_errno);
=== modified file 'storage/ndb/include/mgmapi/ndb_logevent.h'
--- a/storage/ndb/include/mgmapi/ndb_logevent.h 2007-11-14 02:52:29 +0000
+++ b/storage/ndb/include/mgmapi/ndb_logevent.h 2009-08-28 15:06:59 +0000
@@ -272,6 +272,300 @@ extern "C" {
#endif
};
+ struct ndb_logevent_Connected {
+ unsigned node;
+ };
+
+ struct ndb_logevent_Disconnected {
+ unsigned node;
+ };
+
+ struct ndb_logevent_CommunicationClosed {
+ unsigned node;
+ };
+
+ struct ndb_logevent_CommunicationOpened {
+ unsigned node;
+ };
+
+ struct ndb_logevent_ConnectedApiVersion {
+ unsigned node;
+ unsigned version;
+ };
+
+ /* CHECKPOINT */
+ struct ndb_logevent_GlobalCheckpointStarted {
+ unsigned gci;
+ };
+ struct ndb_logevent_GlobalCheckpointCompleted {
+ unsigned gci;
+ };
+ struct ndb_logevent_LocalCheckpointStarted {
+ unsigned lci;
+ unsigned keep_gci;
+ unsigned restore_gci;
+ };
+ struct ndb_logevent_LocalCheckpointCompleted {
+ unsigned lci;
+ };
+ struct ndb_logevent_LCPStoppedInCalcKeepGci {
+ unsigned data;
+ };
+ struct ndb_logevent_LCPFragmentCompleted {
+ unsigned node;
+ unsigned table_id;
+ unsigned fragment_id;
+ };
+ struct ndb_logevent_UndoLogBlocked {
+ unsigned acc_count;
+ unsigned tup_count;
+ };
+
+ /* STARTUP */
+ struct ndb_logevent_NDBStartStarted {
+ unsigned version;
+ };
+ struct ndb_logevent_NDBStartCompleted {
+ unsigned version;
+ };
+ struct ndb_logevent_STTORRYRecieved {
+ };
+ struct ndb_logevent_StartPhaseCompleted {
+ unsigned phase;
+ unsigned starttype;
+ };
+ struct ndb_logevent_CM_REGCONF {
+ unsigned own_id;
+ unsigned president_id;
+ unsigned dynamic_id;
+ };
+ struct ndb_logevent_CM_REGREF {
+ unsigned own_id;
+ unsigned other_id;
+ unsigned cause;
+ };
+ struct ndb_logevent_FIND_NEIGHBOURS {
+ unsigned own_id;
+ unsigned left_id;
+ unsigned right_id;
+ unsigned dynamic_id;
+ };
+ struct ndb_logevent_NDBStopStarted {
+ unsigned stoptype;
+ };
+ struct ndb_logevent_NDBStopCompleted {
+ unsigned action;
+ unsigned signum;
+ };
+ struct ndb_logevent_NDBStopForced {
+ unsigned action;
+ unsigned signum;
+ unsigned error;
+ unsigned sphase;
+ unsigned extra;
+ };
+ struct ndb_logevent_NDBStopAborted {
+ };
+ struct ndb_logevent_StartREDOLog {
+ unsigned node;
+ unsigned keep_gci;
+ unsigned completed_gci;
+ unsigned restorable_gci;
+ };
+ struct ndb_logevent_StartLog {
+ unsigned log_part;
+ unsigned start_mb;
+ unsigned stop_mb;
+ unsigned gci;
+ };
+ struct ndb_logevent_UNDORecordsExecuted {
+ unsigned block;
+ unsigned data1;
+ unsigned data2;
+ unsigned data3;
+ unsigned data4;
+ unsigned data5;
+ unsigned data6;
+ unsigned data7;
+ unsigned data8;
+ unsigned data9;
+ unsigned data10;
+ };
+
+ /* NODERESTART */
+ struct ndb_logevent_NR_CopyDict {
+ };
+ struct ndb_logevent_NR_CopyDistr {
+ };
+ struct ndb_logevent_NR_CopyFragsStarted {
+ unsigned dest_node;
+ };
+ struct ndb_logevent_NR_CopyFragDone {
+ unsigned dest_node;
+ unsigned table_id;
+ unsigned fragment_id;
+ };
+ struct ndb_logevent_NR_CopyFragsCompleted {
+ unsigned dest_node;
+ };
+
+ struct ndb_logevent_NodeFailCompleted {
+ unsigned block; /* 0 = all */
+ unsigned failed_node;
+ unsigned completing_node; /* 0 = all */
+ };
+ struct ndb_logevent_NODE_FAILREP {
+ unsigned failed_node;
+ unsigned failure_state;
+ };
+ struct ndb_logevent_ArbitState {
+ unsigned code; /* code & state << 16 */
+ unsigned arbit_node;
+ unsigned ticket_0;
+ unsigned ticket_1;
+ /* TODO */
+ };
+ struct ndb_logevent_ArbitResult {
+ unsigned code; /* code & state << 16 */
+ unsigned arbit_node;
+ unsigned ticket_0;
+ unsigned ticket_1;
+ /* TODO */
+ };
+ struct ndb_logevent_GCP_TakeoverStarted {
+ };
+ struct ndb_logevent_GCP_TakeoverCompleted {
+ };
+ struct ndb_logevent_LCP_TakeoverStarted {
+ };
+ struct ndb_logevent_LCP_TakeoverCompleted {
+ unsigned state;
+ };
+
+ /* STATISTIC */
+ struct ndb_logevent_TransReportCounters {
+ unsigned trans_count;
+ unsigned commit_count;
+ unsigned read_count;
+ unsigned simple_read_count;
+ unsigned write_count;
+ unsigned attrinfo_count;
+ unsigned conc_op_count;
+ unsigned abort_count;
+ unsigned scan_count;
+ unsigned range_scan_count;
+ };
+ struct ndb_logevent_OperationReportCounters {
+ unsigned ops;
+ };
+ struct ndb_logevent_TableCreated {
+ unsigned table_id;
+ };
+ struct ndb_logevent_JobStatistic {
+ unsigned mean_loop_count;
+ };
+ struct ndb_logevent_SendBytesStatistic {
+ unsigned to_node;
+ unsigned mean_sent_bytes;
+ };
+ struct ndb_logevent_ReceiveBytesStatistic {
+ unsigned from_node;
+ unsigned mean_received_bytes;
+ };
+ struct ndb_logevent_MemoryUsage {
+ int gth;
+ /* union is for compatibility backward.
+ * page_size_kb member variable should be removed in the future
+ */
+ union {
+ unsigned page_size_kb;
+ unsigned page_size_bytes;
+ };
+ unsigned pages_used;
+ unsigned pages_total;
+ unsigned block;
+ };
+
+ /* ERROR */
+ struct ndb_logevent_TransporterError {
+ unsigned to_node;
+ unsigned code;
+ };
+ struct ndb_logevent_TransporterWarning {
+ unsigned to_node;
+ unsigned code;
+ };
+ struct ndb_logevent_MissedHeartbeat {
+ unsigned node;
+ unsigned count;
+ };
+ struct ndb_logevent_DeadDueToHeartbeat {
+ unsigned node;
+ };
+ struct ndb_logevent_WarningEvent {
+ /* TODO */
+ };
+
+ /* INFO */
+ struct ndb_logevent_SentHeartbeat {
+ unsigned node;
+ };
+ struct ndb_logevent_CreateLogBytes {
+ unsigned node;
+ };
+ struct ndb_logevent_InfoEvent {
+ /* TODO */
+ };
+ struct ndb_logevent_EventBufferStatus {
+ unsigned usage;
+ unsigned alloc;
+ unsigned max;
+ unsigned apply_gci_l;
+ unsigned apply_gci_h;
+ unsigned latest_gci_l;
+ unsigned latest_gci_h;
+ };
+
+ /** Log event data for @ref NDB_LE_BackupStarted */
+ struct ndb_logevent_BackupStarted {
+ unsigned starting_node;
+ unsigned backup_id;
+ };
+ /** Log event data @ref NDB_LE_BackupFailedToStart */
+ struct ndb_logevent_BackupFailedToStart {
+ unsigned starting_node;
+ unsigned error;
+ };
+ /** Log event data @ref NDB_LE_BackupCompleted */
+ struct ndb_logevent_BackupCompleted {
+ unsigned starting_node;
+ unsigned backup_id;
+ unsigned start_gci;
+ unsigned stop_gci;
+ unsigned n_records;
+ unsigned n_log_records;
+ unsigned n_bytes;
+ unsigned n_log_bytes;
+ };
+ /** Log event data @ref NDB_LE_BackupAborted */
+ struct ndb_logevent_BackupAborted {
+ unsigned starting_node;
+ unsigned backup_id;
+ unsigned error;
+ };
+ /** Log event data @ref NDB_LE_SingleUser */
+ struct ndb_logevent_SingleUser {
+ unsigned type;
+ unsigned node_id;
+ };
+ /** Log even data @ref NDB_LE_StartReport */
+ struct ndb_logevent_StartReport {
+ unsigned report_type;
+ unsigned remaining_time;
+ unsigned bitmask_size;
+ unsigned bitmask_data[1];
+ };
+
/**
* Structure to store and retrieve log event information.
* @see @ref secSLogEvents
@@ -305,354 +599,87 @@ extern "C" {
*/
union {
/* CONNECT */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } Connected;
-
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } Disconnected;
-
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } CommunicationClosed;
-
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } CommunicationOpened;
-
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- unsigned version;
- } ConnectedApiVersion;
+ struct ndb_logevent_Connected Connected;
+ struct ndb_logevent_Disconnected Disconnected;
+ struct ndb_logevent_CommunicationClosed CommunicationClosed;
+ struct ndb_logevent_CommunicationOpened CommunicationOpened;
+ struct ndb_logevent_ConnectedApiVersion ConnectedApiVersion;
/* CHECKPOINT */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned gci;
- } GlobalCheckpointStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned gci;
- } GlobalCheckpointCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned lci;
- unsigned keep_gci;
- unsigned restore_gci;
- } LocalCheckpointStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned lci;
- } LocalCheckpointCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned data;
- } LCPStoppedInCalcKeepGci;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- unsigned table_id;
- unsigned fragment_id;
- } LCPFragmentCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned acc_count;
- unsigned tup_count;
- } UndoLogBlocked;
+ struct ndb_logevent_GlobalCheckpointStarted GlobalCheckpointStarted;
+ struct ndb_logevent_GlobalCheckpointCompleted GlobalCheckpointCompleted;
+ struct ndb_logevent_LocalCheckpointStarted LocalCheckpointStarted;
+ struct ndb_logevent_LocalCheckpointCompleted LocalCheckpointCompleted;
+ struct ndb_logevent_LCPStoppedInCalcKeepGci LCPStoppedInCalcKeepGci;
+ struct ndb_logevent_LCPFragmentCompleted LCPFragmentCompleted;
+ struct ndb_logevent_UndoLogBlocked UndoLogBlocked;
/* STARTUP */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned version;
- } NDBStartStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned version;
- } NDBStartCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } STTORRYRecieved;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned phase;
- unsigned starttype;
- } StartPhaseCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned own_id;
- unsigned president_id;
- unsigned dynamic_id;
- } CM_REGCONF;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned own_id;
- unsigned other_id;
- unsigned cause;
- } CM_REGREF;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned own_id;
- unsigned left_id;
- unsigned right_id;
- unsigned dynamic_id;
- } FIND_NEIGHBOURS;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned stoptype;
- } NDBStopStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned action;
- unsigned signum;
- } NDBStopCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned action;
- unsigned signum;
- unsigned error;
- unsigned sphase;
- unsigned extra;
- } NDBStopForced;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } NDBStopAborted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- unsigned keep_gci;
- unsigned completed_gci;
- unsigned restorable_gci;
- } StartREDOLog;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned log_part;
- unsigned start_mb;
- unsigned stop_mb;
- unsigned gci;
- } StartLog;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned block;
- unsigned data1;
- unsigned data2;
- unsigned data3;
- unsigned data4;
- unsigned data5;
- unsigned data6;
- unsigned data7;
- unsigned data8;
- unsigned data9;
- unsigned data10;
- } UNDORecordsExecuted;
+ struct ndb_logevent_NDBStartStarted NDBStartStarted;
+ struct ndb_logevent_NDBStartCompleted NDBStartCompleted;
+ struct ndb_logevent_STTORRYRecieved STTORRYRecieved;
+ struct ndb_logevent_StartPhaseCompleted StartPhaseCompleted;
+ struct ndb_logevent_CM_REGCONF CM_REGCONF;
+ struct ndb_logevent_CM_REGREF CM_REGREF;
+ struct ndb_logevent_FIND_NEIGHBOURS FIND_NEIGHBOURS;
+ struct ndb_logevent_NDBStopStarted NDBStopStarted;
+ struct ndb_logevent_NDBStopCompleted NDBStopCompleted;
+ struct ndb_logevent_NDBStopForced NDBStopForced;
+ struct ndb_logevent_NDBStopAborted NDBStopAborted;
+ struct ndb_logevent_StartREDOLog StartREDOLog;
+ struct ndb_logevent_StartLog StartLog;
+ struct ndb_logevent_UNDORecordsExecuted UNDORecordsExecuted;
/* NODERESTART */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } NR_CopyDict;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } NR_CopyDistr;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned dest_node;
- } NR_CopyFragsStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned dest_node;
- unsigned table_id;
- unsigned fragment_id;
- } NR_CopyFragDone;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned dest_node;
- } NR_CopyFragsCompleted;
-
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned block; /* 0 = all */
- unsigned failed_node;
- unsigned completing_node; /* 0 = all */
- } NodeFailCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned failed_node;
- unsigned failure_state;
- } NODE_FAILREP;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned code; /* code & state << 16 */
- unsigned arbit_node;
- unsigned ticket_0;
- unsigned ticket_1;
- /* TODO */
- } ArbitState;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned code; /* code & state << 16 */
- unsigned arbit_node;
- unsigned ticket_0;
- unsigned ticket_1;
- /* TODO */
- } ArbitResult;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } GCP_TakeoverStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } GCP_TakeoverCompleted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- } LCP_TakeoverStarted;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned state;
- } LCP_TakeoverCompleted;
+ struct ndb_logevent_NR_CopyDict NR_CopyDict;
+ struct ndb_logevent_NR_CopyDistr NR_CopyDistr;
+ struct ndb_logevent_NR_CopyFragsStarted NR_CopyFragsStarted;
+ struct ndb_logevent_NR_CopyFragDone NR_CopyFragDone;
+ struct ndb_logevent_NR_CopyFragsCompleted NR_CopyFragsCompleted;
+
+ struct ndb_logevent_NodeFailCompleted NodeFailCompleted;
+ struct ndb_logevent_NODE_FAILREP NODE_FAILREP;
+ struct ndb_logevent_ArbitState ArbitState;
+ struct ndb_logevent_ArbitResult ArbitResult;
+ struct ndb_logevent_GCP_TakeoverStarted GCP_TakeoverStarted;
+ struct ndb_logevent_GCP_TakeoverCompleted GCP_TakeoverCompleted;
+ struct ndb_logevent_LCP_TakeoverStarted LCP_TakeoverStarted;
+ struct ndb_logevent_LCP_TakeoverCompleted LCP_TakeoverCompleted;
/* STATISTIC */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned trans_count;
- unsigned commit_count;
- unsigned read_count;
- unsigned simple_read_count;
- unsigned write_count;
- unsigned attrinfo_count;
- unsigned conc_op_count;
- unsigned abort_count;
- unsigned scan_count;
- unsigned range_scan_count;
- } TransReportCounters;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned ops;
- } OperationReportCounters;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned table_id;
- } TableCreated;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned mean_loop_count;
- } JobStatistic;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned to_node;
- unsigned mean_sent_bytes;
- } SendBytesStatistic;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned from_node;
- unsigned mean_received_bytes;
- } ReceiveBytesStatistic;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- int gth;
- /* union is for compatibility backward.
- * page_size_kb member variable should be removed in the future
- */
- union {
- unsigned page_size_kb;
- unsigned page_size_bytes;
- };
- unsigned pages_used;
- unsigned pages_total;
- unsigned block;
- } MemoryUsage;
+ struct ndb_logevent_TransReportCounters TransReportCounters;
+ struct ndb_logevent_OperationReportCounters OperationReportCounters;
+ struct ndb_logevent_TableCreated TableCreated;
+ struct ndb_logevent_JobStatistic JobStatistic;
+ struct ndb_logevent_SendBytesStatistic SendBytesStatistic;
+ struct ndb_logevent_ReceiveBytesStatistic ReceiveBytesStatistic;
+ struct ndb_logevent_MemoryUsage MemoryUsage;
/* ERROR */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned to_node;
- unsigned code;
- } TransporterError;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned to_node;
- unsigned code;
- } TransporterWarning;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- unsigned count;
- } MissedHeartbeat;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } DeadDueToHeartbeat;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- /* TODO */
- } WarningEvent;
+ struct ndb_logevent_TransporterError TransporterError;
+ struct ndb_logevent_TransporterWarning TransporterWarning;
+ struct ndb_logevent_MissedHeartbeat MissedHeartbeat;
+ struct ndb_logevent_DeadDueToHeartbeat DeadDueToHeartbeat;
+ struct ndb_logevent_WarningEvent WarningEvent;
/* INFO */
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } SentHeartbeat;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned node;
- } CreateLogBytes;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- /* TODO */
- } InfoEvent;
- /** Log event specific data for for corresponding NDB_LE_ log event */
- struct {
- unsigned usage;
- unsigned alloc;
- unsigned max;
- unsigned apply_gci_l;
- unsigned apply_gci_h;
- unsigned latest_gci_l;
- unsigned latest_gci_h;
- } EventBufferStatus;
+ struct ndb_logevent_SentHeartbeat SentHeartbeat;
+ struct ndb_logevent_CreateLogBytes CreateLogBytes;
+ struct ndb_logevent_InfoEvent InfoEvent;
+ struct ndb_logevent_EventBufferStatus EventBufferStatus;
/** Log event data for @ref NDB_LE_BackupStarted */
- struct {
- unsigned starting_node;
- unsigned backup_id;
- } BackupStarted;
+ struct ndb_logevent_BackupStarted BackupStarted;
/** Log event data @ref NDB_LE_BackupFailedToStart */
- struct {
- unsigned starting_node;
- unsigned error;
- } BackupFailedToStart;
+ struct ndb_logevent_BackupFailedToStart BackupFailedToStart;
/** Log event data @ref NDB_LE_BackupCompleted */
- struct {
- unsigned starting_node;
- unsigned backup_id;
- unsigned start_gci;
- unsigned stop_gci;
- unsigned n_records;
- unsigned n_log_records;
- unsigned n_bytes;
- unsigned n_log_bytes;
- } BackupCompleted;
+ struct ndb_logevent_BackupCompleted BackupCompleted;
/** Log event data @ref NDB_LE_BackupAborted */
- struct {
- unsigned starting_node;
- unsigned backup_id;
- unsigned error;
- } BackupAborted;
+ struct ndb_logevent_BackupAborted BackupAborted;
/** Log event data @ref NDB_LE_SingleUser */
- struct {
- unsigned type;
- unsigned node_id;
- } SingleUser;
+ struct ndb_logevent_SingleUser SingleUser;
/** Log even data @ref NDB_LE_StartReport */
- struct {
- unsigned report_type;
- unsigned remaining_time;
- unsigned bitmask_size;
- unsigned bitmask_data[1];
- } StartReport;
+ struct ndb_logevent_StartReport StartReport;
#ifndef DOXYGEN_FIX
};
#else
=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2008-01-04 10:34:23 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2009-09-01 12:32:26 +0000
@@ -7521,8 +7521,8 @@ void Dbdict::execGET_TABINFOREQ(Signal*
return;
}
releaseSections(signal);
-
- DictObject * old_ptr_p = old_ptr_p = get_object(tableName, len);
+
+ DictObject * old_ptr_p = get_object(tableName, len);
if(old_ptr_p)
obj_id = old_ptr_p->m_id;
} else {
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp 2007-08-27 18:58:49 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp 2009-09-02 11:45:48 +0000
@@ -106,8 +106,13 @@ void
AsyncFile::doStart()
{
// Stacksize for filesystem threads
- // An 8k stack should be enough
+#if !defined(DBUG_OFF) && defined (__hpux)
+ // Empirical evidence indicates at least 32k
+ const NDB_THREAD_STACKSIZE stackSize = 32768;
+#else
+ // Otherwise an 8k stack should be enough
const NDB_THREAD_STACKSIZE stackSize = 8192;
+#endif
char buf[16];
numAsyncFiles++;
=== modified file 'storage/ndb/src/mgmsrv/InitConfigFileParser.cpp'
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2007-05-24 10:24:36 +0000
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2009-09-01 12:32:26 +0000
@@ -208,11 +208,10 @@ InitConfigFileParser::run_config_rules(C
ctx.m_config->put("NoOfNodes", nNodes);
char tmpLine[MAX_LINE_LENGTH];
- BaseString::snprintf(tmpLine, MAX_LINE_LENGTH, "EXTERNAL SYSTEM_");
- strncat(tmpLine, system, MAX_LINE_LENGTH);
- strncat(tmpLine, ":NoOfConnections", MAX_LINE_LENGTH);
+ BaseString::snprintf(tmpLine, MAX_LINE_LENGTH,
+ "EXTERNAL SYSTEM_%s:NoOfConnections", system);
ctx.m_config->put(tmpLine, nExtConnections);
-
+
Config * ret = new Config();
ret->m_configValues = (struct ndb_mgm_configuration*)ctx.m_configValues.getConfigValues();
ret->m_oldConfig = ctx.m_config; ctx.m_config = 0;
=== modified file 'storage/pbxt/src/cache_xt.cc'
--- a/storage/pbxt/src/cache_xt.cc 2009-08-17 11:12:36 +0000
+++ b/storage/pbxt/src/cache_xt.cc 2009-10-30 18:50:56 +0000
@@ -374,7 +374,7 @@ xtPublic void xt_ind_release_handle(XTIn
{
DcHandleSlotPtr hs;
XTIndBlockPtr block = NULL;
- u_int hash_idx = NULL;
+ u_int hash_idx = 0;
DcSegmentPtr seg = NULL;
XTIndBlockPtr xblock;
@@ -1379,7 +1379,7 @@ xtPublic xtBool xt_ind_fetch(XTOpenTable
ASSERT_NS(iref->ir_xlock == 2);
#endif
if (!(block = ind_cac_fetch(ot, ind, address, &seg, TRUE)))
- return NULL;
+ return 0;
branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);
if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) {
=== modified file 'storage/pbxt/src/discover_xt.cc'
--- a/storage/pbxt/src/discover_xt.cc 2009-09-03 13:20:22 +0000
+++ b/storage/pbxt/src/discover_xt.cc 2009-10-16 22:57:48 +0000
@@ -1340,7 +1340,8 @@ int xt_create_table_frm(handlerton *hton
COLUMN_FORMAT_TYPE_FIXED,
#endif
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
- NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/))
+ NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/,
+ NULL /*vcol_info*/))
#endif
goto error;
=== modified file 'storage/xtradb/handler/ha_innodb.cc'
--- a/storage/xtradb/handler/ha_innodb.cc 2009-09-09 21:06:57 +0000
+++ b/storage/xtradb/handler/ha_innodb.cc 2009-10-16 22:57:48 +0000
@@ -3200,12 +3200,12 @@ ha_innobase::open(
}
/* Create buffers for packing the fields of a record. Why
- table->reclength did not work here? Obviously, because char
+ table->stored_rec_length did not work here? Obviously, because char
fields when packed actually became 1 byte longer, when we also
stored the string length as the first byte. */
upd_and_key_val_buff_len =
- table->s->reclength + table->s->max_key_length
+ table->s->stored_rec_length + table->s->max_key_length
+ MAX_REF_PARTS * 3;
if (!(uchar*) my_multi_malloc(MYF(MY_WME),
&upd_buff, upd_and_key_val_buff_len,
@@ -3280,7 +3280,7 @@ retry:
prebuilt = row_create_prebuilt(ib_table);
- prebuilt->mysql_row_len = table->s->reclength;
+ prebuilt->mysql_row_len = table->s->stored_rec_length;;
prebuilt->default_rec = table->s->default_values;
ut_ad(prebuilt->default_rec);
@@ -3996,11 +3996,11 @@ build_template(
dict_index_t* clust_index;
mysql_row_templ_t* templ;
Field* field;
- ulint n_fields;
+ ulint n_fields, n_stored_fields;
ulint n_requested_fields = 0;
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
- ulint i;
+ ulint i, sql_idx, innodb_idx=0;
/* byte offset of the end of last requested column */
ulint mysql_prefix_len = 0;
@@ -4061,10 +4061,11 @@ build_template(
}
n_fields = (ulint)table->s->fields; /* number of columns */
+ n_stored_fields= (ulint)table->s->stored_fields; /* number of stored columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
- mem_alloc(n_fields * sizeof(mysql_row_templ_t));
+ mem_alloc(n_stored_fields * sizeof(mysql_row_templ_t));
}
prebuilt->template_type = templ_type;
@@ -4074,15 +4075,17 @@ build_template(
/* Note that in InnoDB, i is the column number. MySQL calls columns
'fields'. */
- for (i = 0; i < n_fields; i++) {
+ for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
templ = prebuilt->mysql_template + n_requested_fields;
- field = table->field[i];
+ field = table->field[sql_idx];
+ if (!field->stored_in_db)
+ goto skip_field;
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
/* Decide which columns we should fetch
and which we can skip. */
register const ibool index_contains_field =
- dict_index_contains_col_or_prefix(index, i);
+ dict_index_contains_col_or_prefix(index, innodb_idx);
if (!index_contains_field && prebuilt->read_just_key) {
/* If this is a 'key read', we do not need
@@ -4097,8 +4100,8 @@ build_template(
goto include_field;
}
- if (bitmap_is_set(table->read_set, i) ||
- bitmap_is_set(table->write_set, i)) {
+ if (bitmap_is_set(table->read_set, sql_idx) ||
+ bitmap_is_set(table->write_set, sql_idx)) {
/* This field is needed in the query */
goto include_field;
@@ -4106,7 +4109,7 @@ build_template(
if (fetch_primary_key_cols
&& dict_table_col_in_clustered_key(
- index->table, i)) {
+ index->table, innodb_idx)) {
/* This field is needed in the query */
goto include_field;
@@ -4119,14 +4122,14 @@ build_template(
include_field:
n_requested_fields++;
- templ->col_no = i;
+ templ->col_no = innodb_idx;
if (index == clust_index) {
templ->rec_field_no = dict_col_get_clust_pos(
- &index->table->cols[i], index);
+ &index->table->cols[innodb_idx], index);
} else {
templ->rec_field_no = dict_index_get_nth_col_pos(
- index, i);
+ index, innodb_idx);
}
if (templ->rec_field_no == ULINT_UNDEFINED) {
@@ -4152,7 +4155,7 @@ include_field:
mysql_prefix_len = templ->mysql_col_offset
+ templ->mysql_col_len;
}
- templ->type = index->table->cols[i].mtype;
+ templ->type = index->table->cols[innodb_idx].mtype;
templ->mysql_type = (ulint)field->type();
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
@@ -4161,16 +4164,18 @@ include_field:
}
templ->charset = dtype_get_charset_coll(
- index->table->cols[i].prtype);
- templ->mbminlen = index->table->cols[i].mbminlen;
- templ->mbmaxlen = index->table->cols[i].mbmaxlen;
- templ->is_unsigned = index->table->cols[i].prtype
+ index->table->cols[innodb_idx].prtype);
+ templ->mbminlen = index->table->cols[innodb_idx].mbminlen;
+ templ->mbmaxlen = index->table->cols[innodb_idx].mbmaxlen;
+ templ->is_unsigned = index->table->cols[innodb_idx].prtype
& DATA_UNSIGNED;
if (templ->type == DATA_BLOB) {
prebuilt->templ_contains_blob = TRUE;
}
skip_field:
- ;
+ if (field->stored_in_db) {
+ innodb_idx++;
+ }
}
prebuilt->n_template = n_requested_fields;
@@ -4634,7 +4639,7 @@ calc_row_difference(
ulint n_changed = 0;
dfield_t dfield;
dict_index_t* clust_index;
- uint i;
+ uint sql_idx, innodb_idx= 0;
n_fields = table->s->fields;
clust_index = dict_table_get_first_index(prebuilt->table);
@@ -4642,8 +4647,10 @@ calc_row_difference(
/* We use upd_buff to convert changed fields */
buf = (byte*) upd_buff;
- for (i = 0; i < n_fields; i++) {
- field = table->field[i];
+ for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
+ field = table->field[sql_idx];
+ if (!field->stored_in_db)
+ continue;
o_ptr = (const byte*) old_row + get_field_offset(table, field);
n_ptr = (const byte*) new_row + get_field_offset(table, field);
@@ -4661,7 +4668,7 @@ calc_row_difference(
field_mysql_type = field->type();
- col_type = prebuilt->table->cols[i].mtype;
+ col_type = prebuilt->table->cols[innodb_idx].mtype;
switch (col_type) {
@@ -4716,7 +4723,7 @@ calc_row_difference(
/* Let us use a dummy dfield to make the conversion
from the MySQL column format to the InnoDB format */
- dict_col_copy_type(prebuilt->table->cols + i,
+ dict_col_copy_type(prebuilt->table->cols + innodb_idx,
dfield_get_type(&dfield));
if (n_len != UNIV_SQL_NULL) {
@@ -4735,9 +4742,11 @@ calc_row_difference(
ufield->exp = NULL;
ufield->orig_len = 0;
ufield->field_no = dict_col_get_clust_pos(
- &prebuilt->table->cols[i], clust_index);
+ &prebuilt->table->cols[innodb_idx], clust_index);
n_changed++;
}
+ if (field->stored_in_db)
+ innodb_idx++;
}
uvect->n_fields = n_changed;
@@ -5754,7 +5763,7 @@ create_table_def(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
- table = dict_mem_table_create(table_name, 0, n_cols, flags);
+ table = dict_mem_table_create(table_name, 0, form->s->stored_fields, flags);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@@ -5763,6 +5772,8 @@ create_table_def(
for (i = 0; i < n_cols; i++) {
field = form->field[i];
+ if (!field->stored_in_db)
+ continue;
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
field);
@@ -6224,7 +6235,7 @@ ha_innobase::create(
}
#endif
- if (form->s->fields > 1000) {
+ if (form->s->stored_fields > 1000) {
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
but we play safe here */
@@ -6890,10 +6901,10 @@ ha_innobase::records_in_range(
KEY* key;
dict_index_t* index;
uchar* key_val_buff2 = (uchar*) my_malloc(
- table->s->reclength
+ table->s->stored_rec_length
+ table->s->max_key_length + 100,
MYF(MY_FAE));
- ulint buff2_len = table->s->reclength
+ ulint buff2_len = table->s->stored_rec_length
+ table->s->max_key_length + 100;
dtuple_t* range_start;
dtuple_t* range_end;
=== modified file 'storage/xtradb/handler/ha_innodb.h'
--- a/storage/xtradb/handler/ha_innodb.h 2009-03-26 06:11:11 +0000
+++ b/storage/xtradb/handler/ha_innodb.h 2009-10-16 22:57:48 +0000
@@ -204,6 +204,7 @@ class ha_innobase: public handler
/** @} */
bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes);
+ bool check_if_supported_virtual_columns(void) { return TRUE; }
};
/* Some accessor functions which the InnoDB plugin needs, but which
=== modified file 'storage/xtradb/include/buf0buf.ic'
--- a/storage/xtradb/include/buf0buf.ic 2009-06-25 01:43:25 +0000
+++ b/storage/xtradb/include/buf0buf.ic 2009-10-30 18:50:56 +0000
@@ -1056,7 +1056,7 @@ buf_page_release(
buf_block_t* block, /* in: buffer block */
ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
- mtr_t* mtr) /* in: mtr */
+ mtr_t* mtr __attribute__((unused))) /* in: mtr */
{
ut_ad(block);
=== modified file 'storage/xtradb/include/srv0srv.h'
--- a/storage/xtradb/include/srv0srv.h 2009-08-10 22:36:10 +0000
+++ b/storage/xtradb/include/srv0srv.h 2009-10-31 19:22:50 +0000
@@ -116,8 +116,8 @@ extern ulint srv_log_file_size;
extern ulint srv_log_buffer_size;
extern ulong srv_flush_log_at_trx_commit;
-extern ulint srv_show_locks_held;
-extern ulint srv_show_verbose_locks;
+extern ulong srv_show_locks_held;
+extern ulong srv_show_verbose_locks;
/* The sort order table of the MySQL latin1_swedish_ci character set
collation */
@@ -166,11 +166,11 @@ extern ulint srv_fast_shutdown; /* If t
extern ibool srv_innodb_status;
extern unsigned long long srv_stats_sample_pages;
-extern ulint srv_stats_method;
+extern ulong srv_stats_method;
#define SRV_STATS_METHOD_NULLS_EQUAL 0
#define SRV_STATS_METHOD_NULLS_NOT_EQUAL 1
#define SRV_STATS_METHOD_IGNORE_NULLS 2
-extern ulint srv_stats_auto_update;
+extern ulong srv_stats_auto_update;
extern ibool srv_use_doublewrite_buf;
extern ibool srv_use_checksums;
@@ -183,19 +183,19 @@ extern ulong srv_max_purge_lag;
extern ulong srv_replication_delay;
-extern ulint srv_io_capacity;
+extern ulong srv_io_capacity;
extern long long srv_ibuf_max_size;
-extern ulint srv_ibuf_active_contract;
-extern ulint srv_ibuf_accel_rate;
-extern ulint srv_flush_neighbor_pages;
-extern ulint srv_enable_unsafe_group_commit;
-extern ulint srv_read_ahead;
-extern ulint srv_adaptive_checkpoint;
+extern ulong srv_ibuf_active_contract;
+extern ulong srv_ibuf_accel_rate;
+extern ulong srv_flush_neighbor_pages;
+extern ulong srv_enable_unsafe_group_commit;
+extern ulong srv_read_ahead;
+extern ulong srv_adaptive_checkpoint;
-extern ulint srv_expand_import;
+extern ulong srv_expand_import;
-extern ulint srv_extra_rsegments;
-extern ulint srv_dict_size_limit;
+extern ulong srv_extra_rsegments;
+extern ulong srv_dict_size_limit;
/*-------------------------------------------*/
extern ulint srv_n_rows_inserted;
=== modified file 'storage/xtradb/srv/srv0srv.c'
--- a/storage/xtradb/srv/srv0srv.c 2009-09-15 10:46:35 +0000
+++ b/storage/xtradb/srv/srv0srv.c 2009-10-31 19:22:50 +0000
@@ -160,8 +160,8 @@ UNIV_INTERN ulint srv_log_file_size = UL
UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
-UNIV_INTERN ulint srv_show_locks_held = 10;
-UNIV_INTERN ulint srv_show_verbose_locks = 0;
+UNIV_INTERN ulong srv_show_locks_held = 10;
+UNIV_INTERN ulong srv_show_verbose_locks = 0;
/* The sort order table of the MySQL latin1_swedish_ci character set
@@ -338,8 +338,8 @@ UNIV_INTERN ibool srv_innodb_status = FA
/* When estimating number of different key values in an index, sample
this many index pages */
UNIV_INTERN unsigned long long srv_stats_sample_pages = 8;
-UNIV_INTERN ulint srv_stats_method = 0;
-UNIV_INTERN ulint srv_stats_auto_update = 1;
+UNIV_INTERN ulong srv_stats_method = 0;
+UNIV_INTERN ulong srv_stats_auto_update = 1;
UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
UNIV_INTERN ibool srv_use_checksums = TRUE;
@@ -349,7 +349,7 @@ UNIV_INTERN int srv_query_thread_priorit
UNIV_INTERN ulong srv_replication_delay = 0;
-UNIV_INTERN ulint srv_io_capacity = 100;
+UNIV_INTERN ulong srv_io_capacity = 100;
/* Returns the number of IO operations that is X percent of the capacity.
PCT_IO(5) -> returns the number of IO operations that is 5% of the max
@@ -357,20 +357,20 @@ where max is srv_io_capacity. */
#define PCT_IO(pct) ((ulint) (srv_io_capacity * ((double) pct / 100.0)))
UNIV_INTERN long long srv_ibuf_max_size = 0;
-UNIV_INTERN ulint srv_ibuf_active_contract = 0; /* 0:disable 1:enable */
-UNIV_INTERN ulint srv_ibuf_accel_rate = 100;
+UNIV_INTERN ulong srv_ibuf_active_contract = 0; /* 0:disable 1:enable */
+UNIV_INTERN ulong srv_ibuf_accel_rate = 100;
#define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0)))
-UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */
+UNIV_INTERN ulong srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */
-UNIV_INTERN ulint srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */
-UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
-UNIV_INTERN ulint srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */
+UNIV_INTERN ulong srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */
+UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
+UNIV_INTERN ulong srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */
-UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
+UNIV_INTERN ulong srv_expand_import = 0; /* 0:disable 1:enable */
-UNIV_INTERN ulint srv_extra_rsegments = 0; /* extra rseg for users */
-UNIV_INTERN ulint srv_dict_size_limit = 0;
+UNIV_INTERN ulong srv_extra_rsegments = 0; /* extra rseg for users */
+UNIV_INTERN ulong srv_dict_size_limit = 0;
/*-------------------------------------------*/
UNIV_INTERN ulong srv_n_spin_wait_rounds = 20;
UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
=== modified file 'strings/ctype-ucs2.c'
--- a/strings/ctype-ucs2.c 2009-07-02 10:15:33 +0000
+++ b/strings/ctype-ucs2.c 2009-10-15 21:38:29 +0000
@@ -203,11 +203,10 @@ static int my_strnncoll_ucs2(CHARSET_INF
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t s_wc,t_wc;
+ my_wc_t UNINIT_VAR(s_wc),t_wc;
const uchar *se=s+slen;
const uchar *te=t+tlen;
MY_UNICASE_INFO **uni_plane= cs->caseinfo;
- LINT_INIT(s_wc);
while ( s < se && t < te )
{
@@ -318,12 +317,10 @@ static int my_strncasecmp_ucs2(CHARSET_I
const char *s, const char *t, size_t len)
{
int s_res,t_res;
- my_wc_t s_wc,t_wc;
+ my_wc_t UNINIT_VAR(s_wc),t_wc;
const char *se=s+len;
const char *te=t+len;
MY_UNICASE_INFO **uni_plane= cs->caseinfo;
- LINT_INIT(s_wc);
- LINT_INIT(t_wc);
while ( s < se && t < te )
{
@@ -1387,11 +1384,9 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t s_wc,t_wc;
+ my_wc_t UNINIT_VAR(s_wc),t_wc;
const uchar *se=s+slen;
const uchar *te=t+tlen;
- LINT_INIT(s_wc);
- LINT_INIT(t_wc);
while ( s < se && t < te )
{
=== modified file 'strings/ctype-utf8.c'
--- a/strings/ctype-utf8.c 2009-07-02 10:15:33 +0000
+++ b/strings/ctype-utf8.c 2009-10-15 21:38:29 +0000
@@ -2310,12 +2310,10 @@ static int my_strnncoll_utf8(CHARSET_INF
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t s_wc,t_wc;
+ my_wc_t UNINIT_VAR(s_wc), t_wc;
const uchar *se=s+slen;
const uchar *te=t+tlen;
MY_UNICASE_INFO **uni_plane= cs->caseinfo;
- LINT_INIT(s_wc);
- LINT_INIT(t_wc);
while ( s < se && t < te )
{
@@ -2382,11 +2380,9 @@ static int my_strnncollsp_utf8(CHARSET_I
my_bool diff_if_only_endspace_difference)
{
int s_res, t_res, res;
- my_wc_t s_wc,t_wc;
+ my_wc_t UNINIT_VAR(s_wc),t_wc;
const uchar *se= s+slen, *te= t+tlen;
MY_UNICASE_INFO **uni_plane= cs->caseinfo;
- LINT_INIT(s_wc);
- LINT_INIT(t_wc);
#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
diff_if_only_endspace_difference= 0;
=== modified file 'strings/decimal.c'
--- a/strings/decimal.c 2009-09-15 10:46:35 +0000
+++ b/strings/decimal.c 2009-10-15 21:38:29 +0000
@@ -1365,8 +1365,7 @@ int bin2decimal(const uchar *from, decim
if (intg0x)
{
int i=dig2bytes[intg0x];
- dec1 x;
- LINT_INIT(x);
+ dec1 UNINIT_VAR(x);
switch (i)
{
case 1: x=mi_sint1korr(from); break;
@@ -1407,8 +1406,7 @@ int bin2decimal(const uchar *from, decim
if (frac0x)
{
int i=dig2bytes[frac0x];
- dec1 x;
- LINT_INIT(x);
+ dec1 UNINIT_VAR(x);
switch (i)
{
case 1: x=mi_sint1korr(from); break;
@@ -1486,7 +1484,7 @@ decimal_round(decimal_t *from, decimal_t
decimal_round_mode mode)
{
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
- frac1=ROUND_UP(from->frac), round_digit,
+ frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit),
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
intg1=ROUND_UP(from->intg +
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
@@ -1495,7 +1493,6 @@ decimal_round(decimal_t *from, decimal_t
sanity(to);
- LINT_INIT(round_digit);
switch (mode) {
case HALF_UP:
case HALF_EVEN: round_digit=5; break;
@@ -2123,13 +2120,11 @@ static int do_div_mod(decimal_t *from1,
{
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
- error, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
+ UNINIT_VAR(error), i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
dec2 norm_factor, x, guess, y;
- LINT_INIT(error);
-
if (mod)
to=mod;
=== modified file 'support-files/mysql.spec.sh'
--- a/support-files/mysql.spec.sh 2009-09-15 12:12:51 +0000
+++ b/support-files/mysql.spec.sh 2009-10-15 21:38:29 +0000
@@ -926,7 +926,7 @@ fi
- Install plugin libraries in appropriate packages.
- Disable libdaemon_example and ftexample plugins.
-* Thu Aug 20 2009 Jonathan Perkin <jperkin@stripped>
+* Thu Aug 20 2009 Jonathan Perkin <jperkin(a)sun.com>
- Update variable used for mysql-test suite location to match source.
=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c 2009-10-26 11:35:42 +0000
+++ b/tests/mysql_client_test.c 2009-11-06 17:22:32 +0000
@@ -4267,7 +4267,7 @@ static void test_fetch_date()
myheader("test_fetch_date");
- /* Will not work if sql_mode is NO_ZERO_DATE (implicit if TRADITIONAL) /*/
+ /* Will not work if sql_mode is NO_ZERO_DATE (implicit if TRADITIONAL) */
rc= mysql_query(mysql, "SET SQL_MODE=''");
myquery(rc);
@@ -17004,7 +17004,7 @@ static void test_bug20023()
{
MYSQL con;
- int sql_big_selects_orig;
+ int sql_big_selects_orig= 0;
/*
Type of max_join_size is ha_rows, which might be ulong or off_t
depending on the platform or configure options. Preserve the string
@@ -17012,10 +17012,10 @@ static void test_bug20023()
*/
char max_join_size_orig[32];
- int sql_big_selects_2;
- int sql_big_selects_3;
- int sql_big_selects_4;
- int sql_big_selects_5;
+ int sql_big_selects_2= 0;
+ int sql_big_selects_3= 0;
+ int sql_big_selects_4= 0;
+ int sql_big_selects_5= 0;
char query_buffer[MAX_TEST_QUERY_LENGTH];
@@ -17154,7 +17154,7 @@ static void bug31418_impl()
MYSQL con;
my_bool is_null;
- int rc;
+ int rc= 0;
/* Create a new connection. */
=== modified file 'win/make_mariadb_win_dist'
--- a/win/make_mariadb_win_dist 2009-10-12 16:50:20 +0000
+++ b/win/make_mariadb_win_dist 2009-10-30 10:50:48 +0000
@@ -66,7 +66,7 @@ ls -lah $ZIPFILE
echo "$ZIPFILE is the Windows noinstall binary zip"
if [ $RES ] ; then
- echo "Archive contents differ from the standard file list, check the diff output above"
+ echo "Archive contents differ from the standard file list, check the diff output above"
else
echo "Archive contents match the standard list, OK"
fi
1
0
[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2763: Fixed typos of --engine help text.
by noreply@launchpad.net 12 Nov '09
by noreply@launchpad.net 12 Nov '09
12 Nov '09
Merge authors:
Hakan Küçükyılmaz (hakan-askmonty)
------------------------------------------------------------
revno: 2763 [merge]
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: maria-local-master
timestamp: Wed 2009-11-11 23:14:00 +0100
message:
Fixed typos of --engine help text.
modified:
client/mysqlslap.c
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription.
1
0