maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #01487
bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2732)
#At lp:maria/5.2 based on revid:psergey@xxxxxxxxxxxx-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@xxxxxxxx> - Federated
+
+Pluggable Storage Engine Skeleton setup
+
+Brian Aker <brian@xxxxxxxxx> | <brian@xxxxxxxxxxx> - 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@xxxxxxx>
- 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