developers
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 10 participants
- 6869 discussions

[Maria-developers] Rev 2783: merged in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2783 [merge]
revision-id: sergii(a)pisem.net-20100408210307-j82aap23b14h7j3t
parent: sergii(a)pisem.net-20100408171901-npw9ltfhwwma6kvi
parent: igor(a)askmonty.org-20100408205517-43ppipg5lrwlnk5u
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Thu 2010-04-08 23:03:07 +0200
message:
merged
modified:
sql/sql_select.cc sp1f-sql_select.cc-19700101030959-egb7whpkh76zzvikycs5nsnuviu4fdlb
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_select.cc 2010-04-08 21:03:07 +0000
@@ -2335,7 +2335,13 @@ JOIN::destroy()
tab->cleanup();
}
tmp_join->tmp_join= 0;
+ /*
+ We need to clean up tmp_table_param for reusable JOINs (having non-zero
+ and different from self tmp_join) because it's not being cleaned up
+ anywhere else (as we need to keep the join is reusable).
+ */
tmp_table_param.cleanup();
+ tmp_join->tmp_table_param.copy_field= 0;
DBUG_RETURN(tmp_join->destroy());
}
cond_equal= 0;
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2845: Fixed a problem of merge from mysql-5.1 baseline.
by noreply@launchpad.net 08 Apr '10
by noreply@launchpad.net 08 Apr '10
08 Apr '10
------------------------------------------------------------
revno: 2845
committer: Igor Babaev <igor(a)askmonty.org>
branch nick: maria-5.1
timestamp: Thu 2010-04-08 13:55:17 -0700
message:
Fixed a problem of merge from mysql-5.1 baseline.
modified:
sql/sql_select.cc
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (igor:2845)
by Igor Babaev 08 Apr '10
by Igor Babaev 08 Apr '10
08 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100408115657-lxjm4cpvi4zp81rk
2845 Igor Babaev 2010-04-08
Fixed a problem of merge from mysql-5.1 baseline.
modified:
sql/sql_select.cc
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-03-10 09:12:23 +0000
+++ b/sql/sql_select.cc 2010-04-08 20:55:17 +0000
@@ -2335,7 +2335,13 @@ JOIN::destroy()
tab->cleanup();
}
tmp_join->tmp_join= 0;
+ /*
+ We need to clean up tmp_table_param for reusable JOINs (having non-zero
+ and different from self tmp_join) because it's not being cleaned up
+ anywhere else (as we need to keep the join is reusable).
+ */
tmp_table_param.cleanup();
+ tmp_join->tmp_table_param.copy_field= 0;
DBUG_RETURN(tmp_join->destroy());
}
cond_equal= 0;
1
0

[Maria-developers] Rev 2782: fixes for buildbot: in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2782
revision-id: sergii(a)pisem.net-20100408171901-npw9ltfhwwma6kvi
parent: sergii(a)pisem.net-20100408135804-rel674ezvlwfj3ax
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Thu 2010-04-08 19:19:01 +0200
message:
fixes for buildbot:
update test results
fix compilation failure on windows
fix for ps-protocol
=== modified file 'mysql-test/r/plugin.result'
--- a/mysql-test/r/plugin.result 2010-04-08 12:10:05 +0000
+++ b/mysql-test/r/plugin.result 2010-04-08 17:19:01 +0000
@@ -102,4 +102,7 @@ SET SQL_MODE='';
CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
ERROR HY000: Incorrect value '10000000000000000000' for option 'ULL'
SET @@SQL_MODE=@OLD_SQL_MODE;
+select 1;
+1
+1
UNINSTALL PLUGIN example;
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-04-08 12:10:05 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-04-08 17:19:01 +0000
@@ -49,7 +49,7 @@ NULL mysql event modified 9 0000-00-00 0
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned select,insert,update,references
-NULL mysql event sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql event sql_mode 15 NO set 494 1482 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select,insert,update,references
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references
@@ -124,7 +124,7 @@ NULL mysql proc returns 10 NULL NO longb
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references
-NULL mysql proc sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql proc sql_mode 15 NO set 494 1482 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI select,insert,update,references
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references
@@ -330,7 +330,7 @@ NULL mysql event starts datetime NULL NU
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 494 1482 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -405,7 +405,7 @@ NULL mysql ndb_binlog_index schemaops bi
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 494 1482 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== modified file 'mysql-test/t/plugin.test'
--- a/mysql-test/t/plugin.test 2010-04-08 12:10:05 +0000
+++ b/mysql-test/t/plugin.test 2010-04-08 17:19:01 +0000
@@ -111,8 +110,14 @@ drop table t1;
SET SQL_MODE='';
--error ER_BAD_OPTION_VALUE
CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
-
SET @@SQL_MODE=@OLD_SQL_MODE;
-
+#
+# The only preparable statement above was CREATE TABLE.
+# We need to prepare another statement here to force the
+# previous one to be deallocated (mysqltest reuses the same handle)
+# and to unlock all thread-local plugin locks. Otherwise it won't
+# uninstall.
+#
+select 1;
UNINSTALL PLUGIN example;
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-04-08 13:07:43 +0000
+++ b/sql/mysqld.cc 2010-04-08 17:19:01 +0000
@@ -2683,8 +2683,9 @@ bugs.\n");
end:
#ifndef __WIN__
- /* On Windows, do not terminate, but pass control to exception filter */
exit(1);
+#else
+ /* On Windows, do not terminate, but pass control to the exception filter */;
#endif
}
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-04-08 09:52:53 +0000
+++ b/sql/sql_plugin.cc 2010-04-08 17:19:01 +0000
@@ -828,7 +828,7 @@ static plugin_ref intern_plugin_lock(LEX
*plugin= pi;
#endif
pi->ref_count++;
- DBUG_PRINT("info",("thd: 0x%lx plugin: \"%s\" ref_count: %d",
+ DBUG_PRINT("lock",("thd: 0x%lx plugin: \"%s\" LOCK ref_count: %d",
(long) current_thd, pi->name.str, pi->ref_count));
if (lex)
@@ -1135,8 +1135,6 @@ static void intern_plugin_unlock(LEX *le
my_free((uchar*) plugin, MYF(MY_WME));
#endif
- DBUG_PRINT("info",("unlocking plugin, name= %s, ref_count= %d",
- pi->name.str, pi->ref_count));
if (lex)
{
/*
@@ -1156,6 +1154,9 @@ static void intern_plugin_unlock(LEX *le
DBUG_ASSERT(pi->ref_count);
pi->ref_count--;
+ DBUG_PRINT("lock",("thd: 0x%lx plugin: \"%s\" UNLOCK ref_count: %d",
+ (long) current_thd, pi->name.str, pi->ref_count));
+
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
reap_needed= true;
1
0
Hi all,
When compiling lp:maria on windows, there are a couple of errors. The
attached patch fixes those.
Part of this patch fixes https://bugs.launchpad.net/maria/+bug/550974,
and it's done the way Sanja suggested.
Bo.
2
2

[Maria-developers] Rev 2781: fix dialog plugin to work again in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2781
revision-id: sergii(a)pisem.net-20100408135804-rel674ezvlwfj3ax
parent: monty(a)askmonty.org-20100408130743-uw4igobwa9mw59n1
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Thu 2010-04-08 15:58:04 +0200
message:
fix dialog plugin to work again
(fgets, unlike gets, does not strip \n)
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-04-08 13:02:49 +0000
+++ b/plugin/auth/dialog.c 2010-04-08 13:58:04 +0000
@@ -226,11 +226,17 @@ static char *builtin_ask(MYSQL *mysql __
const char *prompt,
char *buf, int buf_len)
{
+ int len;
+
fputs(prompt, stdout);
fputc(' ', stdout);
if (fgets(buf, buf_len, stdin) == 0)
return 0;
+ len= strlen(buf);
+ if (len && buf[len-1]=='\n')
+ buf[len-1]=0;
+
return buf;
}
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2780)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria/5.2 based on revid:sergii@pisem.net-20100408121005-h5tzkoe2enmy7j4u
2780 Michael Widenius 2010-04-08 [merge]
Merge with local tree
added:
mysql-test/suite/binlog/t/binlog_index-master.opt
mysql-test/suite/pbxt/t/multi_statement-master.opt
modified:
client/mysql.cc
configure.in
mysql-test/extra/rpl_tests/rpl_insert_id_pk.test
mysql-test/include/maria_empty_logs.inc
mysql-test/lib/My/SafeProcess/safe_process.cc
mysql-test/mysql-test-run.pl
mysql-test/r/func_time.result
mysql-test/suite/binlog/r/binlog_index.result
mysql-test/suite/binlog/t/binlog_index.test
mysql-test/suite/funcs_1/datadict/processlist_priv.inc
mysql-test/suite/pbxt/r/multi_statement.result
mysql-test/suite/pbxt/t/status.test
mysql-test/t/func_time.test
plugin/auth/dialog.c
sql/events.cc
sql/handler.cc
sql/log.cc
sql/mysqld.cc
sql/set_var.cc
sql/slave.cc
sql/sql_plugin.cc
storage/maria/ma_loghandler.c
storage/xtradb/include/ut0lst.h
support-files/compiler_warnings.supp
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2010-03-29 15:13:53 +0000
+++ b/client/mysql.cc 2010-04-08 13:02:49 +0000
@@ -4288,8 +4288,9 @@ extern "C" char *mysql_authentication_di
}
else
{
- fgets(buf, buf_len-1, stdin);
- if (buf[0] && (s= strend(buf))[-1] == '\n')
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else if (buf[0] && (s= strend(buf))[-1] == '\n')
s[-1]= 0;
}
=== modified file 'configure.in'
--- a/configure.in 2010-04-01 14:34:51 +0000
+++ b/configure.in 2010-04-08 13:02:49 +0000
@@ -12,7 +12,7 @@ AC_PREREQ(2.59)
# MySQL version number.
#
# Note: the following line must be parseable by win/configure.js:GetVersion()
-AC_INIT([MariaDB Server], [5.2.0-MariaDB-alpha], [], [mysql])
+AC_INIT([MariaDB Server], [5.2.0-MariaDB-beta], [], [mysql])
AC_CONFIG_SRCDIR([sql/mysqld.cc])
AC_CANONICAL_SYSTEM
# USTAR format gives us the possibility to store longer path names in
=== modified file 'mysql-test/extra/rpl_tests/rpl_insert_id_pk.test'
--- a/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test 2007-06-06 17:57:07 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test 2010-04-06 22:47:08 +0000
@@ -82,7 +82,6 @@ SET FOREIGN_KEY_CHECKS=0;
# Duplicate Key Errors codes
--error 1022, ER_DUP_ENTRY
INSERT INTO t1 VALUES (1),(1);
-sync_slave_with_master;
-connection master;
drop table t1;
+sync_slave_with_master;
# End of 4.1 tests
=== modified file 'mysql-test/include/maria_empty_logs.inc'
--- a/mysql-test/include/maria_empty_logs.inc 2009-10-13 12:47:17 +0000
+++ b/mysql-test/include/maria_empty_logs.inc 2010-04-06 22:47:08 +0000
@@ -11,9 +11,10 @@
connection default;
let $default_db=`select database()`;
let $MYSQLD_DATADIR= `SELECT @@datadir`;
-# it will used at end of test for wait_for_status_var.inc primitive
-let $status_var= Threads_connected;
-let $status_var_value= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
+
+#it will used at end of test for wait_for_status_var.inc primitive
+#let $status_var= Threads_connected;
+#let $status_var_value= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
connection admin;
-- echo * shut down mysqld, removed logs, restarted it
@@ -77,12 +78,15 @@ append_file $MYSQLTEST_VARDIR/tmp/mysqld
restart-maria_empty_logs.inc
EOF
+connection default;
--source include/wait_until_connected_again.inc
-connection default;
# Make sure that all connections are restored
---source include/wait_for_status_var.inc
+# This is disabled as 'Threads_connected' can't be trusted'
+# (It may be affected by 'check_testcase()')
+# --source include/wait_for_status_var.inc
# Restore current database as the effect of "use" was lost after restart
+
--disable_query_log
eval use $default_db;
--enable_query_log
=== modified file 'mysql-test/lib/My/SafeProcess/safe_process.cc'
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-03-28 18:10:00 +0000
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-04-08 11:56:57 +0000
@@ -85,17 +85,18 @@ static void die(const char* fmt, ...)
va_end(args);
if (int last_err= errno)
fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
- exit(1);
+ exit(6);
}
-static void kill_child(void)
+static void kill_child(bool was_killed)
{
int status= 0;
message("Killing child: %d", child_pid);
// Terminate whole process group
- kill(-child_pid, SIGKILL);
+ if (! was_killed)
+ kill(-child_pid, SIGKILL);
pid_t ret_pid= waitpid(child_pid, &status, 0);
if (ret_pid == child_pid)
@@ -115,7 +116,7 @@ static void kill_child(void)
exit(exit_code);
}
- exit(1);
+ exit(5);
}
@@ -135,7 +136,7 @@ extern "C" void handle_signal(int sig)
terminated= 1;
if (child_pid > 0)
- kill_child();
+ kill_child(sig == SIGCHLD);
// Ignore further signals
signal(SIGTERM, SIG_IGN);
@@ -240,8 +241,8 @@ int main(int argc, char* const argv[] )
// Close write end
close(pfd[1]);
- if (execvp(child_argv[0], child_argv) < 0)
- die("Failed to exec child");
+ execvp(child_argv[0], child_argv);
+ die("Failed to exec child");
}
close(pfd[1]); // Close unused write end
@@ -257,39 +258,19 @@ int main(int argc, char* const argv[] )
/* Monitor loop */
message("Started child %d, terminated: %d", child_pid, terminated);
- while(!terminated)
+ while (!terminated)
{
// Check if parent is still alive
- if (kill(parent_pid, 0) != 0){
+ if (kill(parent_pid, 0) != 0)
+ {
message("Parent is not alive anymore");
break;
}
-
- // Check if child has exited, normally this will be
- // detected immediately with SIGCHLD handler
- int status= 0;
- pid_t ret_pid= waitpid(child_pid, &status, WNOHANG);
- if (ret_pid == child_pid)
- {
- int ret_code= 2;
- if (WIFEXITED(status))
- {
- // Process has exited, collect return status
- ret_code= WEXITSTATUS(status);
- message("Child exit: %d", ret_code);
- // Exit with exit status of the child
- exit(ret_code);
- }
-
- if (WIFSIGNALED(status))
- message("Child killed by signal: %d", WTERMSIG(status));
-
- exit(ret_code);
- }
+ /* Wait for parent or child to die */
sleep(1);
}
- kill_child();
+ kill_child(0);
- return 1;
+ return 4;
}
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2010-02-19 08:10:05 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-04-08 09:52:53 +0000
@@ -4012,7 +4012,10 @@ sub extract_warning_lines ($) {
qr/Slave I\/O: Get master COLLATION_SERVER failed with error:.*/,
qr/Slave I\/O: Get master TIME_ZONE failed with error:.*/,
qr/Slave I\/O: error reconnecting to master '.*' - retry-time: [1-3] retries/,
+ qr/Slave I\/0: Master command COM_BINLOG_DUMP failed/,
qr/Error reading packet/,
+ qr/Lost connection to MySQL server at 'reading initial communication packet'/,
+ qr/Failed on request_dump/,
qr/Slave: Can't drop database.* database doesn't exist/,
qr/Slave: Operation DROP USER failed for 'create_rout_db'/,
qr|Checking table: '\./mtr/test_suppressions'|,
=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result 2010-01-21 08:10:05 +0000
+++ b/mysql-test/r/func_time.result 2010-04-08 09:47:31 +0000
@@ -1120,7 +1120,7 @@ drop function t_slow_sysdate;
drop table t1;
SET GLOBAL log_bin_trust_function_creators = 0;
create table t1 (a datetime, i int, b datetime);
-insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+insert into t1 select sysdate(), sleep(2), sysdate() from dual;
select a != b from t1;
a != b
1
=== modified file 'mysql-test/suite/binlog/r/binlog_index.result'
--- a/mysql-test/suite/binlog/r/binlog_index.result 2010-03-20 14:12:53 +0000
+++ b/mysql-test/suite/binlog/r/binlog_index.result 2010-04-08 09:52:53 +0000
@@ -3,6 +3,7 @@ call mtr.add_suppression('MSYQL_BIN_LOG:
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+flush tables;
flush logs;
flush logs;
flush logs;
=== added file 'mysql-test/suite/binlog/t/binlog_index-master.opt'
--- a/mysql-test/suite/binlog/t/binlog_index-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index-master.opt 2010-04-06 22:47:08 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --test-expect-abort --log-warnings=0
=== modified file 'mysql-test/suite/binlog/t/binlog_index.test'
--- a/mysql-test/suite/binlog/t/binlog_index.test 2010-03-20 14:12:53 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index.test 2010-04-08 09:52:53 +0000
@@ -11,6 +11,8 @@ call mtr.add_suppression('MSYQL_BIN_LOG:
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+flush tables;
+
let $old=`select @@debug`;
let $MYSQLD_DATADIR= `select @@datadir`;
=== modified file 'mysql-test/suite/funcs_1/datadict/processlist_priv.inc'
--- a/mysql-test/suite/funcs_1/datadict/processlist_priv.inc 2009-10-10 09:59:06 +0000
+++ b/mysql-test/suite/funcs_1/datadict/processlist_priv.inc 2010-04-07 15:26:30 +0000
@@ -89,18 +89,38 @@ USE information_schema;
--echo 1 Prepare test.
--echo connection default (user=root)
--echo ####################################################################################
-if (`SELECT COUNT(*) <> 1 FROM processlist`)
+
+# Check that we have only one connection around.
+# If there is more, it may be the check() connection that has not yet ended,
+# so we wait for it for up to 10 seconds.
+
+let $counter=100;
+while ($counter)
{
- --echo This test expects one connection to the server.
- --echo Expectation: USER HOST DB COMMAND STATE INFO
- --echo Expectation: root localhost information_schema Query executing SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID
- --echo But we found in the moment:
- SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID;
- --echo Maybe
- --echo - the base configuration (no of parallel auxiliary sessions) of the server has changed
- --echo - a parallel test intended for another server accidently connected to our current one
- --echo We cannot proceed in this situation. Abort
- exit;
+ dec $counter;
+ let $res= `SELECT COUNT(*) <> 1 FROM processlist`;
+ if (!$res)
+ {
+ # Success; Abort while loop
+ let $counter=0;
+ }
+ if ($res)
+ {
+ --sleep 0.1
+ if (!$counter)
+ {
+ --echo This test expects one connection to the server.
+ --echo Expectation: USER HOST DB COMMAND STATE INFO
+ --echo Expectation: root localhost information_schema Query executing SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID
+ --echo But we found in the moment:
+ SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID;
+ --echo Maybe
+ --echo - the base configuration (no of parallel auxiliary sessions) of the server has changed
+ --echo - a parallel test intended for another server accidently connected to our current one
+ --echo We cannot proceed in this situation. Abort
+ exit;
+ }
+ }
}
--echo ####################################################################################
=== modified file 'mysql-test/suite/pbxt/r/multi_statement.result'
--- a/mysql-test/suite/pbxt/r/multi_statement.result 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/r/multi_statement.result 2010-04-06 22:47:08 +0000
@@ -47,5 +47,5 @@ i
3
show status like 'Slow_queries'||||
Variable_name Value
-Slow_queries 0
+Slow_queries 3
drop table t1||||
=== added file 'mysql-test/suite/pbxt/t/multi_statement-master.opt'
--- a/mysql-test/suite/pbxt/t/multi_statement-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/multi_statement-master.opt 2010-04-06 22:47:08 +0000
@@ -0,0 +1,3 @@
+--slow-query-log
+--slow-query-log-file=slow.log
+--log-queries-not-using-indexes
=== modified file 'mysql-test/suite/pbxt/t/status.test'
--- a/mysql-test/suite/pbxt/t/status.test 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/t/status.test 2010-04-07 15:26:30 +0000
@@ -30,7 +30,7 @@ connection con1;
--send
update t1 set n = 3;
connection con2;
-sleep 0.5;
+sleep 5;
unlock tables;
connection con1;
reap;
=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test 2009-01-23 12:22:05 +0000
+++ b/mysql-test/t/func_time.test 2010-04-08 09:47:31 +0000
@@ -650,7 +650,7 @@ drop table t1;
SET GLOBAL log_bin_trust_function_creators = 0;
create table t1 (a datetime, i int, b datetime);
-insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+insert into t1 select sysdate(), sleep(2), sysdate() from dual;
select a != b from t1;
drop table t1;
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-04-01 14:34:51 +0000
+++ b/plugin/auth/dialog.c 2010-04-08 13:02:49 +0000
@@ -224,11 +224,11 @@ static mysql_authentication_dialog_ask_t
static char *builtin_ask(MYSQL *mysql __attribute__((unused)),
int type __attribute__((unused)),
const char *prompt,
- char *buf, int buf_len __attribute__((unused)))
+ char *buf, int buf_len)
{
fputs(prompt, stdout);
fputc(' ', stdout);
- if (gets(buf) == 0)
+ if (fgets(buf, buf_len, stdin) == 0)
return 0;
return buf;
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2010-03-04 08:03:07 +0000
+++ b/sql/events.cc 2010-04-06 22:47:08 +0000
@@ -1263,8 +1263,9 @@ Events::load_events_from_db(THD *thd)
}
}
}
- sql_print_information("Event Scheduler: Loaded %d event%s",
- count, (count == 1) ? "" : "s");
+ if (global_system_variables.log_warnings)
+ sql_print_information("Event Scheduler: Loaded %d event%s",
+ count, (count == 1) ? "" : "s");
ret= FALSE;
end:
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-04-08 12:10:05 +0000
+++ b/sql/handler.cc 2010-04-08 13:07:43 +0000
@@ -4455,6 +4455,8 @@ int handler::index_read_idx_map(uchar *
enum ha_rkey_function find_flag)
{
int error, error1;
+ LINT_INIT(error1);
+
error= index_init(index, 0);
if (!error)
{
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-04-01 14:34:51 +0000
+++ b/sql/log.cc 2010-04-08 09:52:53 +0000
@@ -1238,6 +1238,7 @@ void LOGGER::deactivate_log_handler(THD
{
my_bool *tmp_opt= 0;
MYSQL_LOG *file_log;
+ LINT_INIT(file_log);
switch (log_type) {
case QUERY_LOG_SLOW:
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-04-08 12:10:05 +0000
+++ b/sql/mysqld.cc 2010-04-08 13:07:43 +0000
@@ -1,4 +1,5 @@
/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+ 2009-2010 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -383,7 +384,7 @@ static bool volatile select_thread_in_us
static bool volatile ready_to_exit;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
-static my_bool opt_ignore_wrong_options= 0;
+static my_bool opt_ignore_wrong_options= 0, opt_expect_abort= 0;
static uint kill_cached_threads, wake_thread;
ulong thread_created;
static ulong max_used_connections;
@@ -2549,13 +2550,19 @@ extern "C" sig_handler handle_segfault(i
curr_time= my_time(0);
localtime_r(&curr_time, &tm);
- fprintf(stderr,"\
-%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\
+ fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d ",
+ tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ if (opt_expect_abort && sig == SIGABRT)
+ {
+ fprintf(stderr,"[Note] mysqld did an expected abort\n");
+ goto end;
+ }
+
+ fprintf(stderr,"[ERROR] mysqld got " SIGNAL_FMT " ;\n\
This could be because you hit a bug. It is also possible that this binary\n\
or one of the libraries it was linked against is corrupt, improperly built,\n\
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
- tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec,
sig);
fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
@@ -2674,6 +2681,7 @@ bugs.\n");
}
#endif
+end:
#ifndef __WIN__
/* On Windows, do not terminate, but pass control to exception filter */
exit(1);
@@ -5925,7 +5933,7 @@ enum options_mysqld
OPT_MIN_EXAMINED_ROW_LIMIT,
OPT_LOG_SLOW_SLAVE_STATEMENTS,
OPT_DEBUG_CRC, OPT_DEBUG_ON, OPT_OLD_MODE,
- OPT_TEST_IGNORE_WRONG_OPTIONS,
+ OPT_TEST_IGNORE_WRONG_OPTIONS, OPT_TEST_RESTART,
#if defined(ENABLED_DEBUG_SYNC)
OPT_DEBUG_SYNC_TIMEOUT,
#endif /* defined(ENABLED_DEBUG_SYNC) */
@@ -6773,6 +6781,10 @@ log and this option does nothing anymore
"Ignore wrong enums values in command line arguments. Useful only for test scripts",
(uchar**) &opt_ignore_wrong_options, (uchar**) &opt_ignore_wrong_options,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"test-expect-abort", OPT_TEST_RESTART,
+ "Expect that server aborts with 'abort'; Don't write out server variables on 'abort'. Useful only for test scripts",
+ (uchar**) &opt_expect_abort, (uchar**) &opt_expect_abort,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"timed_mutexes", OPT_TIMED_MUTEXES,
"Specify whether to time mutexes (only InnoDB mutexes are currently supported)",
(uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-04-06 18:36:06 +0000
+++ b/sql/set_var.cc 2010-04-08 09:52:53 +0000
@@ -2604,7 +2604,7 @@ static int sys_check_log_path(THD *thd,
char path[FN_REFLEN], buff[FN_REFLEN];
MY_STAT f_stat;
String str(buff, sizeof(buff), system_charset_info), *res;
- const char *log_file_str;
+ const char *log_file_str= 0;
size_t path_length;
if (!(res= var->value->val_str(&str)))
@@ -2654,7 +2654,7 @@ static int sys_check_log_path(THD *thd,
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name,
- res ? log_file_str : "NULL");
+ log_file_str ? log_file_str : "NULL");
return 1;
}
@@ -2663,7 +2663,7 @@ bool update_sys_var_str_path(THD *thd, s
set_var *var, const char *log_ext,
bool log_state, uint log_type)
{
- MYSQL_QUERY_LOG *file_log;
+ MYSQL_QUERY_LOG *file_log= 0;
char buff[FN_REFLEN];
char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
bool result= 0;
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2010-03-04 08:03:07 +0000
+++ b/sql/slave.cc 2010-04-06 22:47:08 +0000
@@ -2255,6 +2255,7 @@ static int exec_relay_log_event(THD* thd
if (slave_trans_retries)
{
int temp_err;
+ LINT_INIT(temp_err);
if (exec_res && (temp_err= has_temporary_error(thd)))
{
const char *errmsg;
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-04-01 20:05:09 +0000
+++ b/sql/sql_plugin.cc 2010-04-08 09:52:53 +0000
@@ -593,7 +593,7 @@ static my_bool read_maria_plugin_info(st
DBUG_RETURN(FALSE);
}
-#endif HAVE_DLOPEN
+#endif /* HAVE_DLOPEN */
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
@@ -1886,9 +1886,10 @@ bool mysql_install_plugin(THD *thd, cons
if (tmp->state == PLUGIN_IS_DISABLED)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
- name->str, "Plugin is disabled");
+ if (global_system_variables.log_warnings)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
+ name->str, "Plugin is disabled");
}
else
{
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-04-02 09:20:09 +0000
+++ b/storage/maria/ma_loghandler.c 2010-04-08 09:52:53 +0000
@@ -1274,11 +1274,10 @@ static my_bool translog_set_lsn_for_file
for (file= from_file; file <= to_file; file++)
{
LOGHANDLER_FILE_INFO info;
- File fd= open_logfile_by_number_no_cache(file);
-
- LINT_INIT_STRUCT(info);
+ File fd;
LINT_INIT(info.max_lsn);
+ fd= open_logfile_by_number_no_cache(file);
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
=== modified file 'storage/xtradb/include/ut0lst.h'
--- a/storage/xtradb/include/ut0lst.h 2010-03-30 12:36:49 +0000
+++ b/storage/xtradb/include/ut0lst.h 2010-04-06 22:47:08 +0000
@@ -158,7 +158,7 @@ Inserts a NODE2 after NODE1 in a list.
/** Invalidate the pointers in a list node.
@param NAME list name
@param N pointer to the node that was removed */
-# define UT_LIST_REMOVE_CLEAR(NAME, N) {} while (0)
+# define UT_LIST_REMOVE_CLEAR(NAME, N) do {} while (0)
#endif
/*******************************************************************//**
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-04-01 09:40:11 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-07 15:26:30 +0000
@@ -40,6 +40,7 @@ sync/sync0sync\.c: unused parameter
sync/sync0sync\.c: unused variable
ut/ut0ut\.c: ignoring return value of
srv/srv0srv\.c: value computed is not used
+buf/buf0buf\.c: .*block_mutex.* might be used uninitialized
#
# bdb is not critical to keep up to date
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2782)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100408130249-9o2krwjc6s57juew
2782 Michael Widenius 2010-04-08 [merge]
Merge with 5.1
modified:
mysql-test/lib/My/SafeProcess/safe_process.cc
=== modified file 'mysql-test/lib/My/SafeProcess/safe_process.cc'
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-03-28 18:10:00 +0000
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-04-08 11:56:57 +0000
@@ -85,17 +85,18 @@ static void die(const char* fmt, ...)
va_end(args);
if (int last_err= errno)
fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
- exit(1);
+ exit(6);
}
-static void kill_child(void)
+static void kill_child(bool was_killed)
{
int status= 0;
message("Killing child: %d", child_pid);
// Terminate whole process group
- kill(-child_pid, SIGKILL);
+ if (! was_killed)
+ kill(-child_pid, SIGKILL);
pid_t ret_pid= waitpid(child_pid, &status, 0);
if (ret_pid == child_pid)
@@ -115,7 +116,7 @@ static void kill_child(void)
exit(exit_code);
}
- exit(1);
+ exit(5);
}
@@ -135,7 +136,7 @@ extern "C" void handle_signal(int sig)
terminated= 1;
if (child_pid > 0)
- kill_child();
+ kill_child(sig == SIGCHLD);
// Ignore further signals
signal(SIGTERM, SIG_IGN);
@@ -240,8 +241,8 @@ int main(int argc, char* const argv[] )
// Close write end
close(pfd[1]);
- if (execvp(child_argv[0], child_argv) < 0)
- die("Failed to exec child");
+ execvp(child_argv[0], child_argv);
+ die("Failed to exec child");
}
close(pfd[1]); // Close unused write end
@@ -257,39 +258,19 @@ int main(int argc, char* const argv[] )
/* Monitor loop */
message("Started child %d, terminated: %d", child_pid, terminated);
- while(!terminated)
+ while (!terminated)
{
// Check if parent is still alive
- if (kill(parent_pid, 0) != 0){
+ if (kill(parent_pid, 0) != 0)
+ {
message("Parent is not alive anymore");
break;
}
-
- // Check if child has exited, normally this will be
- // detected immediately with SIGCHLD handler
- int status= 0;
- pid_t ret_pid= waitpid(child_pid, &status, WNOHANG);
- if (ret_pid == child_pid)
- {
- int ret_code= 2;
- if (WIFEXITED(status))
- {
- // Process has exited, collect return status
- ret_code= WEXITSTATUS(status);
- message("Child exit: %d", ret_code);
- // Exit with exit status of the child
- exit(ret_code);
- }
-
- if (WIFSIGNALED(status))
- message("Child killed by signal: %d", WTERMSIG(status));
-
- exit(ret_code);
- }
+ /* Wait for parent or child to die */
sleep(1);
}
- kill_child();
+ kill_child(0);
- return 1;
+ return 4;
}
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2781)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100408095253-z8vg2u7fq6hf6jxy
2781 Michael Widenius 2010-04-08
Fixed compiler warnings
Changed version string to beta
modified:
client/mysql.cc
configure.in
plugin/auth/dialog.c
per-file messages:
client/mysql.cc
Fixed compiler warning
configure.in
Changed version string to beta
plugin/auth/dialog.c
Fixed compiler warning (gets() is a not recommended function)
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2010-03-29 15:13:53 +0000
+++ b/client/mysql.cc 2010-04-08 13:02:49 +0000
@@ -4288,8 +4288,9 @@ extern "C" char *mysql_authentication_di
}
else
{
- fgets(buf, buf_len-1, stdin);
- if (buf[0] && (s= strend(buf))[-1] == '\n')
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else if (buf[0] && (s= strend(buf))[-1] == '\n')
s[-1]= 0;
}
=== modified file 'configure.in'
--- a/configure.in 2010-04-01 14:34:51 +0000
+++ b/configure.in 2010-04-08 13:02:49 +0000
@@ -12,7 +12,7 @@ AC_PREREQ(2.59)
# MySQL version number.
#
# Note: the following line must be parseable by win/configure.js:GetVersion()
-AC_INIT([MariaDB Server], [5.2.0-MariaDB-alpha], [], [mysql])
+AC_INIT([MariaDB Server], [5.2.0-MariaDB-beta], [], [mysql])
AC_CONFIG_SRCDIR([sql/mysqld.cc])
AC_CANONICAL_SYSTEM
# USTAR format gives us the possibility to store longer path names in
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-04-01 14:34:51 +0000
+++ b/plugin/auth/dialog.c 2010-04-08 13:02:49 +0000
@@ -224,11 +224,11 @@ static mysql_authentication_dialog_ask_t
static char *builtin_ask(MYSQL *mysql __attribute__((unused)),
int type __attribute__((unused)),
const char *prompt,
- char *buf, int buf_len __attribute__((unused)))
+ char *buf, int buf_len)
{
fputs(prompt, stdout);
fputc(' ', stdout);
- if (gets(buf) == 0)
+ if (fgets(buf, buf_len, stdin) == 0)
return 0;
return buf;
1
0

[Maria-developers] Rev 2779: MWL#43 CREATE TABLE options (by Sanja) in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2779
revision-id: sergii(a)pisem.net-20100408121005-h5tzkoe2enmy7j4u
parent: sergii(a)pisem.net-20100407150509-l5lrdmanv1flfsi7
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Thu 2010-04-08 14:10:05 +0200
message:
MWL#43 CREATE TABLE options (by Sanja)
Diff too large for email (3178 lines, the limit is 1000).
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2844: Fixed race condition in safe_process.cc which may have caused some mysqltests to be reported as f...
by noreply@launchpad.net 08 Apr '10
by noreply@launchpad.net 08 Apr '10
08 Apr '10
------------------------------------------------------------
revno: 2844
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Thu 2010-04-08 14:56:57 +0300
message:
Fixed race condition in safe_process.cc which may have caused some mysqltests to be reported as failed even if they succeded.
modified:
mysql-test/lib/My/SafeProcess/safe_process.cc
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2844)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100408094731-0c5opgwwi1dm5ut6
2844 Michael Widenius 2010-04-08
Fixed race condition in safe_process.cc which may have caused some mysqltests to be reported as failed even if they succeded.
modified:
mysql-test/lib/My/SafeProcess/safe_process.cc
per-file messages:
mysql-test/lib/My/SafeProcess/safe_process.cc
Fixed race condition when getting a signal while calling waitpid()
Don't send kill on killed processes
Return different exit codes depending on how we die.
=== modified file 'mysql-test/lib/My/SafeProcess/safe_process.cc'
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-03-28 18:10:00 +0000
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-04-08 11:56:57 +0000
@@ -85,17 +85,18 @@ static void die(const char* fmt, ...)
va_end(args);
if (int last_err= errno)
fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
- exit(1);
+ exit(6);
}
-static void kill_child(void)
+static void kill_child(bool was_killed)
{
int status= 0;
message("Killing child: %d", child_pid);
// Terminate whole process group
- kill(-child_pid, SIGKILL);
+ if (! was_killed)
+ kill(-child_pid, SIGKILL);
pid_t ret_pid= waitpid(child_pid, &status, 0);
if (ret_pid == child_pid)
@@ -115,7 +116,7 @@ static void kill_child(void)
exit(exit_code);
}
- exit(1);
+ exit(5);
}
@@ -135,7 +136,7 @@ extern "C" void handle_signal(int sig)
terminated= 1;
if (child_pid > 0)
- kill_child();
+ kill_child(sig == SIGCHLD);
// Ignore further signals
signal(SIGTERM, SIG_IGN);
@@ -240,8 +241,8 @@ int main(int argc, char* const argv[] )
// Close write end
close(pfd[1]);
- if (execvp(child_argv[0], child_argv) < 0)
- die("Failed to exec child");
+ execvp(child_argv[0], child_argv);
+ die("Failed to exec child");
}
close(pfd[1]); // Close unused write end
@@ -257,39 +258,19 @@ int main(int argc, char* const argv[] )
/* Monitor loop */
message("Started child %d, terminated: %d", child_pid, terminated);
- while(!terminated)
+ while (!terminated)
{
// Check if parent is still alive
- if (kill(parent_pid, 0) != 0){
+ if (kill(parent_pid, 0) != 0)
+ {
message("Parent is not alive anymore");
break;
}
-
- // Check if child has exited, normally this will be
- // detected immediately with SIGCHLD handler
- int status= 0;
- pid_t ret_pid= waitpid(child_pid, &status, WNOHANG);
- if (ret_pid == child_pid)
- {
- int ret_code= 2;
- if (WIFEXITED(status))
- {
- // Process has exited, collect return status
- ret_code= WEXITSTATUS(status);
- message("Child exit: %d", ret_code);
- // Exit with exit status of the child
- exit(ret_code);
- }
-
- if (WIFSIGNALED(status))
- message("Child killed by signal: %d", WTERMSIG(status));
-
- exit(ret_code);
- }
+ /* Wait for parent or child to die */
sleep(1);
}
- kill_child();
+ kill_child(0);
- return 1;
+ return 4;
}
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2780)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100408095122-fbce81d9c5m89k3r
2780 Michael Widenius 2010-04-08 [merge]
Merge with 5.1
added:
mysql-test/suite/binlog/t/binlog_index-master.opt
mysql-test/suite/pbxt/t/multi_statement-master.opt
modified:
mysql-test/extra/rpl_tests/rpl_insert_id_pk.test
mysql-test/include/maria_empty_logs.inc
mysql-test/mysql-test-run.pl
mysql-test/r/func_time.result
mysql-test/suite/binlog/r/binlog_index.result
mysql-test/suite/binlog/t/binlog_index.test
mysql-test/suite/funcs_1/datadict/processlist_priv.inc
mysql-test/suite/pbxt/r/multi_statement.result
mysql-test/suite/pbxt/t/status.test
mysql-test/t/func_time.test
sql/events.cc
sql/handler.cc
sql/log.cc
sql/mysqld.cc
sql/set_var.cc
sql/slave.cc
sql/sql_plugin.cc
storage/maria/ma_loghandler.c
storage/xtradb/include/ut0lst.h
support-files/compiler_warnings.supp
=== modified file 'mysql-test/extra/rpl_tests/rpl_insert_id_pk.test'
--- a/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test 2007-06-06 17:57:07 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test 2010-04-06 22:47:08 +0000
@@ -82,7 +82,6 @@ SET FOREIGN_KEY_CHECKS=0;
# Duplicate Key Errors codes
--error 1022, ER_DUP_ENTRY
INSERT INTO t1 VALUES (1),(1);
-sync_slave_with_master;
-connection master;
drop table t1;
+sync_slave_with_master;
# End of 4.1 tests
=== modified file 'mysql-test/include/maria_empty_logs.inc'
--- a/mysql-test/include/maria_empty_logs.inc 2009-10-13 12:47:17 +0000
+++ b/mysql-test/include/maria_empty_logs.inc 2010-04-06 22:47:08 +0000
@@ -11,9 +11,10 @@
connection default;
let $default_db=`select database()`;
let $MYSQLD_DATADIR= `SELECT @@datadir`;
-# it will used at end of test for wait_for_status_var.inc primitive
-let $status_var= Threads_connected;
-let $status_var_value= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
+
+#it will used at end of test for wait_for_status_var.inc primitive
+#let $status_var= Threads_connected;
+#let $status_var_value= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
connection admin;
-- echo * shut down mysqld, removed logs, restarted it
@@ -77,12 +78,15 @@ append_file $MYSQLTEST_VARDIR/tmp/mysqld
restart-maria_empty_logs.inc
EOF
+connection default;
--source include/wait_until_connected_again.inc
-connection default;
# Make sure that all connections are restored
---source include/wait_for_status_var.inc
+# This is disabled as 'Threads_connected' can't be trusted'
+# (It may be affected by 'check_testcase()')
+# --source include/wait_for_status_var.inc
# Restore current database as the effect of "use" was lost after restart
+
--disable_query_log
eval use $default_db;
--enable_query_log
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2010-02-19 08:10:05 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-04-08 09:52:53 +0000
@@ -4012,7 +4012,10 @@ sub extract_warning_lines ($) {
qr/Slave I\/O: Get master COLLATION_SERVER failed with error:.*/,
qr/Slave I\/O: Get master TIME_ZONE failed with error:.*/,
qr/Slave I\/O: error reconnecting to master '.*' - retry-time: [1-3] retries/,
+ qr/Slave I\/0: Master command COM_BINLOG_DUMP failed/,
qr/Error reading packet/,
+ qr/Lost connection to MySQL server at 'reading initial communication packet'/,
+ qr/Failed on request_dump/,
qr/Slave: Can't drop database.* database doesn't exist/,
qr/Slave: Operation DROP USER failed for 'create_rout_db'/,
qr|Checking table: '\./mtr/test_suppressions'|,
=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result 2010-01-21 08:10:05 +0000
+++ b/mysql-test/r/func_time.result 2010-04-08 09:47:31 +0000
@@ -1120,7 +1120,7 @@ drop function t_slow_sysdate;
drop table t1;
SET GLOBAL log_bin_trust_function_creators = 0;
create table t1 (a datetime, i int, b datetime);
-insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+insert into t1 select sysdate(), sleep(2), sysdate() from dual;
select a != b from t1;
a != b
1
=== modified file 'mysql-test/suite/binlog/r/binlog_index.result'
--- a/mysql-test/suite/binlog/r/binlog_index.result 2010-03-20 14:12:53 +0000
+++ b/mysql-test/suite/binlog/r/binlog_index.result 2010-04-08 09:52:53 +0000
@@ -3,6 +3,7 @@ call mtr.add_suppression('MSYQL_BIN_LOG:
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+flush tables;
flush logs;
flush logs;
flush logs;
=== added file 'mysql-test/suite/binlog/t/binlog_index-master.opt'
--- a/mysql-test/suite/binlog/t/binlog_index-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index-master.opt 2010-04-06 22:47:08 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --test-expect-abort --log-warnings=0
=== modified file 'mysql-test/suite/binlog/t/binlog_index.test'
--- a/mysql-test/suite/binlog/t/binlog_index.test 2010-03-20 14:12:53 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index.test 2010-04-08 09:52:53 +0000
@@ -11,6 +11,8 @@ call mtr.add_suppression('MSYQL_BIN_LOG:
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+flush tables;
+
let $old=`select @@debug`;
let $MYSQLD_DATADIR= `select @@datadir`;
=== modified file 'mysql-test/suite/funcs_1/datadict/processlist_priv.inc'
--- a/mysql-test/suite/funcs_1/datadict/processlist_priv.inc 2009-10-10 09:59:06 +0000
+++ b/mysql-test/suite/funcs_1/datadict/processlist_priv.inc 2010-04-07 15:26:30 +0000
@@ -89,18 +89,38 @@ USE information_schema;
--echo 1 Prepare test.
--echo connection default (user=root)
--echo ####################################################################################
-if (`SELECT COUNT(*) <> 1 FROM processlist`)
+
+# Check that we have only one connection around.
+# If there is more, it may be the check() connection that has not yet ended,
+# so we wait for it for up to 10 seconds.
+
+let $counter=100;
+while ($counter)
{
- --echo This test expects one connection to the server.
- --echo Expectation: USER HOST DB COMMAND STATE INFO
- --echo Expectation: root localhost information_schema Query executing SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID
- --echo But we found in the moment:
- SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID;
- --echo Maybe
- --echo - the base configuration (no of parallel auxiliary sessions) of the server has changed
- --echo - a parallel test intended for another server accidently connected to our current one
- --echo We cannot proceed in this situation. Abort
- exit;
+ dec $counter;
+ let $res= `SELECT COUNT(*) <> 1 FROM processlist`;
+ if (!$res)
+ {
+ # Success; Abort while loop
+ let $counter=0;
+ }
+ if ($res)
+ {
+ --sleep 0.1
+ if (!$counter)
+ {
+ --echo This test expects one connection to the server.
+ --echo Expectation: USER HOST DB COMMAND STATE INFO
+ --echo Expectation: root localhost information_schema Query executing SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID
+ --echo But we found in the moment:
+ SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID;
+ --echo Maybe
+ --echo - the base configuration (no of parallel auxiliary sessions) of the server has changed
+ --echo - a parallel test intended for another server accidently connected to our current one
+ --echo We cannot proceed in this situation. Abort
+ exit;
+ }
+ }
}
--echo ####################################################################################
=== modified file 'mysql-test/suite/pbxt/r/multi_statement.result'
--- a/mysql-test/suite/pbxt/r/multi_statement.result 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/r/multi_statement.result 2010-04-06 22:47:08 +0000
@@ -47,5 +47,5 @@ i
3
show status like 'Slow_queries'||||
Variable_name Value
-Slow_queries 0
+Slow_queries 3
drop table t1||||
=== added file 'mysql-test/suite/pbxt/t/multi_statement-master.opt'
--- a/mysql-test/suite/pbxt/t/multi_statement-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/multi_statement-master.opt 2010-04-06 22:47:08 +0000
@@ -0,0 +1,3 @@
+--slow-query-log
+--slow-query-log-file=slow.log
+--log-queries-not-using-indexes
=== modified file 'mysql-test/suite/pbxt/t/status.test'
--- a/mysql-test/suite/pbxt/t/status.test 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/t/status.test 2010-04-07 15:26:30 +0000
@@ -30,7 +30,7 @@ connection con1;
--send
update t1 set n = 3;
connection con2;
-sleep 0.5;
+sleep 5;
unlock tables;
connection con1;
reap;
=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test 2009-01-23 12:22:05 +0000
+++ b/mysql-test/t/func_time.test 2010-04-08 09:47:31 +0000
@@ -650,7 +650,7 @@ drop table t1;
SET GLOBAL log_bin_trust_function_creators = 0;
create table t1 (a datetime, i int, b datetime);
-insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+insert into t1 select sysdate(), sleep(2), sysdate() from dual;
select a != b from t1;
drop table t1;
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2010-03-04 08:03:07 +0000
+++ b/sql/events.cc 2010-04-06 22:47:08 +0000
@@ -1263,8 +1263,9 @@ Events::load_events_from_db(THD *thd)
}
}
}
- sql_print_information("Event Scheduler: Loaded %d event%s",
- count, (count == 1) ? "" : "s");
+ if (global_system_variables.log_warnings)
+ sql_print_information("Event Scheduler: Loaded %d event%s",
+ count, (count == 1) ? "" : "s");
ret= FALSE;
end:
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-04-03 20:19:35 +0000
+++ b/sql/handler.cc 2010-04-08 09:52:53 +0000
@@ -4450,6 +4450,8 @@ int handler::index_read_idx_map(uchar *
enum ha_rkey_function find_flag)
{
int error, error1;
+ LINT_INIT(error1);
+
error= index_init(index, 0);
if (!error)
{
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-04-01 14:34:51 +0000
+++ b/sql/log.cc 2010-04-08 09:52:53 +0000
@@ -1238,6 +1238,7 @@ void LOGGER::deactivate_log_handler(THD
{
my_bool *tmp_opt= 0;
MYSQL_LOG *file_log;
+ LINT_INIT(file_log);
switch (log_type) {
case QUERY_LOG_SLOW:
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-04-03 20:19:35 +0000
+++ b/sql/mysqld.cc 2010-04-08 09:52:53 +0000
@@ -1,4 +1,5 @@
/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+ 2009-2010 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -383,7 +384,7 @@ static bool volatile select_thread_in_us
static bool volatile ready_to_exit;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
-static my_bool opt_ignore_wrong_options= 0;
+static my_bool opt_ignore_wrong_options= 0, opt_expect_abort= 0;
static uint kill_cached_threads, wake_thread;
ulong thread_created;
static ulong max_used_connections;
@@ -2549,13 +2550,19 @@ extern "C" sig_handler handle_segfault(i
curr_time= my_time(0);
localtime_r(&curr_time, &tm);
- fprintf(stderr,"\
-%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\
+ fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d ",
+ tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ if (opt_expect_abort && sig == SIGABRT)
+ {
+ fprintf(stderr,"[Note] mysqld did an expected abort\n");
+ goto end;
+ }
+
+ fprintf(stderr,"[ERROR] mysqld got " SIGNAL_FMT " ;\n\
This could be because you hit a bug. It is also possible that this binary\n\
or one of the libraries it was linked against is corrupt, improperly built,\n\
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
- tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec,
sig);
fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
@@ -2674,6 +2681,7 @@ bugs.\n");
}
#endif
+end:
#ifndef __WIN__
/* On Windows, do not terminate, but pass control to exception filter */
exit(1);
@@ -5925,7 +5933,7 @@ enum options_mysqld
OPT_MIN_EXAMINED_ROW_LIMIT,
OPT_LOG_SLOW_SLAVE_STATEMENTS,
OPT_DEBUG_CRC, OPT_DEBUG_ON, OPT_OLD_MODE,
- OPT_TEST_IGNORE_WRONG_OPTIONS,
+ OPT_TEST_IGNORE_WRONG_OPTIONS, OPT_TEST_RESTART,
#if defined(ENABLED_DEBUG_SYNC)
OPT_DEBUG_SYNC_TIMEOUT,
#endif /* defined(ENABLED_DEBUG_SYNC) */
@@ -6773,6 +6781,10 @@ log and this option does nothing anymore
"Ignore wrong enums values in command line arguments. Useful only for test scripts",
(uchar**) &opt_ignore_wrong_options, (uchar**) &opt_ignore_wrong_options,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"test-expect-abort", OPT_TEST_RESTART,
+ "Expect that server aborts with 'abort'; Don't write out server variables on 'abort'. Useful only for test scripts",
+ (uchar**) &opt_expect_abort, (uchar**) &opt_expect_abort,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"timed_mutexes", OPT_TIMED_MUTEXES,
"Specify whether to time mutexes (only InnoDB mutexes are currently supported)",
(uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-04-06 18:36:06 +0000
+++ b/sql/set_var.cc 2010-04-08 09:52:53 +0000
@@ -2604,7 +2604,7 @@ static int sys_check_log_path(THD *thd,
char path[FN_REFLEN], buff[FN_REFLEN];
MY_STAT f_stat;
String str(buff, sizeof(buff), system_charset_info), *res;
- const char *log_file_str;
+ const char *log_file_str= 0;
size_t path_length;
if (!(res= var->value->val_str(&str)))
@@ -2654,7 +2654,7 @@ static int sys_check_log_path(THD *thd,
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name,
- res ? log_file_str : "NULL");
+ log_file_str ? log_file_str : "NULL");
return 1;
}
@@ -2663,7 +2663,7 @@ bool update_sys_var_str_path(THD *thd, s
set_var *var, const char *log_ext,
bool log_state, uint log_type)
{
- MYSQL_QUERY_LOG *file_log;
+ MYSQL_QUERY_LOG *file_log= 0;
char buff[FN_REFLEN];
char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
bool result= 0;
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2010-03-04 08:03:07 +0000
+++ b/sql/slave.cc 2010-04-06 22:47:08 +0000
@@ -2255,6 +2255,7 @@ static int exec_relay_log_event(THD* thd
if (slave_trans_retries)
{
int temp_err;
+ LINT_INIT(temp_err);
if (exec_res && (temp_err= has_temporary_error(thd)))
{
const char *errmsg;
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-04-08 09:51:22 +0000
+++ b/sql/sql_plugin.cc 2010-04-08 09:52:53 +0000
@@ -1886,9 +1886,10 @@ bool mysql_install_plugin(THD *thd, cons
if (tmp->state == PLUGIN_IS_DISABLED)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
- name->str, "Plugin is disabled");
+ if (global_system_variables.log_warnings)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
+ name->str, "Plugin is disabled");
}
else
{
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-04-02 09:20:09 +0000
+++ b/storage/maria/ma_loghandler.c 2010-04-08 09:52:53 +0000
@@ -1274,11 +1274,10 @@ static my_bool translog_set_lsn_for_file
for (file= from_file; file <= to_file; file++)
{
LOGHANDLER_FILE_INFO info;
- File fd= open_logfile_by_number_no_cache(file);
-
- LINT_INIT_STRUCT(info);
+ File fd;
LINT_INIT(info.max_lsn);
+ fd= open_logfile_by_number_no_cache(file);
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
=== modified file 'storage/xtradb/include/ut0lst.h'
--- a/storage/xtradb/include/ut0lst.h 2010-03-30 12:36:49 +0000
+++ b/storage/xtradb/include/ut0lst.h 2010-04-06 22:47:08 +0000
@@ -158,7 +158,7 @@ Inserts a NODE2 after NODE1 in a list.
/** Invalidate the pointers in a list node.
@param NAME list name
@param N pointer to the node that was removed */
-# define UT_LIST_REMOVE_CLEAR(NAME, N) {} while (0)
+# define UT_LIST_REMOVE_CLEAR(NAME, N) do {} while (0)
#endif
/*******************************************************************//**
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-04-01 09:40:11 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-07 15:26:30 +0000
@@ -40,6 +40,7 @@ sync/sync0sync\.c: unused parameter
sync/sync0sync\.c: unused variable
ut/ut0ut\.c: ignoring return value of
srv/srv0srv\.c: value computed is not used
+buf/buf0buf\.c: .*block_mutex.* might be used uninitialized
#
# bdb is not critical to keep up to date
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2779)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria/5.2 based on revid:sergii@pisem.net-20100407150509-l5lrdmanv1flfsi7
2779 Michael Widenius 2010-04-08
Fixed compiler warning
modified:
sql/sql_plugin.cc
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-04-01 20:05:09 +0000
+++ b/sql/sql_plugin.cc 2010-04-08 09:51:22 +0000
@@ -593,7 +593,7 @@ static my_bool read_maria_plugin_info(st
DBUG_RETURN(FALSE);
}
-#endif HAVE_DLOPEN
+#endif /* HAVE_DLOPEN */
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2843: Fixed syntax error and some timeing issues in test suite
by noreply@launchpad.net 08 Apr '10
by noreply@launchpad.net 08 Apr '10
08 Apr '10
------------------------------------------------------------
revno: 2843
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Thu 2010-04-08 12:47:31 +0300
message:
Fixed syntax error and some timeing issues in test suite
modified:
mysql-test/r/func_time.result
mysql-test/t/func_time.test
storage/maria/ma_loghandler.c
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2843)
by Michael Widenius 08 Apr '10
by Michael Widenius 08 Apr '10
08 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100407152630-br17spd9a30jvmx0
2843 Michael Widenius 2010-04-08
Fixed syntax error and some timeing issues in test suite
modified:
mysql-test/r/func_time.result
mysql-test/t/func_time.test
storage/maria/ma_loghandler.c
per-file messages:
mysql-test/r/func_time.result
Updated result
mysql-test/t/func_time.test
sysdate() could be same even with one sleep(1) in between.
storage/maria/ma_loghandler.c
Fixed syntax error
=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result 2010-01-21 08:10:05 +0000
+++ b/mysql-test/r/func_time.result 2010-04-08 09:47:31 +0000
@@ -1120,7 +1120,7 @@ drop function t_slow_sysdate;
drop table t1;
SET GLOBAL log_bin_trust_function_creators = 0;
create table t1 (a datetime, i int, b datetime);
-insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+insert into t1 select sysdate(), sleep(2), sysdate() from dual;
select a != b from t1;
a != b
1
=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test 2009-01-23 12:22:05 +0000
+++ b/mysql-test/t/func_time.test 2010-04-08 09:47:31 +0000
@@ -650,7 +650,7 @@ drop table t1;
SET GLOBAL log_bin_trust_function_creators = 0;
create table t1 (a datetime, i int, b datetime);
-insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+insert into t1 select sysdate(), sleep(2), sysdate() from dual;
select a != b from t1;
drop table t1;
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-03-30 12:36:49 +0000
+++ b/storage/maria/ma_loghandler.c 2010-04-08 09:47:31 +0000
@@ -1211,9 +1211,10 @@ static my_bool translog_set_lsn_for_file
for (file= from_file; file <= to_file; file++)
{
LOGHANDLER_FILE_INFO info;
+ File fd;
LINT_INIT(info.max_lsn);
- File fd= open_logfile_by_number_no_cache(file);
+ fd= open_logfile_by_number_no_cache(file);
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
1
0

[Maria-developers] Rev 2780: bzr ignore in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2780
revision-id: sergii(a)pisem.net-20100408090706-a196ebold533efvo
parent: sanja(a)askmonty.org-20100406000609-swbb13c0biged8iv
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Thu 2010-04-08 11:07:06 +0200
message:
bzr ignore
=== modified file '.bzrignore'
--- a/.bzrignore 2010-03-29 15:13:53 +0000
+++ b/.bzrignore 2010-04-08 09:07:06 +0000
@@ -1934,3 +1934,4 @@ client/sql_list.h
libmysqld/client_plugin.c
sql/client_plugin.c
*.dgcov
+libmysqld/create_options.cc
1
0

[Maria-developers] Rev 2779: MWL#43 CREATE TABLE options in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2779
revision-id: sanja(a)askmonty.org-20100406000609-swbb13c0biged8iv
parent: sergii(a)pisem.net-20100407150509-l5lrdmanv1flfsi7
author: sanja(a)askmonty.org
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: work-maria-5.2-createoptions5
timestamp: Tue 2010-04-06 03:06:09 +0300
message:
MWL#43 CREATE TABLE options
Diff too large for email (3333 lines, the limit is 1000).
1
0

[Maria-developers] Rev 2776: post-review changes, and merge of the MWL#43 CREATE TABLE options in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 08 Apr '10
by serg@askmonty.org 08 Apr '10
08 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2776 [merge]
revision-id: sergii(a)pisem.net-20100408085536-qjt3rz3su3oumthu
parent: sergii(a)pisem.net-20100406110456-zhkf13tvdcywb9tb
parent: sanja(a)askmonty.org-20100406000609-jl8415st523eq5jj
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Thu 2010-04-08 10:55:36 +0200
message:
post-review changes, and merge of the MWL#43 CREATE TABLE options
added:
mysql-test/r/create_options.result create_options.resul-20100406150813-x9l18ft2v5asbu6u-1
mysql-test/t/create_options.test create_options.test-20100405221601-8v82yzjsbg8d5t9h-1
sql/create_options.cc create_options.cc-20100405221547-pgejz63vqubo45gk-1
sql/create_options.h create_options.h-20100405221550-zuwt433ekdv7y9u3-1
modified:
.bzrignore sp1f-ignore-20001018235455-q4gxfbritt5f42nwix354ufpsvrf5ebj
Docs/sp-imp-spec.txt sp1f-spimpspec.txt-20030202164941-cm47byoggfqjr73hhqr24vos7luqh36q
include/my_base.h sp1f-my_base.h-19700101030959-3yhq5cta6tatwfxpqmoukzvevlehtxoz
include/my_sys.h sp1f-my_sys.h-19700101030959-lyllvna5vzqfcjnmlcrutgqocylhtb54
libmysqld/CMakeLists.txt sp1f-cmakelists.txt-20060403082523-x3vxka3k56u2wpzwcrlpykznlz2akpxd
libmysqld/Makefile.am sp1f-makefile.am-20010411110351-26htpk3ynkyh7pkfvnshztqrxx3few4g
mysql-test/r/events_bugs.result sp1f-events_bugs.result-20060220225211-jzbz6uk6vlho4vlbzbfymaub54fll3ou
mysql-test/r/information_schema.result sp1f-information_schema.r-20041113105544-waoxa2fjjsicturpothmjmi6jc3yrovn
mysql-test/r/plugin.result sp1f-plugin.result-20061214230953-dljmjo3wuacc3eox3gwroufqmk3hlne7
mysql-test/r/sp.result sp1f-sp.result-20030117133802-duandg3yzagzyv7zhhbbt2kcomcegpc7
mysql-test/r/system_mysql_db.result sp1f-system_mysql_db.resu-20040310185404-f7br5g4442iqwxireltudlyu5ppbkijo
mysql-test/suite/funcs_1/r/is_columns_mysql.result sp1f-is_columns_mysql.res-20080307163304-a2ymkif2vzliwqqqzr22cglbaf75tthe
mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result is_columns_mysql_emb-20080616171935-sl04j972o55obadv-7
mysql-test/t/events_bugs.test sp1f-events_bugs.test-20060220225212-ji5acdijogityb45kk4msvs7h5gn4ld3
mysql-test/t/plugin.test sp1f-plugin.test-20061214230953-rdqkovjzpupoeypjzzvefseahkmrdz4f
mysql-test/t/sp.test sp1f-sp.test-20030117133803-b6pcfv2yscbqkur5fszep7acmdg7nf5k
scripts/mysql_system_tables.sql sp1f-mysql_system_tables.-20070226104923-4n5a67fuifobcyhhicfbacpsv5npohgv
scripts/mysql_system_tables_fix.sql sp1f-mysql_fix_privilege_-20030604152848-cz6lnrig5srcrvkt7d5m35bk3wsz4bdc
sql/CMakeLists.txt sp1f-cmakelists.txt-20060831175237-esoeu5kpdtwjvehkghwy6fzbleniq2wy
sql/Makefile.am sp1f-makefile.am-19700101030959-xsjdiakci3nqcdd4xl4yomwdl5eo2f3q
sql/event_db_repository.cc sp1f-event_db_repository.-20060627064838-k6rpjg72omnihtxhbubu6ht7wjvxggb7
sql/field.cc sp1f-field.cc-19700101030959-f4imaofclsea3n4fj4ow5m7havmyxa2r
sql/field.h sp1f-field.h-19700101030959-3n6smzxcwkjl7bikm3wg4hfkjn66uvvp
sql/ha_partition.cc sp1f-ha_partition.cc-20050718113037-eoky4qluumb5dmdyg5z6n2fvdkgutxms
sql/handler.cc sp1f-handler.cc-19700101030959-ta6zfrlbxzucylciyro3musjsdpocrdh
sql/handler.h sp1f-handler.h-19700101030959-mumq2hpilkpgxuf22ftyv5kbilysnzvn
sql/log_event.h sp1f-log_event.h-19700101030959-clq6ett55tcqbpys2i4cpfrdccq7j4om
sql/mysql_priv.h sp1f-mysql_priv.h-19700101030959-4fl65tqpop5zfgxaxkqotu2fa2ree5ci
sql/mysqld.cc sp1f-mysqld.cc-19700101030959-zpswdvekpvixxzxf7gdtofzel7nywtfj
sql/share/errmsg.txt sp1f-errmsg.txt-20041213212820-do5w642w224ja7ctyqhyl6iihdmpkzv5
sql/sp.cc sp1f-sp.cc-20021212121421-6xwuvxq5bku2b4yv655kp2e5gsvautd5
sql/sp_head.cc sp1f-sp_head.cc-20021208185920-jtgc5wvyqdnu2gvcdus3gazrfhxbofxd
sql/sql_class.cc sp1f-sql_class.cc-19700101030959-rpotnweaff2pikkozh3butrf7mv3oero
sql/sql_class.h sp1f-sql_class.h-19700101030959-jnqnbrjyqsvgncsibnumsmg3lyi7pa5s
sql/sql_insert.cc sp1f-sql_insert.cc-19700101030959-xgwqe5svnimxudzdcuitauljzz2zjk5g
sql/sql_lex.h sp1f-sql_lex.h-19700101030959-sgldb2sooc7twtw5q7pgjx7qzqiaa3sn
sql/sql_parse.cc sp1f-sql_parse.cc-19700101030959-ehcre3rwhv5l3mlxqhaxg36ujenxnrcd
sql/sql_plugin.cc sp1f-sql_plugin.cc-20051105112032-hrm64p6xfjq33ud6zy3uivpo7azm75a2
sql/sql_show.cc sp1f-sql_show.cc-19700101030959-umlljfnpplg452h7reeyqr4xnbmlkvfj
sql/sql_table.cc sp1f-sql_table.cc-19700101030959-tzdkvgigezpuaxnldqh3fx2h7h2ggslu
sql/sql_view.cc sp1f-sql_view.cc-20040715221517-nw4p4mja6nzzlvwwhzfgfqb4umxqobe4
sql/sql_yacc.yy sp1f-sql_yacc.yy-19700101030959-wvn4qyy2drpmge7kaq3dysprbhlrv27j
sql/structs.h sp1f-structs.h-19700101030959-dqulhwijezc2pwv2x4g32qdggnybj2nc
sql/table.cc sp1f-table.cc-19700101030959-nsxtem2adyqzwe6nz4cgrpcmts3o54v7
sql/table.h sp1f-table.h-19700101030959-dv72bajftxj5fbdjuajquappanuv2ija
sql/unireg.cc sp1f-unireg.cc-19700101030959-6a4wymwak6cmvk25gch56ctjvadrhu3v
storage/example/ha_example.cc sp1f-ha_example.cc-20040331231732-d55r4dr2e7cf5dutte3f74z6h6yxdywb
storage/example/ha_example.h sp1f-ha_example.h-20040331231733-ssl4zmhqjrevhtqixivtivdmlwiau2x5
storage/pbxt/src/discover_xt.cc discover_xt.cc-20090326121724-x683v32twzr3fi0y-26
Diff too large for email (3198 lines, the limit is 1000).
1
0

[Maria-developers] Rev 33: Added: in file:///Users/hakan/work/monty_program/mariadb-tools/
by Hakan Kuecuekyilmaz 08 Apr '10
by Hakan Kuecuekyilmaz 08 Apr '10
08 Apr '10
At file:///Users/hakan/work/monty_program/mariadb-tools/
------------------------------------------------------------
revno: 33
revision-id: hakan(a)askmonty.org-20100408002114-36ml405ax1h61x60
parent: hakan(a)askmonty.org-20100407121715-2k24p66xyfkgpdpn
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: mariadb-tools
timestamp: Thu 2010-04-08 02:21:14 +0200
message:
Added:
* IO utilization with iostat
* CPU utilization with mpstat
* Simple queries/second monitoring per test with mysqladmin --sleep 10 status
* Tests can have options now
** select_random_points has option for number of points
** select_random_ragnes has option for number of ranges and delta of ranges.
=== modified file 'sysbench/run-sysbench-myisam.sh'
--- a/sysbench/run-sysbench-myisam.sh 2010-04-07 12:17:15 +0000
+++ b/sysbench/run-sysbench-myisam.sh 2010-04-08 00:21:14 +0000
@@ -106,16 +106,26 @@
# We need at least 1 GB disk space in our $WORK_DIR.
SPACE_LIMIT=1000000
-SYSBENCH_TESTS="delete.lua \
- insert.lua \
- oltp_complex_ro.lua \
- oltp_complex_rw.lua \
- oltp_simple.lua \
- select.lua \
- select_random_points.lua \
- select_random_ranges.lua \
- update_index.lua \
- update_non_index.lua"
+# Interval in seconds for monitoring system status like disk IO,
+# CPU utilization, and such.
+MONITOR_INTERVAL=10
+
+SYSBENCH_TESTS[0]="delete.lua"
+SYSBENCH_TESTS[1]="insert.lua"
+SYSBENCH_TESTS[2]="oltp_complex_ro.lua"
+SYSBENCH_TESTS[3]="oltp_complex_rw.lua"
+SYSBENCH_TESTS[4]="oltp_simple.lua"
+SYSBENCH_TESTS[5]="select.lua"
+
+# Default option is --random-points=10.
+SYSBENCH_TESTS[6]="select_random_points.lua"
+
+# Default options are
+# --number-of-ranges=10
+# --random-ranges-delta=5.
+SYSBENCH_TESTS[7]="select_random_ranges.lua"
+SYSBENCH_TESTS[8]="update_index.lua"
+SYSBENCH_TESTS[9]="update_non_index.lua"
#
# Note: myisam-max-rows has to match or exceed oltp-table-size
@@ -277,7 +287,7 @@
}
#
-# Write out configurations used for future refernce.
+# Write out configurations used for future reference.
#
echo $MYSQLD_OPTIONS > ${RESULT_DIR}/${TODAY}/${PRODUCT}/mysqld_options.txt
echo $SYSBENCH_OPTIONS > ${RESULT_DIR}/${TODAY}/${PRODUCT}/sysbench_options.txt
@@ -285,8 +295,17 @@
echo "Warm up time is: $WARM_UP_TIME" >> ${RESULT_DIR}/${TODAY}/${PRODUCT}/sysbench_options.txt
echo "Run time is: $RUN_TIME" >> ${RESULT_DIR}/${TODAY}/${PRODUCT}/sysbench_options.txt
-for SYSBENCH_TEST in $SYSBENCH_TESTS
+#
+# Kill possibly left over monitoring processes.
+#
+killall -9 iostat
+killall -9 mpstat
+killall -9 mysqladmin
+
+for (( i = 0 ; i < ${#SYSBENCH_TESTS[@]} ; i++ ))
do
+ # Get rid of any options of given sysbench test.
+ SYSBENCH_TEST=$(echo "${SYSBENCH_TESTS[$i]}" | awk '{ print $1 }')
mkdir ${RESULT_DIR}/${TODAY}/${PRODUCT}/${SYSBENCH_TEST}
kill_mysqld
@@ -299,8 +318,8 @@
exit 1
fi
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Preparing and loading data for $SYSBENCH_TEST."
- SYSBENCH_OPTIONS="${SYSBENCH_OPTIONS} --test=${TEST_DIR}/${SYSBENCH_TEST}"
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Preparing and loading data for ${SYSBENCH_TESTS[$i]}."
+ SYSBENCH_OPTIONS="${SYSBENCH_OPTIONS} --test=${TEST_DIR}/${SYSBENCH_TESTS[$i]}"
$SYSBENCH $SYSBENCH_OPTIONS --max-time=$RUN_TIME prepare
$MYSQLADMIN $MYSQLADMIN_OPTIONS shutdown
@@ -308,14 +327,14 @@
rm -rf ${SYSBENCH_DB_BACKUP}
mkdir ${SYSBENCH_DB_BACKUP}
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Copying $DATA_DIR of $SYSBENCH_TEST for later usage."
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Copying $DATA_DIR of ${SYSBENCH_TESTS[$i]} for later usage."
cp -a ${DATA_DIR}/* ${SYSBENCH_DB_BACKUP}/
for THREADS in $NUM_THREADS
do
THIS_RESULT_DIR="${RESULT_DIR}/${TODAY}/${PRODUCT}/${SYSBENCH_TEST}/${THREADS}"
mkdir $THIS_RESULT_DIR
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Running $SYSBENCH_TEST with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee ${THIS_RESULT_DIR}/results.txt
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Running ${SYSBENCH_TESTS[$i]} with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee ${THIS_RESULT_DIR}/results.txt
echo '' >> ${THIS_RESULT_DIR}/results.txt
SYSBENCH_OPTIONS_WARM_UP="${SYSBENCH_OPTIONS} --num-threads=3 --max-time=$WARM_UP_TIME"
@@ -325,7 +344,7 @@
while [ $k -lt $LOOP_COUNT ]
do
echo ''
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Killing mysqld and copying back $DATA_DIR for $SYSBENCH_TEST."
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Killing mysqld and copying back $DATA_DIR for ${SYSBENCH_TESTS[$i]}."
kill_mysqld
cp -a ${SYSBENCH_DB_BACKUP}/* ${DATA_DIR}
@@ -334,7 +353,7 @@
sync
echo 3 | $SUDO tee /proc/sys/vm/drop_caches
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting mysqld for running $SYSBENCH_TEST with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT"
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting mysqld for running ${SYSBENCH_TESTS[$i]} with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT"
start_mysqld
sync
@@ -346,8 +365,25 @@
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished warm up."
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting actual sysbench run."
+
+ $IOSTAT -d -k $IOSTAT_DEVICE $MONITOR_INTERVAL > ${THIS_RESULT_DIR}/iostat${k}.txt 2>&1 &
+ IOSTAT_PID=$!
+
+ $MPSTAT -u $MONITOR_INTERVAL > ${THIS_RESULT_DIR}/cpustat${k}.txt 2>&1 &
+ MPSTAT_PID=$!
+
+ $MYSQLADMIN $MYSQLADMIN_OPTIONS --sleep $MONITOR_INTERVAL status > ${THIS_RESULT_DIR}/server_status${k}.txt 2>&1 &
+ SERVER_STATUS_PID=$!
+
$SYSBENCH $SYSBENCH_OPTIONS_RUN run > ${THIS_RESULT_DIR}/result${k}.txt 2>&1
+ sync; sync; sync
+ sleep 1
+
+ kill -9 $SERVER_STATUS_PID
+ kill -9 $MPSTAT_PID
+ kill -9 $IOSTAT_PID
+
grep "write requests:" ${THIS_RESULT_DIR}/result${k}.txt | awk '{ print $4 }' | sed -e 's/(//' >> ${THIS_RESULT_DIR}/results.txt
echo 'SELECT * FROM INFORMATION_SCHEMA.KEY_CACHES' | $MYSQL $MYSQL_OPTIONS > ${THIS_RESULT_DIR}/key_cache_stats${k}.txt
@@ -356,7 +392,7 @@
done
echo '' >> ${THIS_RESULT_DIR}/results.txt
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished $SYSBENCH_TEST with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee -a ${THIS_RESULT_DIR}/results.txt
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished ${SYSBENCH_TESTS[$i]} with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee -a ${THIS_RESULT_DIR}/results.txt
done
done
=== modified file 'sysbench/run-sysbench.sh'
--- a/sysbench/run-sysbench.sh 2010-04-07 12:17:15 +0000
+++ b/sysbench/run-sysbench.sh 2010-04-08 00:21:14 +0000
@@ -103,16 +103,26 @@
# We need at least 1 GB disk space in our $WORK_DIR.
SPACE_LIMIT=1000000
-SYSBENCH_TESTS="delete.lua \
- insert.lua \
- oltp_complex_ro.lua \
- oltp_complex_rw.lua \
- oltp_simple.lua \
- select.lua \
- select_random_points.lua \
- select_random_ranges.lua \
- update_index.lua \
- update_non_index.lua"
+# Interval in seconds for monitoring system status like disk IO,
+# CPU utilization, and such.
+MONITOR_INTERVAL=10
+
+SYSBENCH_TESTS[0]="delete.lua"
+SYSBENCH_TESTS[1]="insert.lua"
+SYSBENCH_TESTS[2]="oltp_complex_ro.lua"
+SYSBENCH_TESTS[3]="oltp_complex_rw.lua"
+SYSBENCH_TESTS[4]="oltp_simple.lua"
+SYSBENCH_TESTS[5]="select.lua"
+
+# Default option is --random-points=10.
+SYSBENCH_TESTS[6]="select_random_points.lua"
+
+# Default options are
+# --number-of-ranges=10
+# --random-ranges-delta=5.
+SYSBENCH_TESTS[7]="select_random_ranges.lua"
+SYSBENCH_TESTS[8]="update_index.lua"
+SYSBENCH_TESTS[9]="update_non_index.lua"
SYSBENCH_OPTIONS="--oltp-table-size=$TABLE_SIZE \
--max-requests=0 \
@@ -269,7 +279,7 @@
}
#
-# Write out configurations used for future refernce.
+# Write out configurations used for future reference.
#
echo $MYSQLD_OPTIONS > ${RESULT_DIR}/${TODAY}/${PRODUCT}/mysqld_options.txt
echo $SYSBENCH_OPTIONS > ${RESULT_DIR}/${TODAY}/${PRODUCT}/sysbench_options.txt
@@ -277,8 +287,17 @@
echo "Warm up time is: $WARM_UP_TIME" >> ${RESULT_DIR}/${TODAY}/${PRODUCT}/sysbench_options.txt
echo "Run time is: $RUN_TIME" >> ${RESULT_DIR}/${TODAY}/${PRODUCT}/sysbench_options.txt
-for SYSBENCH_TEST in $SYSBENCH_TESTS
+#
+# Kill possibly left over monitoring processes.
+#
+killall -9 iostat
+killall -9 mpstat
+killall -9 mysqladmin
+
+for (( i = 0 ; i < ${#SYSBENCH_TESTS[@]} ; i++ ))
do
+ # Get rid of any options of given sysbench test.
+ SYSBENCH_TEST=$(echo "${SYSBENCH_TESTS[$i]}" | awk '{ print $1 }')
mkdir ${RESULT_DIR}/${TODAY}/${PRODUCT}/${SYSBENCH_TEST}
kill_mysqld
@@ -291,8 +310,8 @@
exit 1
fi
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Preparing and loading data for $SYSBENCH_TEST."
- SYSBENCH_OPTIONS="${SYSBENCH_OPTIONS} --test=${TEST_DIR}/${SYSBENCH_TEST}"
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Preparing and loading data for ${SYSBENCH_TESTS[$i]}."
+ SYSBENCH_OPTIONS="${SYSBENCH_OPTIONS} --test=${TEST_DIR}/${SYSBENCH_TESTS[$i]}"
$SYSBENCH $SYSBENCH_OPTIONS --max-time=$RUN_TIME prepare
$MYSQLADMIN $MYSQLADMIN_OPTIONS shutdown
@@ -300,14 +319,14 @@
rm -rf ${SYSBENCH_DB_BACKUP}
mkdir ${SYSBENCH_DB_BACKUP}
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Copying $DATA_DIR of $SYSBENCH_TEST for later usage."
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Copying $DATA_DIR of ${SYSBENCH_TESTS[$i]} for later usage."
cp -a ${DATA_DIR}/* ${SYSBENCH_DB_BACKUP}/
for THREADS in $NUM_THREADS
do
THIS_RESULT_DIR="${RESULT_DIR}/${TODAY}/${PRODUCT}/${SYSBENCH_TEST}/${THREADS}"
mkdir $THIS_RESULT_DIR
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Running $SYSBENCH_TEST with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee ${THIS_RESULT_DIR}/results.txt
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Running ${SYSBENCH_TESTS[$i]} with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee ${THIS_RESULT_DIR}/results.txt
echo '' >> ${THIS_RESULT_DIR}/results.txt
SYSBENCH_OPTIONS_WARM_UP="${SYSBENCH_OPTIONS} --num-threads=1 --max-time=$WARM_UP_TIME"
@@ -317,7 +336,7 @@
while [ $k -lt $LOOP_COUNT ]
do
echo ''
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Killing mysqld and copying back $DATA_DIR for $SYSBENCH_TEST."
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Killing mysqld and copying back $DATA_DIR for ${SYSBENCH_TESTS[$i]}."
kill_mysqld
cp -a ${SYSBENCH_DB_BACKUP}/* ${DATA_DIR}
@@ -326,7 +345,7 @@
sync
echo 3 | $SUDO tee /proc/sys/vm/drop_caches
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting mysqld for running $SYSBENCH_TEST with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT"
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting mysqld for running ${SYSBENCH_TESTS[$i]} with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT"
start_mysqld
sync
@@ -337,15 +356,32 @@
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished warm up."
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting actual sysbench run."
+
+ $IOSTAT -d -k $IOSTAT_DEVICE $MONITOR_INTERVAL > ${THIS_RESULT_DIR}/iostat${k}.txt 2>&1 &
+ IOSTAT_PID=$!
+
+ $MPSTAT -u $MONITOR_INTERVAL > ${THIS_RESULT_DIR}/cpustat${k}.txt 2>&1 &
+ MPSTAT_PID=$!
+
+ $MYSQLADMIN $MYSQLADMIN_OPTIONS --sleep $MONITOR_INTERVAL status > ${THIS_RESULT_DIR}/server_status${k}.txt 2>&1 &
+ SERVER_STATUS_PID=$!
+
$SYSBENCH $SYSBENCH_OPTIONS_RUN run > ${THIS_RESULT_DIR}/result${k}.txt 2>&1
-
+
+ sync; sync; sync
+ sleep 1
+
+ kill -9 $SERVER_STATUS_PID
+ kill -9 $MPSTAT_PID
+ kill -9 $IOSTAT_PID
+
grep "write requests:" ${THIS_RESULT_DIR}/result${k}.txt | awk '{ print $4 }' | sed -e 's/(//' >> ${THIS_RESULT_DIR}/results.txt
k=$(($k + 1))
done
echo '' >> ${THIS_RESULT_DIR}/results.txt
- echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished $SYSBENCH_TEST with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee -a ${THIS_RESULT_DIR}/results.txt
+ echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished ${SYSBENCH_TESTS[$i]} with $THREADS threads and $LOOP_COUNT iterations for $PRODUCT" | tee -a ${THIS_RESULT_DIR}/results.txt
done
done
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2842: Fixed suppression of compiler/test warnings
by noreply@launchpad.net 07 Apr '10
by noreply@launchpad.net 07 Apr '10
07 Apr '10
------------------------------------------------------------
revno: 2842
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Wed 2010-04-07 18:26:30 +0300
message:
Fixed suppression of compiler/test warnings
Fixed some timing issues in test suite
modified:
mysql-test/mysql-test-run.pl
mysql-test/suite/funcs_1/datadict/processlist_priv.inc
mysql-test/suite/pbxt/t/status.test
support-files/compiler_warnings.supp
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2842)
by Michael Widenius 07 Apr '10
by Michael Widenius 07 Apr '10
07 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100406224708-i62wvtw3nl14fhv4
2842 Michael Widenius 2010-04-07
Fixed suppression of compiler/test warnings
Fixed some timing issues in test suite
modified:
mysql-test/mysql-test-run.pl
mysql-test/suite/funcs_1/datadict/processlist_priv.inc
mysql-test/suite/pbxt/t/status.test
support-files/compiler_warnings.supp
per-file messages:
mysql-test/mysql-test-run.pl
Added suppression of errors that comes when master is killed before slave has connect (like with rpl_udf.test)
mysql-test/suite/funcs_1/datadict/processlist_priv.inc
Wait for check thread to end
mysql-test/suite/pbxt/t/status.test
Added longer sleep to avoid timing issue
support-files/compiler_warnings.supp
Fixed wrong suppression
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2010-03-10 10:32:14 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-04-07 15:26:30 +0000
@@ -4015,7 +4015,10 @@ sub extract_warning_lines ($) {
qr/Slave I\/O: Get master COLLATION_SERVER failed with error:.*/,
qr/Slave I\/O: Get master TIME_ZONE failed with error:.*/,
qr/Slave I\/O: error reconnecting to master '.*' - retry-time: [1-3] retries/,
+ qr/Slave I\/0: Master command COM_BINLOG_DUMP failed/,
qr/Error reading packet/,
+ qr/Lost connection to MySQL server at 'reading initial communication packet'/,
+ qr/Failed on request_dump/,
qr/Slave: Can't drop database.* database doesn't exist/,
qr/Slave: Operation DROP USER failed for 'create_rout_db'/,
qr|Checking table: '\./mtr/test_suppressions'|,
=== modified file 'mysql-test/suite/funcs_1/datadict/processlist_priv.inc'
--- a/mysql-test/suite/funcs_1/datadict/processlist_priv.inc 2009-10-10 09:59:06 +0000
+++ b/mysql-test/suite/funcs_1/datadict/processlist_priv.inc 2010-04-07 15:26:30 +0000
@@ -89,18 +89,38 @@ USE information_schema;
--echo 1 Prepare test.
--echo connection default (user=root)
--echo ####################################################################################
-if (`SELECT COUNT(*) <> 1 FROM processlist`)
+
+# Check that we have only one connection around.
+# If there is more, it may be the check() connection that has not yet ended,
+# so we wait for it for up to 10 seconds.
+
+let $counter=100;
+while ($counter)
{
- --echo This test expects one connection to the server.
- --echo Expectation: USER HOST DB COMMAND STATE INFO
- --echo Expectation: root localhost information_schema Query executing SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID
- --echo But we found in the moment:
- SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID;
- --echo Maybe
- --echo - the base configuration (no of parallel auxiliary sessions) of the server has changed
- --echo - a parallel test intended for another server accidently connected to our current one
- --echo We cannot proceed in this situation. Abort
- exit;
+ dec $counter;
+ let $res= `SELECT COUNT(*) <> 1 FROM processlist`;
+ if (!$res)
+ {
+ # Success; Abort while loop
+ let $counter=0;
+ }
+ if ($res)
+ {
+ --sleep 0.1
+ if (!$counter)
+ {
+ --echo This test expects one connection to the server.
+ --echo Expectation: USER HOST DB COMMAND STATE INFO
+ --echo Expectation: root localhost information_schema Query executing SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID
+ --echo But we found in the moment:
+ SELECT USER,HOST,DB,COMMAND,STATE,INFO FROM processlist ORDER BY ID;
+ --echo Maybe
+ --echo - the base configuration (no of parallel auxiliary sessions) of the server has changed
+ --echo - a parallel test intended for another server accidently connected to our current one
+ --echo We cannot proceed in this situation. Abort
+ exit;
+ }
+ }
}
--echo ####################################################################################
=== modified file 'mysql-test/suite/pbxt/t/status.test'
--- a/mysql-test/suite/pbxt/t/status.test 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/t/status.test 2010-04-07 15:26:30 +0000
@@ -30,7 +30,7 @@ connection con1;
--send
update t1 set n = 3;
connection con2;
-sleep 0.5;
+sleep 5;
unlock tables;
connection con1;
reap;
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-04-06 22:47:08 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-07 15:26:30 +0000
@@ -40,7 +40,7 @@ sync/sync0sync\.c: unused parameter
sync/sync0sync\.c: unused variable
ut/ut0ut\.c: ignoring return value of
srv/srv0srv\.c: value computed is not used
-buf/buf0buf\.c: warning: .*block_mutex.* might be used uninitialized
+buf/buf0buf\.c: .*block_mutex.* might be used uninitialized
#
# bdb is not critical to keep up to date
1
0
Hi Sanja,
On Wed, Apr 07, 2010 at 01:54:25PM +0300, Oleksandr Byelkin wrote:
> I found 1 interesting test case:
>
> create table t1 (a int, b int);
> insert into t1 values (1,2),(3,4),(1,2),(3,4),(3,4),(4,5),(4,5),(5,6),
> (5,6),(4,5);
> create table t2 (c int, d int);
> insert into t2 values (2,3),(3,4),(5,6);
>
> select a, b from t1 where b in (select d from t2);
>
> It crashes but only if test case started with --debug.
I assume this is with current lp:~maria-captains/maria/5.3-subqueries? I'll
take a look.
> Also could you give me example where Item_in_optimizer will be used for
> sure (in above example it looks like it is not used).
Basically, subquery must not be a semi-join. The easiest way to achieve this is
to make it so that the subuqery is not an AND-part of ther WHERE anymore.
The following will use Item_in_optimizer:
select a, b, b in (select d from t2) as SUBQ from t1 ;
select a, b from t1 where b in (select d from t2) or b < 3;
If you want to get lots of test coverage fast, include the standard
subselect*.test after having done:
SET optimizer_switch='semijoin=off,materialization=off';
This will cause Item_in_optimizer to be used for every IN subquery.
BR
Sergey
--
Sergey Petrunia, Software Developer
Monty Program AB, http://askmonty.org
Blog: http://s.petrunia.net/blog
1
1

[Maria-developers] Rev 32: * Increased run time to 20 minutes in file:///Users/hakan/work/monty_program/mariadb-tools/
by Hakan Kuecuekyilmaz 07 Apr '10
by Hakan Kuecuekyilmaz 07 Apr '10
07 Apr '10
At file:///Users/hakan/work/monty_program/mariadb-tools/
------------------------------------------------------------
revno: 32
revision-id: hakan(a)askmonty.org-20100407121715-2k24p66xyfkgpdpn
parent: hakan(a)askmonty.org-20100331181744-71hyuyjjlijrsl68
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: mariadb-tools
timestamp: Wed 2010-04-07 14:17:15 +0200
message:
* Increased run time to 20 minutes
* Increased warm up time to 5 minutes
* Added select_random_points.lua and select_random_ranges.lua tests
* Added --log-error to mysqld startup options to catch errors and crashes.
=== modified file 'sysbench/run-sysbench-myisam.sh'
--- a/sysbench/run-sysbench-myisam.sh 2010-03-31 18:16:51 +0000
+++ b/sysbench/run-sysbench-myisam.sh 2010-04-07 12:17:15 +0000
@@ -17,6 +17,7 @@
# * oltp_complex_rw.lua 313M sbtest.MYI
# * oltp_simple.lua 325M sbtest.MYI
# * select.lua 313M sbtest.MYI
+# * select_random_points.lua 313M sbtest.MYI
# * select_random_ranges.lua 313M sbtest.MYI
# * update_index.lua 313M sbtest.MYI
# * update_non_index.lua 313M sbtest.MYI
@@ -75,6 +76,7 @@
MYSQLD_OPTIONS="--no-defaults \
--datadir=$DATA_DIR \
--language=./sql/share/english \
+ --log-error \
--key_buffer_size=32M \
--max_connections=256 \
--query_cache_size=0 \
@@ -93,7 +95,7 @@
TABLE_SIZE=20000000
# The run time we use for sysbench.
-RUN_TIME=1800
+RUN_TIME=1200
# Warm up time we use for sysbench.
WARM_UP_TIME=300
@@ -110,6 +112,7 @@
oltp_complex_rw.lua \
oltp_simple.lua \
select.lua \
+ select_random_points.lua \
select_random_ranges.lua \
update_index.lua \
update_non_index.lua"
=== modified file 'sysbench/run-sysbench.sh'
--- a/sysbench/run-sysbench.sh 2010-03-31 18:16:51 +0000
+++ b/sysbench/run-sysbench.sh 2010-04-07 12:17:15 +0000
@@ -62,6 +62,7 @@
MYSQLD_OPTIONS="--no-defaults \
--datadir=$DATA_DIR \
--language=./sql/share/english \
+ --log-error \
--max_connections=256 \
--query_cache_size=0 \
--query_cache_type=0 \
@@ -91,10 +92,10 @@
TABLE_SIZE=2000000
# The run time we use for sysbench.
-RUN_TIME=300
+RUN_TIME=1200
# Warm up time we use for sysbench.
-WARM_UP_TIME=180
+WARM_UP_TIME=300
# How many times we run each test.
LOOP_COUNT=3
@@ -108,6 +109,8 @@
oltp_complex_rw.lua \
oltp_simple.lua \
select.lua \
+ select_random_points.lua \
+ select_random_ranges.lua \
update_index.lua \
update_non_index.lua"
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2841: Removed compiler warnings
by noreply@launchpad.net 06 Apr '10
by noreply@launchpad.net 06 Apr '10
06 Apr '10
------------------------------------------------------------
revno: 2841
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Wed 2010-04-07 01:47:08 +0300
message:
Removed compiler warnings
Removed random failures from test suite
added:
mysql-test/suite/binlog/t/binlog_index-master.opt
mysql-test/suite/pbxt/t/multi_statement-master.opt
modified:
mysql-test/extra/rpl_tests/rpl_insert_id_pk.test
mysql-test/include/maria_empty_logs.inc
mysql-test/suite/binlog/r/binlog_index.result
mysql-test/suite/binlog/t/binlog_index.test
mysql-test/suite/pbxt/r/multi_statement.result
sql/events.cc
sql/handler.cc
sql/log.cc
sql/mysqld.cc
sql/set_var.cc
sql/slave.cc
sql/sql_plugin.cc
storage/xtradb/include/ut0lst.h
support-files/compiler_warnings.supp
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2841)
by Michael Widenius 06 Apr '10
by Michael Widenius 06 Apr '10
06 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100401094011-hdhc99gn00rhidy5
2841 Michael Widenius 2010-04-07
Removed compiler warnings
Removed random failures from test suite
added:
mysql-test/suite/binlog/t/binlog_index-master.opt
mysql-test/suite/pbxt/t/multi_statement-master.opt
modified:
mysql-test/extra/rpl_tests/rpl_insert_id_pk.test
mysql-test/include/maria_empty_logs.inc
mysql-test/suite/binlog/r/binlog_index.result
mysql-test/suite/binlog/t/binlog_index.test
mysql-test/suite/pbxt/r/multi_statement.result
sql/events.cc
sql/handler.cc
sql/log.cc
sql/mysqld.cc
sql/set_var.cc
sql/slave.cc
sql/sql_plugin.cc
storage/xtradb/include/ut0lst.h
support-files/compiler_warnings.supp
per-file messages:
mysql-test/extra/rpl_tests/rpl_insert_id_pk.test
Make test predicatable.
mysql-test/include/maria_empty_logs.inc
We can't use 'Threads_connected' for syncronization, as the 'check_warnings' thread that just quit may still be counted in 'Threads_connected'
Now we just wait until MySQLD answers again, which should be good enough for our purposes
mysql-test/suite/binlog/r/binlog_index.result
Updated results file
mysql-test/suite/binlog/t/binlog_index-master.opt
Added option file to not get stack traces in .err file.
mysql-test/suite/binlog/t/binlog_index.test
Added 'flush tables' to remove warning about crashed suppression file from logs
mysql-test/suite/pbxt/r/multi_statement.result
Updated results
mysql-test/suite/pbxt/t/multi_statement-master.opt
Added options so that slow query testing makes sense
sql/events.cc
Don't write Event Scheduler startup message if warnings are turned off.
sql/handler.cc
Removed compiler warning
sql/log.cc
Removed compiler warning
sql/mysqld.cc
Added option 'test-expect-abort'; If this is set, we don't write message to log in case of 'DBUG_ABORT'.
(Gives us smaller, easier to read log files)
sql/set_var.cc
Removed compiler warning
sql/slave.cc
Removed compiler warning
sql/sql_plugin.cc
Don't write warnings about disabled plugin if using --log_warnings=0
storage/xtradb/include/ut0lst.h
Removed compiler warning
support-files/compiler_warnings.supp
Supress warning from xtradb
=== modified file 'mysql-test/extra/rpl_tests/rpl_insert_id_pk.test'
--- a/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test 2007-06-06 17:57:07 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test 2010-04-06 22:47:08 +0000
@@ -82,7 +82,6 @@ SET FOREIGN_KEY_CHECKS=0;
# Duplicate Key Errors codes
--error 1022, ER_DUP_ENTRY
INSERT INTO t1 VALUES (1),(1);
-sync_slave_with_master;
-connection master;
drop table t1;
+sync_slave_with_master;
# End of 4.1 tests
=== modified file 'mysql-test/include/maria_empty_logs.inc'
--- a/mysql-test/include/maria_empty_logs.inc 2009-10-13 12:47:17 +0000
+++ b/mysql-test/include/maria_empty_logs.inc 2010-04-06 22:47:08 +0000
@@ -11,9 +11,10 @@
connection default;
let $default_db=`select database()`;
let $MYSQLD_DATADIR= `SELECT @@datadir`;
-# it will used at end of test for wait_for_status_var.inc primitive
-let $status_var= Threads_connected;
-let $status_var_value= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
+
+#it will used at end of test for wait_for_status_var.inc primitive
+#let $status_var= Threads_connected;
+#let $status_var_value= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
connection admin;
-- echo * shut down mysqld, removed logs, restarted it
@@ -77,12 +78,15 @@ append_file $MYSQLTEST_VARDIR/tmp/mysqld
restart-maria_empty_logs.inc
EOF
+connection default;
--source include/wait_until_connected_again.inc
-connection default;
# Make sure that all connections are restored
---source include/wait_for_status_var.inc
+# This is disabled as 'Threads_connected' can't be trusted'
+# (It may be affected by 'check_testcase()')
+# --source include/wait_for_status_var.inc
# Restore current database as the effect of "use" was lost after restart
+
--disable_query_log
eval use $default_db;
--enable_query_log
=== modified file 'mysql-test/suite/binlog/r/binlog_index.result'
--- a/mysql-test/suite/binlog/r/binlog_index.result 2009-12-16 19:52:56 +0000
+++ b/mysql-test/suite/binlog/r/binlog_index.result 2010-04-06 22:47:08 +0000
@@ -3,6 +3,7 @@ call mtr.add_suppression('MSYQL_BIN_LOG:
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+flush tables;
flush logs;
flush logs;
flush logs;
=== added file 'mysql-test/suite/binlog/t/binlog_index-master.opt'
--- a/mysql-test/suite/binlog/t/binlog_index-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index-master.opt 2010-04-06 22:47:08 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --test-expect-abort --log-warnings=0
=== modified file 'mysql-test/suite/binlog/t/binlog_index.test'
--- a/mysql-test/suite/binlog/t/binlog_index.test 2009-12-08 16:03:19 +0000
+++ b/mysql-test/suite/binlog/t/binlog_index.test 2010-04-06 22:47:08 +0000
@@ -11,6 +11,8 @@ call mtr.add_suppression('MSYQL_BIN_LOG:
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
+flush tables;
+
let $old=`select @@debug`;
let $MYSQLD_DATADIR= `select @@datadir`;
=== modified file 'mysql-test/suite/pbxt/r/multi_statement.result'
--- a/mysql-test/suite/pbxt/r/multi_statement.result 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/r/multi_statement.result 2010-04-06 22:47:08 +0000
@@ -47,5 +47,5 @@ i
3
show status like 'Slow_queries'||||
Variable_name Value
-Slow_queries 0
+Slow_queries 3
drop table t1||||
=== added file 'mysql-test/suite/pbxt/t/multi_statement-master.opt'
--- a/mysql-test/suite/pbxt/t/multi_statement-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/multi_statement-master.opt 2010-04-06 22:47:08 +0000
@@ -0,0 +1,3 @@
+--slow-query-log
+--slow-query-log-file=slow.log
+--log-queries-not-using-indexes
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2010-03-04 08:03:07 +0000
+++ b/sql/events.cc 2010-04-06 22:47:08 +0000
@@ -1263,8 +1263,9 @@ Events::load_events_from_db(THD *thd)
}
}
}
- sql_print_information("Event Scheduler: Loaded %d event%s",
- count, (count == 1) ? "" : "s");
+ if (global_system_variables.log_warnings)
+ sql_print_information("Event Scheduler: Loaded %d event%s",
+ count, (count == 1) ? "" : "s");
ret= FALSE;
end:
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-03-30 12:36:49 +0000
+++ b/sql/handler.cc 2010-04-06 22:47:08 +0000
@@ -4298,6 +4298,8 @@ int handler::index_read_idx_map(uchar *
enum ha_rkey_function find_flag)
{
int error, error1;
+ LINT_INIT(error1);
+
error= index_init(index, 0);
if (!error)
{
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-03-24 22:12:39 +0000
+++ b/sql/log.cc 2010-04-06 22:47:08 +0000
@@ -1216,6 +1216,7 @@ void LOGGER::deactivate_log_handler(THD
{
my_bool *tmp_opt= 0;
MYSQL_LOG *file_log;
+ LINT_INIT(file_log);
switch (log_type) {
case QUERY_LOG_SLOW:
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-30 12:36:49 +0000
+++ b/sql/mysqld.cc 2010-04-06 22:47:08 +0000
@@ -1,4 +1,5 @@
/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+ 2009-2010 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -382,7 +383,7 @@ static bool volatile select_thread_in_us
static bool volatile ready_to_exit;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
-static my_bool opt_ignore_wrong_options= 0;
+static my_bool opt_ignore_wrong_options= 0, opt_expect_abort= 0;
static uint kill_cached_threads, wake_thread;
ulong thread_created;
static ulong max_used_connections;
@@ -2530,13 +2531,19 @@ extern "C" sig_handler handle_segfault(i
curr_time= my_time(0);
localtime_r(&curr_time, &tm);
- fprintf(stderr,"\
-%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\
+ fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d ",
+ tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ if (opt_expect_abort && sig == SIGABRT)
+ {
+ fprintf(stderr,"[Note] mysqld did an expected abort\n");
+ goto end;
+ }
+
+ fprintf(stderr,"[ERROR] mysqld got " SIGNAL_FMT " ;\n\
This could be because you hit a bug. It is also possible that this binary\n\
or one of the libraries it was linked against is corrupt, improperly built,\n\
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
- tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec,
sig);
fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
@@ -2655,6 +2662,7 @@ bugs.\n");
}
#endif
+end:
#ifndef __WIN__
/* On Windows, do not terminate, but pass control to exception filter */
exit(1);
@@ -5888,7 +5896,7 @@ enum options_mysqld
OPT_MIN_EXAMINED_ROW_LIMIT,
OPT_LOG_SLOW_SLAVE_STATEMENTS,
OPT_DEBUG_CRC, OPT_DEBUG_ON, OPT_OLD_MODE,
- OPT_TEST_IGNORE_WRONG_OPTIONS,
+ OPT_TEST_IGNORE_WRONG_OPTIONS, OPT_TEST_RESTART,
#if defined(ENABLED_DEBUG_SYNC)
OPT_DEBUG_SYNC_TIMEOUT,
#endif /* defined(ENABLED_DEBUG_SYNC) */
@@ -6737,6 +6745,10 @@ log and this option does nothing anymore
"Ignore wrong enums values in command line arguments. Useful only for test scripts",
(uchar**) &opt_ignore_wrong_options, (uchar**) &opt_ignore_wrong_options,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"test-expect-abort", OPT_TEST_RESTART,
+ "Expect that server aborts with 'abort'; Don't write out server variables on 'abort'. Useful only for test scripts",
+ (uchar**) &opt_expect_abort, (uchar**) &opt_expect_abort,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"timed_mutexes", OPT_TIMED_MUTEXES,
"Specify whether to time mutexes (only InnoDB mutexes are currently supported)",
(uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-03-28 18:10:00 +0000
+++ b/sql/set_var.cc 2010-04-06 22:47:08 +0000
@@ -2590,7 +2590,7 @@ static int sys_check_log_path(THD *thd,
char path[FN_REFLEN], buff[FN_REFLEN];
MY_STAT f_stat;
String str(buff, sizeof(buff), system_charset_info), *res;
- const char *log_file_str;
+ const char *log_file_str= 0;
size_t path_length;
if (!(res= var->value->val_str(&str)))
@@ -2640,7 +2640,7 @@ static int sys_check_log_path(THD *thd,
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name,
- res ? log_file_str : "NULL");
+ log_file_str ? log_file_str : "NULL");
return 1;
}
@@ -2649,7 +2649,7 @@ bool update_sys_var_str_path(THD *thd, s
set_var *var, const char *log_ext,
bool log_state, uint log_type)
{
- MYSQL_QUERY_LOG *file_log;
+ MYSQL_QUERY_LOG *file_log= 0;
char buff[FN_REFLEN];
char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
bool result= 0;
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2010-03-04 08:03:07 +0000
+++ b/sql/slave.cc 2010-04-06 22:47:08 +0000
@@ -2255,6 +2255,7 @@ static int exec_relay_log_event(THD* thd
if (slave_trans_retries)
{
int temp_err;
+ LINT_INIT(temp_err);
if (exec_res && (temp_err= has_temporary_error(thd)))
{
const char *errmsg;
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-12 19:05:21 +0000
+++ b/sql/sql_plugin.cc 2010-04-06 22:47:08 +0000
@@ -1701,9 +1701,10 @@ bool mysql_install_plugin(THD *thd, cons
if (tmp->state == PLUGIN_IS_DISABLED)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
- name->str, "Plugin is disabled");
+ if (global_system_variables.log_warnings)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
+ name->str, "Plugin is disabled");
}
else
{
=== modified file 'storage/xtradb/include/ut0lst.h'
--- a/storage/xtradb/include/ut0lst.h 2010-03-30 12:36:49 +0000
+++ b/storage/xtradb/include/ut0lst.h 2010-04-06 22:47:08 +0000
@@ -158,7 +158,7 @@ Inserts a NODE2 after NODE1 in a list.
/** Invalidate the pointers in a list node.
@param NAME list name
@param N pointer to the node that was removed */
-# define UT_LIST_REMOVE_CLEAR(NAME, N) {} while (0)
+# define UT_LIST_REMOVE_CLEAR(NAME, N) do {} while (0)
#endif
/*******************************************************************//**
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-04-01 09:40:11 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-06 22:47:08 +0000
@@ -40,6 +40,7 @@ sync/sync0sync\.c: unused parameter
sync/sync0sync\.c: unused variable
ut/ut0ut\.c: ignoring return value of
srv/srv0srv\.c: value computed is not used
+buf/buf0buf\.c: warning: .*block_mutex.* might be used uninitialized
#
# bdb is not critical to keep up to date
1
0

[Maria-developers] Rev 2793: Always refer to materialized table as "SUBSELECT#%d" where %d is select number in file:///home/psergey/dev/maria-5.3-subqueries-r12/
by Sergey Petrunya 06 Apr '10
by Sergey Petrunya 06 Apr '10
06 Apr '10
At file:///home/psergey/dev/maria-5.3-subqueries-r12/
------------------------------------------------------------
revno: 2793
revision-id: psergey(a)askmonty.org-20100406212909-r07zximlfpwmyxhm
parent: psergey(a)askmonty.org-20100406103533-0upq6g7sse9sjstz
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r12
timestamp: Wed 2010-04-07 01:29:09 +0400
message:
Always refer to materialized table as "SUBSELECT#%d" where %d is select number
- for Item-based materialization, it was "materialized subselect"
- for SJ-Materialization it was "subquery%d"
=== modified file 'mysql-test/r/group_min_max.result'
--- a/mysql-test/r/group_min_max.result 2010-04-06 08:10:58 +0000
+++ b/mysql-test/r/group_min_max.result 2010-04-06 21:29:09 +0000
@@ -2256,7 +2256,7 @@
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 8
-1 PRIMARY t1_outer ref a a 5 materialized subselect.max(b) 2 Using index
+1 PRIMARY t1_outer ref a a 5 SUBQUERY#2.max(b) 2 Using index
2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/subselect.result 2010-04-06 21:29:09 +0000
@@ -4328,14 +4328,14 @@
1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`SUBQUERY#2`.`1` = 1)
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`SUBQUERY#2`.`1` = 1)
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
=== modified file 'mysql-test/r/subselect3.result'
--- a/mysql-test/r/subselect3.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/subselect3.result 2010-04-06 21:29:09 +0000
@@ -1017,7 +1017,7 @@
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 8 Using temporary; Using filesort
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 8 Using temporary; Using filesort
1 PRIMARY t21 ALL NULL NULL NULL NULL 26 Using where; Using join buffer
1 PRIMARY t22 ALL NULL NULL NULL NULL 26 Using where; Using join buffer
2 SUBQUERY t11 ALL NULL NULL NULL NULL 8 Using where
@@ -1035,7 +1035,7 @@
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY X ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY subselect3 eq_ref unique_key unique_key 5 func 1
+2 DEPENDENT SUBQUERY SUBQUERY#3 eq_ref unique_key unique_key 5 func 1
3 SUBQUERY Z ALL NULL NULL NULL NULL 2
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
subq
@@ -1158,7 +1158,7 @@
insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 2
1 PRIMARY t3 ref a a 5 test.t2.a 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where a in (select a from t2);
@@ -1207,7 +1207,7 @@
explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref a a 5 test.t2.a 10
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10 Using where
explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
@@ -1241,14 +1241,14 @@
explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 system NULL NULL NULL NULL 1
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref a a 5 test.t2.a 10
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10 Using where
create table t4 as select a as x, a as y from t1;
explain select * from t0, t3 where (t3.a, t3.b) in (select x,y from t4) and (t3.a < 10 or t3.a >30);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 system NULL NULL NULL NULL 1
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref a a 5 test.t4.x 10 Using where
2 SUBQUERY t4 ALL NULL NULL NULL NULL 10 Using where
drop table t0,t1,t2,t3,t4;
@@ -1274,14 +1274,14 @@
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
-1 PRIMARY subselect2 eq_ref unique_key unique_key 10 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 10 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 100
set @save_optimizer_search_depth=@@optimizer_search_depth;
set @@optimizer_search_depth=63;
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
-1 PRIMARY subselect2 eq_ref unique_key unique_key 10 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 10 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 100
set @@optimizer_search_depth=@save_optimizer_search_depth;
set @@optimizer_switch=default;
@@ -1320,7 +1320,7 @@
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY subselect2 eq_ref unique_key unique_key 15 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 15 func 1
2 SUBQUERY X ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY Y ALL NULL NULL NULL NULL 6 Using join buffer
2 SUBQUERY Z ALL NULL NULL NULL NULL 6 Using join buffer
@@ -1393,7 +1393,7 @@
WHERE cona.postalStripped='T2H3B2'
);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2 1.00
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 2 1.00
1 PRIMARY a index PRIMARY PRIMARY 4 NULL 2 100.00 Using where; Using index; Using join buffer
2 SUBQUERY cona ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY c eq_ref PRIMARY PRIMARY 4 test.cona.idContact 1 100.00
=== modified file 'mysql-test/r/subselect3_jcl6.result'
--- a/mysql-test/r/subselect3_jcl6.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/subselect3_jcl6.result 2010-04-06 21:29:09 +0000
@@ -1021,7 +1021,7 @@
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 8 Using temporary; Using filesort
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 8 Using temporary; Using filesort
1 PRIMARY t21 ALL NULL NULL NULL NULL 26 Using where; Using join buffer
1 PRIMARY t22 ALL NULL NULL NULL NULL 26 Using where; Using join buffer
2 SUBQUERY t11 ALL NULL NULL NULL NULL 8 Using where
@@ -1040,7 +1040,7 @@
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY X ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY subselect3 eq_ref unique_key unique_key 5 func 1
+2 DEPENDENT SUBQUERY SUBQUERY#3 eq_ref unique_key unique_key 5 func 1
3 SUBQUERY Z ALL NULL NULL NULL NULL 2
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
subq
@@ -1163,7 +1163,7 @@
insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 2
1 PRIMARY t3 ref a a 5 test.t2.a 1 Using join buffer
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where a in (select a from t2);
@@ -1212,7 +1212,7 @@
explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref a a 5 test.t2.a 10 Using join buffer
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10 Using where
explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
@@ -1246,14 +1246,14 @@
explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 system NULL NULL NULL NULL 1
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref a a 5 test.t2.a 10 Using join buffer
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10 Using where
create table t4 as select a as x, a as y from t1;
explain select * from t0, t3 where (t3.a, t3.b) in (select x,y from t4) and (t3.a < 10 or t3.a >30);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 system NULL NULL NULL NULL 1
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref a a 5 test.t4.x 10 Using where; Using join buffer
2 SUBQUERY t4 ALL NULL NULL NULL NULL 10 Using where
drop table t0,t1,t2,t3,t4;
@@ -1279,14 +1279,14 @@
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
-1 PRIMARY subselect2 eq_ref unique_key unique_key 10 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 10 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 100
set @save_optimizer_search_depth=@@optimizer_search_depth;
set @@optimizer_search_depth=63;
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
-1 PRIMARY subselect2 eq_ref unique_key unique_key 10 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 10 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 100
set @@optimizer_search_depth=@save_optimizer_search_depth;
set @@optimizer_switch=default;
@@ -1325,7 +1325,7 @@
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY subselect2 eq_ref unique_key unique_key 15 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 15 func 1
2 SUBQUERY X ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY Y ALL NULL NULL NULL NULL 6 Using join buffer
2 SUBQUERY Z ALL NULL NULL NULL NULL 6 Using join buffer
@@ -1398,7 +1398,7 @@
WHERE cona.postalStripped='T2H3B2'
);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2 1.00
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 2 1.00
1 PRIMARY a index PRIMARY PRIMARY 4 NULL 2 100.00 Using where; Using index; Using join buffer
2 SUBQUERY cona ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY c eq_ref PRIMARY PRIMARY 4 test.cona.idContact 1 100.00 Using join buffer
=== modified file 'mysql-test/r/subselect4.result'
--- a/mysql-test/r/subselect4.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect4.result 2010-04-06 21:29:09 +0000
@@ -216,7 +216,7 @@
WHERE PTYPE = 'Design'));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL t1_IDX NULL NULL NULL 5
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
PREPARE stmt FROM "EXPLAIN SELECT EMPNAME
@@ -231,13 +231,13 @@
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL t1_IDX NULL NULL NULL 5
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL t1_IDX NULL NULL NULL 5
-1 SIMPLE subselect2 eq_ref unique_key unique_key 3 func 1
+1 SIMPLE SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
DEALLOCATE PREPARE stmt;
@@ -254,7 +254,7 @@
WHERE PTYPE = 'Design'));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL t1_IDX NULL NULL NULL 5
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
PREPARE stmt FROM "EXPLAIN SELECT EMPNAME
@@ -269,13 +269,13 @@
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL t1_IDX NULL NULL NULL 5
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL t1_IDX NULL NULL NULL 5
-1 SIMPLE subselect2 eq_ref unique_key unique_key 3 func 1
+1 SIMPLE SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
DEALLOCATE PREPARE stmt;
@@ -291,7 +291,7 @@
WHERE PTYPE = 'Design'));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
PREPARE stmt FROM "EXPLAIN SELECT EMPNAME
@@ -306,13 +306,13 @@
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5
-1 SIMPLE subselect2 eq_ref unique_key unique_key 3 func 1
+1 SIMPLE SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer
DEALLOCATE PREPARE stmt;
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result 2010-04-06 10:35:33 +0000
+++ b/mysql-test/r/subselect_mat.result 2010-04-06 21:29:09 +0000
@@ -42,7 +42,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 9 test.t1.a1 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0')) join `test`.`t1` where (`materialized subselect`.`b1` = `test`.`t1`.`a1`)
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0')) join `test`.`t1` where (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`)
select * from t1 where a1 in (select b1 from t2 where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -54,7 +54,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 9 test.t1.a1 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`) join `test`.`t1` where (`materialized subselect`.`b1` = `test`.`t1`.`a1`)
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`) join `test`.`t1` where (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`)
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -66,7 +66,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`b2` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`SUBQUERY#2`.`b2` = `test`.`t1`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -78,7 +78,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,min(`test`.`t2`.`b2`) AS `min(b2)` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`) join `test`.`t1` where ((`materialized subselect`.`min(b2)` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,min(`test`.`t2`.`b2`) AS `min(b2)` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`) join `test`.`t1` where ((`SUBQUERY#2`.`min(b2)` = `test`.`t1`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -90,7 +90,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 9 test.t1i.a1 1 100.00
2 SUBQUERY t2i index it2i1,it2i3 it2i1 9 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where (`materialized subselect`.`b1` = `test`.`t1i`.`a1`)
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where (`SUBQUERY#2`.`b1` = `test`.`t1i`.`a1`)
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -102,7 +102,7 @@
1 PRIMARY t1i ref it1i1,it1i3 # 9 # 1 100.00 #
2 SUBQUERY t2i range it2i1,it2i3 # 9 # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where (`test`.`t1i`.`a1` = `materialized subselect`.`b1`)
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where (`test`.`t1i`.`a1` = `SUBQUERY#2`.`b1`)
select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -114,7 +114,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1i.a1,test.t1i.a2 1 100.00
2 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`materialized subselect`.`b2` = `test`.`t1i`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1i`.`a1`))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`SUBQUERY#2`.`b2` = `test`.`t1i`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1i`.`a1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -126,7 +126,7 @@
1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
2 SUBQUERY t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `SUBQUERY#2`.`b2`) and (`test`.`t1i`.`a1` = `SUBQUERY#2`.`b1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -138,7 +138,7 @@
1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
2 SUBQUERY t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `materialized subselect`.`min(b2)`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `SUBQUERY#2`.`min(b2)`) and (`test`.`t1i`.`a1` = `SUBQUERY#2`.`b1`))
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -150,7 +150,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2i range NULL it2i3 9 NULL 3 100.00 Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,max(`test`.`t2i`.`b2`) AS `max(b2)` from `test`.`t2i` group by `test`.`t2i`.`b1`) join `test`.`t1` where ((`materialized subselect`.`max(b2)` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,max(`test`.`t2i`.`b2`) AS `max(b2)` from `test`.`t2i` group by `test`.`t2i`.`b1`) join `test`.`t1` where ((`SUBQUERY#2`.`max(b2)` = `test`.`t1`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1);
a1 a2
1 - 01 2 - 01
@@ -182,7 +182,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1` where ((`materialized subselect`.`min(b2)` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1` where ((`SUBQUERY#2`.`min(b2)` = `test`.`t1`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -223,7 +223,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`b2` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`SUBQUERY#2`.`b2` = `test`.`t1`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -235,7 +235,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1i.a1,test.t1i.a2 1 100.00
2 SUBQUERY t2i index NULL it2i3 18 NULL 5 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`materialized subselect`.`b2` = `test`.`t1i`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1i`.`a1`))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`SUBQUERY#2`.`b2` = `test`.`t1i`.`a2`) and (`SUBQUERY#2`.`b1` = `test`.`t1i`.`a1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -286,14 +286,14 @@
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
-1 PRIMARY SUBQUERY#3 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+1 PRIMARY SUBQUERY#3 eq_ref distinct_key distinct_key 18 SUBQUERY#2.b1,SUBQUERY#2.b2 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
3 SUBQUERY SUBQUERY#4 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
4 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0')) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`SUBQUERY#4`.`b2` = `test`.`t3`.`c2`) and (`SUBQUERY#4`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0')) join `test`.`t1` where ((`SUBQUERY#3`.`c2` = `SUBQUERY#2`.`b2`) and (`test`.`t1`.`a2` = `SUBQUERY#2`.`b2`) and (`SUBQUERY#3`.`c1` = `SUBQUERY#2`.`b1`) and (`test`.`t1`.`a1` = `SUBQUERY#2`.`b1`))
select * from t1
where (a1, a2) in (select b1, b2 from t2 where b1 > '0') and
(a1, a2) in (select c1, c2 from t3
@@ -315,7 +315,7 @@
4 SUBQUERY t2i index it2i2 # # # 5 100.00 #
2 SUBQUERY t2i index it2i1,it2i3 # # # 5 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`materialized subselect`.`b2` = `test`.`t3i`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`SUBQUERY#4`.`b2` = `test`.`t3i`.`c2`) and (`SUBQUERY#4`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`SUBQUERY#3`.`c2` = `SUBQUERY#2`.`b2`) and (`test`.`t1i`.`a2` = `SUBQUERY#2`.`b2`) and (`SUBQUERY#3`.`c1` = `SUBQUERY#2`.`b1`) and (`test`.`t1i`.`a1` = `SUBQUERY#2`.`b1`))
select * from t1i
where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i
@@ -332,7 +332,7 @@
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
-1 PRIMARY SUBQUERY#5 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+1 PRIMARY SUBQUERY#5 eq_ref distinct_key distinct_key 18 SUBQUERY#2.b1,SUBQUERY#2.b2 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer
5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
5 SUBQUERY SUBQUERY#6 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
@@ -341,7 +341,7 @@
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(
`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))))) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`SUBQUERY#6`.`b2` = `test`.`t3`.`c2`) and (`SUBQUERY#6`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `SUBQUERY#3`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table
> on distinct_key where ((`test`.`t2`.`b2` = `SUBQUERY#4`.`c2`))))))) join `test`.`t1` where ((`SUBQUERY#5`.`c2` = `SUBQUERY#2`.`b2`) and (`test`.`t1`.`a2` = `SUBQUERY#2`.`b2`) and (`SUBQUERY#5`.`c1` = `SUBQUERY#2`.`b1`) and (`test`.`t1`.`a1` = `SUBQUERY#2`.`b1`))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -368,7 +368,7 @@
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` `t3c` where ((`materialized subselect`.`b2` = `test`.`t3c`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3c`.`c1`))) join `test`.`t1` where ((`materialized subselect`.`c2` = `test`.`t1`.`a2`) and (`materialized subselect`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` fr
om `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` `t3c` where ((`SUBQUERY#6`.`b2` = `test`.`t3c`.`c2`) and (`SUBQUERY#6`.`b1` = `test`.`t3c`.`c1`))) join `test`.`t1` where ((`SUBQUERY#5`.`c2` = `test`.`t1`.`a2`) and (`SUBQUERY#5`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` li
ke '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `SUBQUERY#4`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
@@ -410,7 +410,7 @@
8 SUBQUERY t2i index it2i1,it2i3 # # # 5 100.00 #
NULL UNION RESULT <union1,7> ALL NULL # # # NULL NULL #
Warnings:
-Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>
(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`materialized subselect`.`b2` = `test`.`t3i`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i
` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))
+Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`SUBQUERY#6`.`b2` = `test`.`t3`.`c2`) and (`SUBQUERY#6`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `SUBQUERY#3`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary tabl
e> on distinct_key where ((`test`.`t2`.`b2` = `SUBQUERY#4`.`c2`)))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`SUBQUERY#5`.`c2` = `SUBQUERY#2`.`b2`) and (`test`.`t1`.`a2` = `SUBQUERY#2`.`b2`) and (`SUBQUERY#5`.`c1` = `SUBQUERY#2`.`b1`) and (`test`.`t1`.`a1` = `SUBQUERY#2`.`b1`))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`SUBQUERY#10`.`b2` = `test`.`t3i`.`c2`) and (`SUBQUERY#10`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`SUBQUERY#9`.`c2` = `SUBQUERY#8`.`b2`) and (`test`.`t1i`.`a2` = `SUBQUERY#8`.`b2`) and (`SUBQUERY#9`.`c1` = `SUBQUERY#8`.`b1`) and (
`test`.`t1i`.`a1` = `SUBQUERY#8`.`b1`)))
(select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -441,7 +441,7 @@
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join `test`.`t1` where ((`materialized subselect`.`c2` = `test`.`t1`.`a2`) and (`materialized subselect`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`t
est`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`SUBQUERY#5`.`b2` = `test`.`t3`.`c2`) and (`SUBQUERY#5`.`b1` = `test`.`t3`.`c1`))) join `test`.`t1` where ((`SUBQUERY#4`.`c2` = `test`.`t1`.`a2`) and (`SUBQUERY#4`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
select * from t1
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(a1, a2) in (select c1, c2 from t3
@@ -466,7 +466,7 @@
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`c2` = `materialized subselect`.`c2`) and (`materialized subselect`.`c1` = `test`.`t1`.`a1`) and (`test`.`t3`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `
test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`SUBQUERY#5`.`b2` = `test`.`t3`.`c2`) and (`SUBQUERY#5`.`b1` = `test`.`t3`.`c1`))) join `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`c2` = `SUBQUERY#4`.`c2`) and (`SUBQUERY#4`.`c1` = `test`.`t1`.`a1`) and (`test`.`t3`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (
<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -512,7 +512,7 @@
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from `test`.`t3` `t3c` where (<i
n_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (((`test`.`t2i`.`b2` > '0') or (`test`.`t2i`.`b2` = `test`.`t1`.`a2`)) and (<cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1`) and (<cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `SUBQUERY#4`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from `test`.`t3` `t3c` where (<in_optimizer>
((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (((`test`.`t2i`.`b2` > '0') or (`test`.`t2i`.`b2` = `test`.`t1`.`a2`)) and (<cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1`) and (<cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))))
explain extended
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -648,7 +648,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 20 test.t1_16.a1 1 100.00 Using where
2 SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) AS `substring(b1,1,16)` from `test`.`t2_16` where (`test`.`t2_16`.`b1` > '0')) join `test`.`t1_16` where (`test`.`t1_16`.`a1` = `materialized subselect`.`substring(b1,1,16)`)
+Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) AS `substring(b1,1,16)` from `test`.`t2_16` where (`test`.`t2_16`.`b1` > '0')) join `test`.`t1_16` where (`test`.`t1_16`.`a1` = `SUBQUERY#2`.`substring(b1,1,16)`)
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select substring(b1,1,16) from t2_16 where b1 > '0');
@@ -678,7 +678,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_16.a1 1 100.00 Using where
2 SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_16` group by `test`.`t2_16`.`b2`) join `test`.`t1_16` where (`test`.`t1_16`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_16` group by `test`.`t2_16`.`b2`) join `test`.`t1_16` where (`test`.`t1_16`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -701,7 +701,7 @@
3 DEPENDENT SUBQUERY SUBQUERY#4 eq_ref distinct_key distinct_key 9 test.t2.b1 1 100.00 Using where
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(select 1 AS `Not_used` from `test`.`t1_16` where (<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(select `test`.`t2_16`.`b1` AS `b1`,`test`.`t2_16`.`b2` AS `b2` from <materialize> (select `test`.`t3`.`c1` AS `c1` from `test`.`t3` where (`test`.`t3`.`c2` > '0')) join `test`.`t2_16` join `test`.`t2` where ((`materialized subselect`.`c1` = `test`.`t2`.`b1`) and (`test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6)) and (<cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`) and (<cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))) and (<cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(select 1 AS `Not_used` from `test`.`t1_16` where (<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(select `test`.`t2_16`.`b1` AS `b1`,`test`.`t2_16`.`b2` AS `b2` from <materialize> (select `test`.`t3`.`c1` AS `c1` from `test`.`t3` where (`test`.`t3`.`c2` > '0')) join `test`.`t2_16` join `test`.`t2` where ((`SUBQUERY#4`.`c1` = `test`.`t2`.`b1`) and (`test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6)) and (<cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`) and (<cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))) and (<cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8)))))
drop table t1_16, t2_16, t3_16;
set @blob_len = 512;
set @suffix_len = @blob_len - @prefix_len;
@@ -764,7 +764,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 517 test.t1_512.a1 1 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) AS `substring(b1,1,512)` from `test`.`t2_512` where (`test`.`t2_512`.`b1` > '0')) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `materialized subselect`.`substring(b1,1,512)`)
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) AS `substring(b1,1,512)` from `test`.`t2_512` where (`test`.`t2_512`.`b1` > '0')) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `SUBQUERY#2`.`substring(b1,1,512)`)
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select substring(b1,1,512) from t2_512 where b1 > '0');
@@ -779,7 +779,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_512.a1 1 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -793,7 +793,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_512.a1 1 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -874,7 +874,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1024.a1 1 100.00 Using where
2 SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where (`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where (`test`.`t1_1024`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -888,7 +888,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1024.a1 1 100.00 Using where
2 SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where (`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where (`test`.`t1_1024`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -969,7 +969,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1025.a1 1 100.00 Using where
2 SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where (`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where (`test`.`t1_1025`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -983,7 +983,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1025.a1 1 100.00 Using where
2 SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where (`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where (`test`.`t1_1025`.`a1` = `SUBQUERY#2`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -1006,7 +1006,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 10 test.t1bit.a1,test.t1bit.a2 1 100.00 Using where
2 SUBQUERY t2bit ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from <materialize> (select `test`.`t2bit`.`b1` AS `b1`,`test`.`t2bit`.`b2` AS `b2` from `test`.`t2bit`) join `test`.`t1bit` where ((`test`.`t1bit`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1bit`.`a2` = `materialized subselect`.`b2`))
+Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from <materialize> (select `test`.`t2bit`.`b1` AS `b1`,`test`.`t2bit`.`b2` AS `b2` from `test`.`t2bit`) join `test`.`t1bit` where ((`test`.`t1bit`.`a1` = `SUBQUERY#2`.`b1`) and (`test`.`t1bit`.`a2` = `SUBQUERY#2`.`b2`))
select bin(a1), bin(a2)
from t1bit
where (a1, a2) in (select b1, b2 from t2bit);
@@ -1078,7 +1078,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t1.a 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`materialized subselect`.`c` = `test`.`t1`.`a`)
+Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`SUBQUERY#2`.`c` = `test`.`t1`.`a`)
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1093,7 +1093,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t1.a 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`materialized subselect`.`c` = `test`.`t1`.`a`)
+Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`SUBQUERY#2`.`c` = `test`.`t1`.`a`)
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1108,7 +1108,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t1.a 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`materialized subselect`.`c` = `test`.`t1`.`a`)
+Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`SUBQUERY#2`.`c` = `test`.`t1`.`a`)
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1121,7 +1121,7 @@
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `SUBQUERY#2`.`c`)))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1133,7 +1133,7 @@
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `SUBQUERY#2`.`c`)))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1253,7 +1253,7 @@
SET @@optimizer_switch='default,semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
@@ -1275,7 +1275,7 @@
EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 Using index condition; Using MRR
SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
pk
=== modified file 'mysql-test/r/subselect_no_semijoin.result'
--- a/mysql-test/r/subselect_no_semijoin.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/subselect_no_semijoin.result 2010-04-06 21:29:09 +0000
@@ -1303,7 +1303,7 @@
1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer
2 SUBQUERY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1`) join `test`.`t2` where (`test`.`t2`.`a` = `materialized subselect`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1`) join `test`.`t2` where (`test`.`t2`.`a` = `SUBQUERY#2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1314,7 +1314,7 @@
1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer
2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`test`.`t2`.`a` = `materialized subselect`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`test`.`t2`.`a` = `SUBQUERY#2`.`a`)
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1326,7 +1326,7 @@
2 SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using index
2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`)) join `test`.`t2` where (`SUBQUERY#2`.`a` = `test`.`t2`.`a`)
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1349,7 +1349,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1`) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1`) join `test`.`t2` where (`SUBQUERY#2`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1360,7 +1360,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`SUBQUERY#2`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1372,7 +1372,7 @@
2 SUBQUERY t3 index a a 5 NULL 3 100.00 Using index
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using where; Using index; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`)) join `test`.`t2` where (`SUBQUERY#2`.`a` = `test`.`t2`.`a`)
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1389,7 +1389,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t1 index NULL a 10 NULL 10005 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`SUBQUERY#2`.`a` = `test`.`t2`.`a`)
drop table t0, t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -2844,7 +2844,7 @@
1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 10 test.t1.one,test.t1.two 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from <materialize> (select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = 'N')) join `test`.`t1` where ((`materialized subselect`.`two` = `test`.`t1`.`two`) and (`materialized subselect`.`one` = `test`.`t1`.`one`))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from <materialize> (select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = 'N')) join `test`.`t1` where ((`SUBQUERY#2`.`two` = `test`.`t1`.`two`) and (`SUBQUERY#2`.`one` = `test`.`t1`.`one`))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -4343,14 +4343,14 @@
1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`SUBQUERY#2`.`1` = 1)
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`SUBQUERY#2`.`1` = 1)
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
=== modified file 'mysql-test/r/subselect_sj.result'
--- a/mysql-test/r/subselect_sj.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect_sj.result 2010-04-06 21:29:09 +0000
@@ -848,7 +848,7 @@
EXPLAIN EXTENDED SELECT pk FROM t1 WHERE (a, b) IN (SELECT a, b FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-1 PRIMARY subselect2 eq_ref unique_key unique_key 13 func 1 1.00
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 13 func 1 1.00
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 100.00 Using index condition; Using MRR
Warnings:
Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`pk` > 0))
@@ -1017,7 +1017,7 @@
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
-1 PRIMARY subselect2 eq_ref unique_key unique_key 8 func 1 1.00
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 8 func 1 1.00
2 SUBQUERY t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key`) and ((`test`.`t1`.`varchar_nokey` < 'n') xor `test`.`t1`.`pk`))
=== modified file 'mysql-test/r/subselect_sj2.result'
--- a/mysql-test/r/subselect_sj2.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect_sj2.result 2010-04-06 21:29:09 +0000
@@ -32,7 +32,7 @@
9 5
explain select * from t2 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 3
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 3
1 PRIMARY t2 ref b b 5 test.t1.a 2
2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
select * from t2 where b in (select a from t1);
@@ -74,7 +74,7 @@
from t0 A, t0 B where B.a <5;
explain select * from t3 where b in (select a from t0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref b b 5 test.t0.a 1
2 SUBQUERY t0 ALL NULL NULL NULL NULL 10
set @save_ecp= @@engine_condition_pushdown;
@@ -101,7 +101,7 @@
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY t2 index b b 5 NULL 10 Using index
select * from t1;
a b
@@ -129,7 +129,7 @@
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 22
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 22
1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer
2 SUBQUERY it ALL NULL NULL NULL NULL 22
select
@@ -163,7 +163,7 @@
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY it ALL NULL NULL NULL NULL 32
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
@@ -197,7 +197,7 @@
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 22
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 22
1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer
2 SUBQUERY it ALL NULL NULL NULL NULL 22
select
@@ -231,7 +231,7 @@
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY it ALL NULL NULL NULL NULL 52
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
@@ -348,7 +348,7 @@
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 31
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL CountryCode NULL NULL NULL 545 Using where
SELECT Name FROM t1
WHERE t1.Code IN (
@@ -692,7 +692,7 @@
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index a a 5 NULL 1000 Using index
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
=== modified file 'mysql-test/r/subselect_sj2_jcl6.result'
--- a/mysql-test/r/subselect_sj2_jcl6.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect_sj2_jcl6.result 2010-04-06 21:29:09 +0000
@@ -36,7 +36,7 @@
9 5
explain select * from t2 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 3
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 3
1 PRIMARY t2 ref b b 5 test.t1.a 2 Using join buffer
2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
select * from t2 where b in (select a from t1);
@@ -78,7 +78,7 @@
from t0 A, t0 B where B.a <5;
explain select * from t3 where b in (select a from t0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 10
1 PRIMARY t3 ref b b 5 test.t0.a 1 Using join buffer
2 SUBQUERY t0 ALL NULL NULL NULL NULL 10
set @save_ecp= @@engine_condition_pushdown;
@@ -105,7 +105,7 @@
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY t2 index b b 5 NULL 10 Using index
select * from t1;
a b
@@ -133,7 +133,7 @@
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 22
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 22
1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer
2 SUBQUERY it ALL NULL NULL NULL NULL 22
select
@@ -167,7 +167,7 @@
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY it ALL NULL NULL NULL NULL 32
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
@@ -201,7 +201,7 @@
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 22
+1 PRIMARY SUBQUERY#2 ALL unique_key NULL NULL NULL 22
1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer
2 SUBQUERY it ALL NULL NULL NULL NULL 22
select
@@ -235,7 +235,7 @@
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY it ALL NULL NULL NULL NULL 52
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
@@ -352,7 +352,7 @@
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 31
-1 PRIMARY subselect2 eq_ref unique_key unique_key 3 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 3 func 1
2 SUBQUERY t2 ALL CountryCode NULL NULL NULL 545 Using where
SELECT Name FROM t1
WHERE t1.Code IN (
@@ -698,7 +698,7 @@
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index a a 5 NULL 1000 Using index
-1 PRIMARY subselect2 eq_ref unique_key unique_key 5 func 1
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 5 func 1
2 SUBQUERY t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
=== modified file 'mysql-test/r/subselect_sj_jcl6.result'
--- a/mysql-test/r/subselect_sj_jcl6.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect_sj_jcl6.result 2010-04-06 21:29:09 +0000
@@ -852,7 +852,7 @@
EXPLAIN EXTENDED SELECT pk FROM t1 WHERE (a, b) IN (SELECT a, b FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-1 PRIMARY subselect2 eq_ref unique_key unique_key 13 func 1 1.00
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 13 func 1 1.00
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 100.00 Using index condition; Using MRR
Warnings:
Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`pk` > 0))
@@ -1021,7 +1021,7 @@
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
-1 PRIMARY subselect2 eq_ref unique_key unique_key 8 func 1 1.00
+1 PRIMARY SUBQUERY#2 eq_ref unique_key unique_key 8 func 1 1.00
2 SUBQUERY t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key`) and ((`test`.`t1`.`varchar_nokey` < 'n') xor `test`.`t1`.`pk`))
=== modified file 'mysql-test/suite/pbxt/r/group_min_max.result'
--- a/mysql-test/suite/pbxt/r/group_min_max.result 2010-04-06 08:10:58 +0000
+++ b/mysql-test/suite/pbxt/r/group_min_max.result 2010-04-06 21:29:09 +0000
@@ -2257,7 +2257,7 @@
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 15
-1 PRIMARY t1_outer ref a a 5 materialized subselect.max(b) 1 Using index
+1 PRIMARY t1_outer ref a a 5 SUBQUERY#2.max(b) 1 Using index
2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
=== modified file 'mysql-test/suite/pbxt/r/subselect.result'
--- a/mysql-test/suite/pbxt/r/subselect.result 2010-04-06 08:10:58 +0000
+++ b/mysql-test/suite/pbxt/r/subselect.result 2010-04-06 21:29:09 +0000
@@ -3433,7 +3433,7 @@
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 9
-1 PRIMARY t1 ref a a 8 materialized subselect.a 1 Using where
+1 PRIMARY t1 ref a a 8 SUBQUERY#2.a 1 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2010-04-05 20:16:45 +0000
+++ b/sql/item_subselect.cc 2010-04-06 21:29:09 +0000
@@ -2116,7 +2116,8 @@
if (!(new_engine= new subselect_hash_sj_engine(thd, this,
old_engine)) ||
- new_engine->init_permanent(unit->get_unit_column_types()))
+ new_engine->init_permanent(unit->get_unit_column_types(),
+ old_engine->get_identifier()))
{
Item_subselect::trans_res trans_res;
/*
@@ -3662,6 +3663,7 @@
reexecution.
@param tmp_columns the items that produce the data for the temp table
+ @param subquery_id subquery's identifier (for temptable name)
@details
- Create a temporary table to store the result of the IN subquery. The
@@ -3677,7 +3679,8 @@
@retval FALSE otherwise
*/
-bool subselect_hash_sj_engine::init_permanent(List<Item> *tmp_columns)
+bool subselect_hash_sj_engine::init_permanent(List<Item> *tmp_columns,
+ uint subquery_id)
{
/* Options to create_tmp_table. */
ulonglong tmp_create_options= thd->options | TMP_TABLE_ALL_COLUMNS;
@@ -3712,12 +3715,19 @@
DBUG_RETURN(TRUE);
}
*/
+ char buf[32];
+ uint len= my_snprintf(buf, sizeof(buf), "SUBQUERY#%d", subquery_id);
+ char *name;
+ if (!(name= (char*)thd->alloc(len + 1)))
+ DBUG_RETURN(TRUE);
+ memcpy(name, buf, len+1);
+
if (!(result= new select_materialize_with_stats))
DBUG_RETURN(TRUE);
if (((select_union*) result)->create_result_table(
thd, tmp_columns, TRUE, tmp_create_options,
- "materialized subselect", TRUE))
+ name, TRUE))
DBUG_RETURN(TRUE);
tmp_table= ((select_union*) result)->table;
@@ -3798,7 +3808,7 @@
if (!(tmp_table_ref= (TABLE_LIST*) thd->alloc(sizeof(TABLE_LIST))))
DBUG_RETURN(TRUE);
- tmp_table_ref->init_one_table("", "materialized subselect", TL_READ);
+ tmp_table_ref->init_one_table("", tmp_table->alias, TL_READ);
tmp_table_ref->table= tmp_table;
context= new Name_resolution_context;
=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h 2010-04-05 20:16:45 +0000
+++ b/sql/item_subselect.h 2010-04-06 21:29:09 +0000
@@ -814,7 +814,7 @@
}
~subselect_hash_sj_engine();
- bool init_permanent(List<Item> *tmp_columns);
+ bool init_permanent(List<Item> *tmp_columns, uint subquery_id);
bool init_runtime();
void cleanup();
int prepare() { return 0; } /* Override virtual function in base class. */
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-04-05 20:16:45 +0000
+++ b/sql/sql_select.cc 2010-04-06 21:29:09 +0000
@@ -18004,7 +18004,7 @@
/* table */
int len= my_snprintf(table_name_buffer,
sizeof(table_name_buffer)-1,
- "subselect%d",
+ "SUBQUERY#%d",
tab->emb_sj_nest->sj_subq_pred->get_identifier());
item_list.push_back(new Item_string(table_name_buffer, len, cs));
/* partitions */
1
0

[Maria-developers] bzr commit into file:///home/tsk/mprog/src/5.3-subqueries/ branch (timour:2790)
by timour@askmonty.org 06 Apr '10
by timour@askmonty.org 06 Apr '10
06 Apr '10
#At file:///home/tsk/mprog/src/5.3-subqueries/ based on revid:timour@askmonty.org-20100405211515-istsgehaz7zafg0l
2790 timour(a)askmonty.org 2010-04-06
Fixed an error in the creation of REF access method for materialized
semi-join, where the the REF buffer format was mistaken to be in
record format instead of key format. The error was that the null
byte for all fields of the record was in the front of the buffer,
and not before each field data.
modified:
sql/opt_subselect.cc
=== modified file 'sql/opt_subselect.cc'
--- a/sql/opt_subselect.cc 2010-03-15 19:52:58 +0000
+++ b/sql/opt_subselect.cc 2010-04-06 19:56:20 +0000
@@ -2296,7 +2296,7 @@ bool setup_sj_materialization(JOIN_TAB *
use that information instead.
*/
cur_ref_buff + null_count,
- null_count ? tab_ref->key_buff : 0,
+ null_count ? cur_ref_buff : 0,
cur_key_part->length, tab_ref->items[i]);
cur_ref_buff+= cur_key_part->store_length;
}
1
0

[Maria-developers] Progress (by Knielsen): Merge OQGraph into MariaDB (112)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Merge OQGraph into MariaDB
CREATION DATE..: Mon, 29 Mar 2010, 18:00
SUPERVISOR.....: Knielsen
IMPLEMENTOR....: Knielsen
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 112 (http://askmonty.org/worklog/?tid=112)
VERSION........: Server-5.2
STATUS.........: Code-Review
PRIORITY.......: 60
WORKED HOURS...: 13
ESTIMATE.......: 2 (hours remain)
ORIG. ESTIMATE.: 15
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:28)=-=-
Fixed all issues from first code review.
Implement packaging for OQGraph in bakery.
Set up buildbot hosts for including OQGraph, including binary packaging.
Worked 13 hours and estimate 2 hours remain (original estimate unchanged).
-=-=(Knielsen - Wed, 31 Mar 2010, 13:38)=-=-
Status updated.
--- /tmp/wklog.112.old.12166 2010-03-31 13:38:25.000000000 +0000
+++ /tmp/wklog.112.new.12166 2010-03-31 13:38:25.000000000 +0000
@@ -1 +1 @@
-Assigned
+Code-Review
-=-=(Knielsen - Wed, 31 Mar 2010, 13:38)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.12070 2010-03-31 13:38:08.000000000 +0000
+++ /tmp/wklog.112.new.12070 2010-03-31 13:38:08.000000000 +0000
@@ -15,3 +15,5 @@
Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
if such boost is found.
+Update the packaging in ourdelta/bakery to include the oqgraph_engine.so and
+link with g++ rather than gcc.
-=-=(Knielsen - Mon, 29 Mar 2010, 21:46)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.31142 2010-03-29 21:46:11.000000000 +0000
+++ /tmp/wklog.112.new.31142 2010-03-29 21:46:11.000000000 +0000
@@ -1,28 +1,17 @@
Tasks:
-Find the latest version of OQGraph to base this on (there should be a
-Launchpad branch somewhere, match it up with what is in the OQGraph patch for
-MySQL 5.0 in the ourdelta stuff).
-
-Extract the correct version of Boost from the MySQL 5.0 ourdelta patch. This
-is a patched version of Boost fixing a bug that is supposedly fatal for
-OQGraph (details are not known at the time of writing).
+Base work on the Launchpad branch lp:~knielsen/maria/mariadb-5.1-oqgraph
-Document in OQGraph README the need for boost of a specific version, and point
-to where it can be obtained. Also include the patch for boost if the correct
-base version of boost to do this against can be determined.
+OQGraph requires Boost >= 1.40.0 (earlier versions have a bug that affects
+OQGraph).
-Install the patched boost in /usr/local/ on the build machines (release builds
-and selected Buildbot slaves).
+Document in OQGraph README the need for boost of a specific version, and point
+to where it can be obtained.
-Fix OQGraph plug.in to detect correct version of OQGraph that makes the build
-not break. Check which version in Ubuntu starts working (I think it was
-Jaunty), and require at least that version.
-
-Setup some repository or source tarball of the patched boost
-somewhere. Preferably a Launchpad branch or similar (if upstream project can
-be found).
+Install the patched boost in /usr/local/include/boost on the build machines
+(release builds and selected Buildbot slaves). G++ seems to by default look in
+/usr/local/include, so that is sufficient to find it.
-Setup in plug.in or /configure.in appropriate --with-boost=xxx. Or in a pinch,
-we can make do with CFLAGS=-Ixxx, or even default look in /usr/local/.
+Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
+if such boost is found.
-=-=(Knielsen - Mon, 29 Mar 2010, 18:09)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.23061 2010-03-29 18:09:27.000000000 +0000
+++ /tmp/wklog.112.new.23061 2010-03-29 18:09:27.000000000 +0000
@@ -1 +1,28 @@
+Tasks:
+
+Find the latest version of OQGraph to base this on (there should be a
+Launchpad branch somewhere, match it up with what is in the OQGraph patch for
+MySQL 5.0 in the ourdelta stuff).
+
+Extract the correct version of Boost from the MySQL 5.0 ourdelta patch. This
+is a patched version of Boost fixing a bug that is supposedly fatal for
+OQGraph (details are not known at the time of writing).
+
+Document in OQGraph README the need for boost of a specific version, and point
+to where it can be obtained. Also include the patch for boost if the correct
+base version of boost to do this against can be determined.
+
+Install the patched boost in /usr/local/ on the build machines (release builds
+and selected Buildbot slaves).
+
+Fix OQGraph plug.in to detect correct version of OQGraph that makes the build
+not break. Check which version in Ubuntu starts working (I think it was
+Jaunty), and require at least that version.
+
+Setup some repository or source tarball of the patched boost
+somewhere. Preferably a Launchpad branch or similar (if upstream project can
+be found).
+
+Setup in plug.in or /configure.in appropriate --with-boost=xxx. Or in a pinch,
+we can make do with CFLAGS=-Ixxx, or even default look in /usr/local/.
DESCRIPTION:
Get the OQGraph storage engine merged into MariaDB, fixing the remaining
problems blocking the merge.
HIGH-LEVEL SPECIFICATION:
Tasks:
Base work on the Launchpad branch lp:~knielsen/maria/mariadb-5.1-oqgraph
OQGraph requires Boost >= 1.40.0 (earlier versions have a bug that affects
OQGraph).
Document in OQGraph README the need for boost of a specific version, and point
to where it can be obtained.
Install the patched boost in /usr/local/include/boost on the build machines
(release builds and selected Buildbot slaves). G++ seems to by default look in
/usr/local/include, so that is sufficient to find it.
Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
if such boost is found.
Update the packaging in ourdelta/bakery to include the oqgraph_engine.so and
link with g++ rather than gcc.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Progress (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 47
ESTIMATE.......: 8 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:26)=-=-
Code review (mailed to maria-developers@).
Worked 7 hours and estimate 8 hours remain (original estimate unchanged).
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
------------------------------------------------------------
-=-=(View All Progress Notes, 27 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Progress (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 47
ESTIMATE.......: 8 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:26)=-=-
Code review (mailed to maria-developers@).
Worked 7 hours and estimate 8 hours remain (original estimate unchanged).
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
------------------------------------------------------------
-=-=(View All Progress Notes, 27 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Progress (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 47
ESTIMATE.......: 8 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:26)=-=-
Code review (mailed to maria-developers@).
Worked 7 hours and estimate 8 hours remain (original estimate unchanged).
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
------------------------------------------------------------
-=-=(View All Progress Notes, 27 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Progress (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 47
ESTIMATE.......: 8 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:26)=-=-
Code review (mailed to maria-developers@).
Worked 7 hours and estimate 8 hours remain (original estimate unchanged).
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
------------------------------------------------------------
-=-=(View All Progress Notes, 27 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 40
ESTIMATE.......: 15 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
-=-=(Alexi - Sun, 20 Dec 2009, 09:29)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.32726 2009-12-20 07:29:56.000000000 +0000
+++ /tmp/wklog.47.new.32726 2009-12-20 07:29:56.000000000 +0000
@@ -56,7 +56,7 @@
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
- 00000082 | 00 | 0 - ANNOTATE_RBR_EVENT [51]
+ 00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
------------------------------------------------------------
-=-=(View All Progress Notes, 26 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 40
ESTIMATE.......: 15 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
-=-=(Alexi - Sun, 20 Dec 2009, 09:29)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.32726 2009-12-20 07:29:56.000000000 +0000
+++ /tmp/wklog.47.new.32726 2009-12-20 07:29:56.000000000 +0000
@@ -56,7 +56,7 @@
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
- 00000082 | 00 | 0 - ANNOTATE_RBR_EVENT [51]
+ 00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
------------------------------------------------------------
-=-=(View All Progress Notes, 26 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 40
ESTIMATE.......: 15 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
-=-=(Alexi - Sun, 20 Dec 2009, 09:29)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.32726 2009-12-20 07:29:56.000000000 +0000
+++ /tmp/wklog.47.new.32726 2009-12-20 07:29:56.000000000 +0000
@@ -56,7 +56,7 @@
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
- 00000082 | 00 | 0 - ANNOTATE_RBR_EVENT [51]
+ 00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
------------------------------------------------------------
-=-=(View All Progress Notes, 26 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Knielsen): Store in binlog text of statements that caused RBR events (47)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Store in binlog text of statements that caused RBR events
CREATION DATE..: Sat, 15 Aug 2009, 23:48
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Knielsen, Serg
CATEGORY.......: Server-Sprint
TASK ID........: 47 (http://askmonty.org/worklog/?tid=47)
VERSION........: Server-9.x
STATUS.........: In-Progress
PRIORITY.......: 60
WORKED HOURS...: 40
ESTIMATE.......: 15 (hours remain)
ORIG. ESTIMATE.: 35
PROGRESS NOTES:
-=-=(Knielsen - Tue, 06 Apr 2010, 15:25)=-=-
Status updated.
--- /tmp/wklog.47.old.12734 2010-04-06 15:25:54.000000000 +0000
+++ /tmp/wklog.47.new.12734 2010-04-06 15:25:54.000000000 +0000
@@ -1 +1 @@
-Code-Review
+In-Progress
-=-=(Knielsen - Mon, 29 Mar 2010, 10:59)=-=-
Status updated.
--- /tmp/wklog.47.old.27790 2010-03-29 10:59:53.000000000 +0000
+++ /tmp/wklog.47.new.27790 2010-03-29 10:59:53.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Code-Review
-=-=(Alexi - Thu, 18 Feb 2010, 19:29)=-=-
Worked 20 hours (alexi)
Worked 20 hours and estimate 15 hours remain (original estimate unchanged).
-=-=(Serg - Fri, 05 Feb 2010, 14:04)=-=-
Observers changed: Knielsen,Serg
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Category updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Server-RawIdeaBin
+Server-Sprint
-=-=(Guest - Fri, 05 Feb 2010, 13:40)=-=-
Status updated.
--- /tmp/wklog.47.old.9197 2010-02-05 13:40:36.000000000 +0200
+++ /tmp/wklog.47.new.9197 2010-02-05 13:40:36.000000000 +0200
@@ -1 +1 @@
-Un-Assigned
+In-Progress
-=-=(Alexi - Thu, 04 Feb 2010, 09:54)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.16174 2010-02-04 09:54:13.000000000 +0200
+++ /tmp/wklog.47.new.16174 2010-02-04 09:54:13.000000000 +0200
@@ -171,35 +171,20 @@
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When requesting an event, the slave should inform the master whether
-it should send Annotate_rows events or not. To that end we add a new
-BINLOG_SEND_ANNOTATE_ROWS_EVENT flag used when requesting an event:
+If the replicate-annotate-rows-events option is not set on a slave, there
+is no need for master to send Annotate_rows events to this slave. The slave
+(or mysqlbinlog in remote case), before requesting binlog dump via the
+COM_BINLOG_DUMP command, informs the master whether it should send these
+events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
+command:
+
+ case COM_BINLOG_DUMP_OPTIONS_EXT:
+ thd->binlog_dump_flags_ext= packet[0];
+ my_ok(thd);
+ break;
- #define BINLOG_DUMP_NON_BLOCK 1
- #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2
-
- pthread_handler_t handle_slave_io(void *arg)
- { ...
- request_dump(mysql, ...);
- ...
- }
-
- int request_dump(MYSQL* mysql, ...)
- { ...
- if (opt_log_slave_updates &&
- mi->io_thd->variables.binlog_annotate_rows_events)
- binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
- ...
- int2store(buf + 4, binlog_flags);
- ...
- simple_command(mysql, COM_BINLOG_DUMP, buf, ...);
- ...
- }
-
-NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
-simple_command() function, should also use this flag if it wants (in case
-of the --print-annotate-rows-events option set) to recieve Annotate_rows
-events.
+Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
+conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,10 +323,4 @@
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
-Also we should notice the introduction of the BINLOG_SEND_ANNOTATE_ROWS_EVENT
-flag taking into account that MySQL/Sun may also introduce a flag with the
-same value to be used in the request_dump-mysql_binlog_send interface.
-But this is mainly the question of merging: if a conflict concerning this
-flag occur, we may simply change the BINLOG_SEND_ANNOTATE_ROWS_EVENT value
-(this does not require additional changes in the code).
-=-=(Alexi - Sun, 20 Dec 2009, 16:00)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.19667 2009-12-20 14:00:56.000000000 +0000
+++ /tmp/wklog.47.new.19667 2009-12-20 14:00:56.000000000 +0000
@@ -196,6 +196,11 @@
...
}
+NOTE. mysqlbinlog, when remotely requesting BINLOG_DUMP by calling the
+simple_command() function, should also use this flag if it wants (in case
+of the --print-annotate-rows-events option set) to recieve Annotate_rows
+events.
+
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -212,8 +217,7 @@
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
- flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT ||
- thd->server_id == 0 /* slave == mysqlbinlog */ )
+ flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
-=-=(Alexi - Sun, 20 Dec 2009, 13:14)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.11350 2009-12-20 13:14:04.000000000 +0200
+++ /tmp/wklog.47.new.11350 2009-12-20 13:14:04.000000000 +0200
@@ -282,23 +282,18 @@
Annotate_rows_log_event* m_annotate_event;
};
-When the saved Annotate_rows object may be deleted? When all corresponding
-Rows events will be processed, i.e. before processing the first non-Rows
-event (note that Annotate_rows object resides in the binary log *after*
-the (possible) 'BEGIN' Query event which accompanies the rows events; note
-also that this deletion is adjusted with the case when some or all
-corresponding Rows events are filtered out by replicate filter rules):
+The saved Annotate_rows object should be deleted when all corresponding
+Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
- if (rli->get_annotate_event() && !IS_RBR_EVENT_TYPE(ev->get_type_code()))
- rli->free_annotate_event();
-
apply_event_and_update_pos(ev, ...);
- if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
+ if (rli->get_annotate_event() && is_last_rows_event(ev))
+ rli->free_annotate_event();
+ else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
@@ -307,10 +302,21 @@
where
- #define IS_RBR_EVENT_TYPE(type) ( (type) == TABLE_MAP_EVENT || \
- (type) == WRITE_ROWS_EVENT || \
+ bool is_last_rows_event(Log_event* ev)
+ {
+ Log_event_type type= ev->get_type_code();
+ if (IS_ROWS_EVENT_TYPE(type))
+ {
+ Rows_log_event* rows= (Rows_log_event*)ev;
+ return rows->get_flags(Rows_log_event::STMT_END_F);
+ }
+
+ return 0;
+ }
+
+ #define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
- (type) == DELETE_ROWS_EVENT )
+ (type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
-=-=(Alexi - Sun, 20 Dec 2009, 09:29)=-=-
Low Level Design modified.
--- /tmp/wklog.47.old.32726 2009-12-20 07:29:56.000000000 +0000
+++ /tmp/wklog.47.new.32726 2009-12-20 07:29:56.000000000 +0000
@@ -56,7 +56,7 @@
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
- 00000082 | 00 | 0 - ANNOTATE_RBR_EVENT [51]
+ 00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
------------------------------------------------------------
-=-=(View All Progress Notes, 26 total)=-=-
http://askmonty.org/worklog/index.pl?tid=47&nolimit=1
DESCRIPTION:
Store in binlog (and show in mysqlbinlog output) texts of statements that
caused RBR events
This is needed for (list from Monty):
- Easier to understand why updates happened
- Would make it easier to find out where in application things went
wrong (as you can search for exact strings)
- Allow one to filter things based on comments in the statement.
The cost of this can be that the binlog will be approximately 2x in size
(especially insert of big blob's would be a bit painful), so this should
be an optional feature.
HIGH-LEVEL SPECIFICATION:
Content
~~~~~~~
1. Annotate_rows_log_event
2. Server option: --binlog-annotate-rows-events
3. Server option: --replicate-annotate-rows-events
4. mysqlbinlog option: --print-annotate-rows-events
5. mysqlbinlog output
1. Annotate_rows_log_event [ ANNOTATE_ROWS_EVENT ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Describes the query which caused the corresponding rows events. Has empty
post-header and contains the query text in its data part. Example:
************************
ANNOTATE_ROWS_EVENT
************************
00000220 | B6 A0 2C 4B | time_when = 1261215926
00000224 | 33 | event_type = 51
00000225 | 64 00 00 00 | server_id = 100
00000229 | 36 00 00 00 | event_len = 54
0000022D | 56 02 00 00 | log_pos = 00000256
00000231 | 00 00 | flags = <none>
------------------------
00000233 | 49 4E 53 45 | query = "INSERT INTO t1 VALUES (1), (2), (3)"
00000237 | 52 54 20 49 |
0000023B | 4E 54 4F 20 |
0000023F | 74 31 20 56 |
00000243 | 41 4C 55 45 |
00000247 | 53 20 28 31 |
0000024B | 29 2C 20 28 |
0000024F | 32 29 2C 20 |
00000253 | 28 33 29 |
************************
In binary log, Annotate_rows event follows the (possible) 'BEGIN' Query event
and precedes the first of Table map events which accompany the corresponding
rows events. (See example in the "mysqlbinlog output" section below.)
2. Server option: --binlog-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the master to write Annotate_rows events to the binary log.
* Variable Name: binlog_annotate_rows_events
* Scope: Global & Session
* Access Type: Dynamic
* Data Type: bool
* Default Value: OFF
NOTE. Session values allows to annotate only some selected statements:
...
SET SESSION binlog_annotate_rows_events=ON;
... statements to be annotated ...
SET SESSION binlog_annotate_rows_events=OFF;
... statements not to be annotated ...
3. Server option: --replicate-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tells the slave to reproduce Annotate_rows events recieved from the master
in its own binary log (sensible only in pair with log-slave-updates option).
* Variable Name: replicate_annotate_rows_events
* Scope: Global
* Access Type: Read only
* Data Type: bool
* Default Value: OFF
NOTE. Why do we additionally need this 'replicate' option? Why not to make
the slave to reproduce this events when its binlog-annotate-rows-events
global value is ON? Well, because, for example, we may want to configure
the slave which should reproduce Annotate_rows events but has global
binlog-annotate-rows-events = OFF meaning this to be the default value for
the client threads (see also "How slave treats replicate-annotate-rows-events
option" in LLD part).
4. mysqlbinlog option: --print-annotate-rows-events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this option, mysqlbinlog prints the content of Annotate_rows events (if
the binary log does contain them). Without this option (i.e. by default),
mysqlbinlog skips Annotate_rows events.
5. mysqlbinlog output
~~~~~~~~~~~~~~~~~~~~~
With --print-annotate-rows-events, mysqlbinlog outputs Annotate_rows events
in a form like this:
...
# at 1646
#091219 12:45:26 server id 100 end_log_pos 1714 Query thread_id=1
exec_time=0 error_code=0
SET TIMESTAMP=1261215926/*!*/;
BEGIN
/*!*/;
# at 1714
# at 1812
# at 1853
# at 1894
# at 1938
#091219 12:45:26 server id 100 end_log_pos 1812 Query: `DELETE t1, t2 FROM
t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a`
#091219 12:45:26 server id 100 end_log_pos 1853 Table_map: `test`.`t1`
mapped to number 16
#091219 12:45:26 server id 100 end_log_pos 1894 Table_map: `test`.`t2`
mapped to number 17
#091219 12:45:26 server id 100 end_log_pos 1938 Delete_rows: table id 16
#091219 12:45:26 server id 100 end_log_pos 1982 Delete_rows: table id 17
flags: STMT_END_F
...
LOW-LEVEL DESIGN:
Content
~~~~~~~
1. Annotate_rows event number
2. Outline of Annotate_rows event behavior
3. How Master writes Annotate_rows events to the binary log
4. How slave treats replicate-annotate-rows-events option
5. How slave IO thread requests Annotate_rows events
6. How master executes the request
7. How slave SQL thread processes Annotate_rows events
8. General remarks
1. Annotate_rows event number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid possible event numbers conflict with MySQL/Sun, we leave a gap
between the last MySQL event number and the Annotate_rows event number:
enum Log_event_type
{ ...
INCIDENT_EVENT= 26,
// New MySQL event numbers are to be added here
MYSQL_EVENTS_END,
MARIA_EVENTS_BEGIN= 51,
// New Maria event numbers start from here
ANNOTATE_ROWS_EVENT= 51,
ENUM_END_EVENT
};
together with the corresponding extension of 'post_header_len' array in the
Format description event. (This extension does not affect the compatibility
of the binary log). Here is how Format description event looks like with
this extension:
************************
FORMAT_DESCRIPTION_EVENT
************************
00000004 | A1 A0 2C 4B | time_when = 1261215905
00000008 | 0F | event_type = 15
00000009 | 64 00 00 00 | server_id = 100
0000000D | 7F 00 00 00 | event_len = 127
00000011 | 83 00 00 00 | log_pos = 00000083
00000015 | 01 00 | flags = LOG_EVENT_BINLOG_IN_USE_F
------------------------
00000017 | 04 00 | binlog_ver = 4
00000019 | 35 2E 32 2E | server_ver = 5.2.0-MariaDB-alpha-debug-log
..... ...
0000004B | A1 A0 2C 4B | time_created = 1261215905
0000004F | 13 | common_header_len = 19
------------------------
post_header_len
------------------------
00000050 | 38 | 56 - START_EVENT_V3 [1]
..... ...
00000069 | 02 | 2 - INCIDENT_EVENT [26]
0000006A | 00 | 0 - RESERVED [27]
..... ...
00000081 | 00 | 0 - RESERVED [50]
00000082 | 00 | 0 - ANNOTATE_ROWS_EVENT [51]
************************
2. Outline of Annotate_rows event behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each Annotate_rows_log_event object has two private members describing the
corresponding query:
char *m_query_txt;
uint m_query_len;
When the object is created for writing to a binary log, this query is taken
from 'thd' (for short, below we omit the 'Annotate_rows_log_event::' prefix
as well as other implementation details):
Annotate_rows_log_event(THD *thd)
{
m_query_txt = thd->query();
m_query_len = thd->query_length();
}
When the object is read from a binary log, the query is taken from the buffer
containing the binary log representation of the event (this buffer is allocated
in Log_event object from which all Log events are derived):
Annotate_rows_log_event(char *buf, uint event_len,
Format_description_log_event *desc)
{
m_query_len = event_len - desc->common_header_len;
m_query_txt = buf + desc->common_header_len;
}
The events are written to the binary log by the Log_event::write() member
which calls virtual write_data_header() and write_data_body() members
("data header" and "post header" are synonym in replication terminology).
In our case, data header is empty and data body is just the query:
bool write_data_body(IO_CACHE *file)
{
return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len);
}
Printing the event is just printing the query:
void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
{
my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
}
3. How Master writes Annotate_rows events to the binary log
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The event is written to the binary log just before the group of Table_map
events which precede corresponding Rows events (one query may generate
several Table map events in the binary log, but the corresponding
Annotate_rows event must be written only once before the first Table map
event; hence the boolean variable 'with_annotate' below):
int write_locked_table_maps(THD *thd)
{ ...
bool with_annotate= thd->variables.binlog_annotate_rows_events;
...
for (uint i= 0; i < ... <number of tables> ...; ++i)
{ ...
thd->binlog_write_table_map(table, ..., with_annotate);
with_annotate= 0; // write Annotate_event not more than once
...
}
...
}
int THD::binlog_write_table_map(TABLE *table, ..., bool with_annotate)
{ ...
Table_map_log_event the_event(...);
...
if (with_annotate)
{
Annotate_rows_log_event anno(this);
mysql_bin_log.write(&anno);
}
mysql_bin_log.write(&the_event);
...
}
4. How slave treats replicate-annotate-rows-events option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The replicate-annotate-rows-events option is treated just as the session
value of the binlog_annotate_rows_events variable for the slave IO and
SQL threads. This setting is done during initialization of these threads:
pthread_handler_t handle_slave_io(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_IO);
...
}
pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd= new THD;
...
init_slave_thread(thd, SLAVE_THD_SQL);
...
}
int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{ ...
thd->variables.binlog_annotate_rows_events=
opt_replicate_annotate_rows_events;
...
}
5. How slave IO thread requests Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the replicate-annotate-rows-events option is not set on a slave, there
is no need for master to send Annotate_rows events to this slave. The slave
(or mysqlbinlog in remote case), before requesting binlog dump via the
COM_BINLOG_DUMP command, informs the master whether it should send these
events by executing the newly added COM_BINLOG_DUMP_OPTIONS_EXT server
command:
case COM_BINLOG_DUMP_OPTIONS_EXT:
thd->binlog_dump_flags_ext= packet[0];
my_ok(thd);
break;
Note. We add this new command and don't use COM_BINLOG_DUMP to avoid possible
conflicts with MySQL/Sun.
6. How master executes the request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case COM_BINLOG_DUMP:
{ ...
flags= uint2korr(packet + 4);
...
mysql_binlog_send(thd, ..., flags);
...
}
void mysql_binlog_send(THD* thd, ..., ushort flags)
{ ...
Log_event::read_log_event(&log, packet, ...);
...
if ((*packet)[EVENT_TYPE_OFFSET + 1] != ANNOTATE_ROWS_EVENT ||
flags & BINLOG_SEND_ANNOTATE_ROWS_EVENT)
{
my_net_write(net, packet->ptr(), packet->length());
}
...
}
7. How slave SQL thread processes Annotate_rows events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The slave processes each recieved event by "applying" it, i.e. by
calling the Log_event::apply_event() function which in turn calls
the virtual do_apply_event() member specific for each type of the
event.
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev = next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
int apply_event_and_update_pos(Log_event *ev, ...)
{ ...
ev->apply_event(...);
...
}
int Log_event::apply_event(...)
{
return do_apply_event(...);
}
What does it mean to "apply" an Annotate_rows event? It means to set current
thd query to that of the described by the event, i.e. to the query which
caused the subsequent Rows events (see "How Master writes Annotate_rows
events to the binary log" to follow what happens further when the subsequent
Rows events are applied):
int Annotate_rows_log_event::do_apply_event(...)
{
thd->set_query(m_query_txt, m_query_len);
}
NOTE. I am not sure, but possibly current values of thd->query and
thd->query_length should be saved before calling set_query() and to be
restored on the Annotate_rows_log_event object deletion.
Is it really needed ?
After calling this do_apply_event() function we may not delete the
Annotate_rows_log_event object immediatedly (see exec_relay_log_event()
above) because thd->query now points to the string inside this object.
We may keep the pointer to this object in the Relay_log_info:
class Relay_log_info
{
public:
...
void set_annotate_event(Annotate_rows_log_event*);
Annotate_rows_log_event* get_annotate_event();
void free_annotate_event();
...
private:
Annotate_rows_log_event* m_annotate_event;
};
The saved Annotate_rows object should be deleted when all corresponding
Rows events will be processed:
int exec_relay_log_event(THD* thd, Relay_log_info* rli)
{ ...
Log_event *ev= next_event(rli);
...
apply_event_and_update_pos(ev, ...);
if (rli->get_annotate_event() && is_last_rows_event(ev))
rli->free_annotate_event();
else if (ev->get_type_code() == ANNOTATE_ROWS_EVENT)
rli->set_annotate_event((Annotate_rows_log_event*) ev);
else if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev;
...
}
where
bool is_last_rows_event(Log_event* ev)
{
Log_event_type type= ev->get_type_code();
if (IS_ROWS_EVENT_TYPE(type))
{
Rows_log_event* rows= (Rows_log_event*)ev;
return rows->get_flags(Rows_log_event::STMT_END_F);
}
return 0;
}
#define IS_ROWS_EVENT_TYPE(type) ((type) == WRITE_ROWS_EVENT || \
(type) == UPDATE_ROWS_EVENT || \
(type) == DELETE_ROWS_EVENT)
8. General remarks
~~~~~~~~~~~~~~~~~~
Kristian noticed that introducing new log event type should be coordinated
somehow with MySQL/Sun:
Kristian: The numeric code for this event must be assigned carefully.
It should be coordinated with MySQL/Sun, otherwise we can get into a
situation where MySQL uses the same numeric code for one event that
MariaDB uses for ANNOTATE_ROWS_EVENT, which would make merging the two
impossible.
Alex: I reserved about 20 numbers not to have possible conflicts
with MySQL.
Kristian: Still, I think it would be appropriate to send a polite email
to internals(a)lists.mysql.com about this and suggesting to reserve the
event number.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
Alexi1952 <Alexi1952(a)yandex.ru> writes:
> Hi Sergey,
>
> Send you for review:
>
> 1. WL#47 branch published on:
> https://code.launchpad.net/~alexi1952/maria/maria-5.2-wl47
>
> 2. Diff file attached.
>
> 3. Commit message attached.
Hi Alexi,
Thanks for sending the patch. I did the code review as Sergey is really busy
with preparations for the User's conference.
General comments, most of them with details inline in the patch below:
I started by reading the text in MWL#47. It was _very_ nice to have detailed
description of the approach here, thanks!
The patch also looks very well worked-through.
We should run this through our Buildbot in a MWL#47 feature branch before
pushing to main, as there may be more result file updates needed in special
parts of the test suite (eg --big). I'll help you set it up when you're ready.
It seems your Windows editor (?) has added Windows line ending (CTRL-M)
characters to some of the lines in the patch. You need to fix this and remove
those extra characters.
The new COM_BINLOG_DUMP_OPTIONS_EXT will cause problems the next time MySQL
adds a new command (which will have same numeric value but different
semantics). This needs to be coordinated, which I think means we might as well
use (and coordinate) a new flag for the normal COM_BINLOG_DUMP command.
If the server does not support COM_BINLOG_DUMP_OPTIONS_EXT, this should not be
a fatal error (as it will prevent working against older MariaDB, or
MySQL). This is for both mysqlbinlog and slave thread.
I think a newline in a query will cause mysqlbinlog to output a file that
cannot be correctly read by the mysql command-line client.
I suggest adding a couple more test cases, with multi-session INSERT DELAYED,
different character sets in query, and newline in query (see detailed comments
below).
I am wondering about the --print-annotate-rows-events option for
mysqlbinlog. Maybe we should have it on by default? My reasoning is that there
is little concern about backwards compatibility, as output will only change if
the corresponding option is enabled explicitly in the server (and the extra
output is just a comment anyway). And the user may want to see the annotations
by default. What do you think?
I found it a bit unnatural to have the annotate event be logged inside the
binlog_write_table_map() method, using the extra with_annotate
parameter. Check the suggestions for how to do this differently (below), and
see if it makes sense.
Things that need fixing:
- Windows line ending issue.
- The COM_BINLOG_DUMP_OPTIONS_EXT potential conflict issue
- Extra test cases
- Newline-in-query problem
- Not fail if server does not support annotate events.
- Minor coding style, comment spelling, etc. issues.
- Full Buildbot run before pushing (I'll set it up later).
Also try to see if the other suggestions can be implemented, or if not lets
discuss.
Detailed comments inline with the patch below.
- Kristian.
> === modified file 'client/mysqlbinlog.cc'
> --- client/mysqlbinlog.cc 2010-03-15 11:51:23 +0000
> +++ client/mysqlbinlog.cc 2010-03-24 06:25:13 +0000
> @@ -128,6 +129,69 @@
> OK_STOP
> };
>
> +/**
> + Pointer to the last read Annotate_rows_log_event. Having read an
> + Annotate_rows event, we should not print it immediatedly because all
> + subsequent rbr events can be filtered away, and have to keep it for a while.
> + Also because of that when reading a remote Annotate event we have to keep
> + its binary log representation in a separately allocated buffer.
> +*/
> +static Annotate_rows_log_event *annotate_event= NULL;
> +
> +inline void free_annotate_event()
Do not make this 'inline'.
> +inline void print_annotate_event(PRINT_EVENT_INFO *print_event_info)
> +{
> + if (annotate_event)
> + {
> + annotate_event->print(result_file, print_event_info);
> + delete annotate_event; // the event should be printed not more than once
s/should be printed not more than once/should not be printed more than once/
> @@ -1673,6 +1769,16 @@
> if ((retval= check_master_version()) != OK_CONTINUE)
> DBUG_RETURN(retval);
>
> + buf[0]= 0;
> + if (opt_print_annotate_rows_events)
> + buf[0]|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
> +
> + if (simple_command(mysql, COM_BINLOG_DUMP_OPTIONS_EXT, buf, 1, 0))
> + {
> + error("Got fatal error sending the log dump options command.");
> + DBUG_RETURN(ERROR_STOP);
> + }
What if the server we are trying to dump from does not support the
COM_BINLOG_DUMP_OPTIONS_EXT command? This should not be a fatal error.
At most, it should be an error only if the user actually requested printing of
annotate_rows_events. But I think it should not be an error at all - it seems
more useful to have an option that just prints any annotate events that are
available. Maybe print a warning if the user explicitly requests this option,
no more than that I think.
And I am wondering if the opt_print_annotate_rows_events should not be on by
default in mysqlbinlog. After all, the events will only be there if they were
explicitly enabled in the database, so most likely they will be wanted, or if
not most likely they will not do much harm as they are comments only.
> === modified file 'include/mysql_com.h'
> --- include/mysql_com.h 2010-03-15 11:51:23 +0000
> +++ include/mysql_com.h 2010-03-24 06:25:13 +0000
> @@ -62,6 +62,7 @@
> COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
> COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
> COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON,
> + COM_BINLOG_DUMP_OPTIONS_EXT,
In the MWL#47 text, you explain that
"Note. We add this new command and don't use COM_BINLOG_DUMP to avoid
possible conflicts with MySQL/Sun."
But this does not avoid such conflicts, on the contrary, we will for sure get
serious problems with this the next time upstream MySQL adds _any_ command
here.
One way or the other, when extending the communication between servers and
clients, we need to coordinate with MySQL/Sun/Oracle. And given this, it is
probably better to just use COM_BINLOG_DUMP, do you agree?
(Lars Thalman actually asked if we would be willing to contribute this work
upstream, which suggests that there should be no problem getting such
coordination working).
> === modified file 'mysql-test/extra/rpl_tests/rpl_deadlock.test'
> --- mysql-test/extra/rpl_tests/rpl_deadlock.test 2009-04-03 21:33:13 +0000
> +++ mysql-test/extra/rpl_tests/rpl_deadlock.test 2010-03-24 06:25:13 +0000
> @@ -72,7 +72,7 @@
> --source include/stop_slave.inc
> DELETE FROM t2;
> # Set slave position to the BEGIN log event
> ---replace_result $master_pos_begin MASTER_POS_BEGIN
> +--replace_result $master_pos_begin <master_pos_begin>
Why this change?
> === added file 'mysql-test/extra/rpl_tests/rpl_row_annotate.test'
> --- mysql-test/extra/rpl_tests/rpl_row_annotate.test 1970-01-01 00:00:00 +0000
> +++ mysql-test/extra/rpl_tests/rpl_row_annotate.test 2010-03-24 06:25:13 +0000
> +INSERT DELAYED INTO t2 VALUES (1,1), (2,2), (3,3);
Add to this test to do INSERT DELAYED from two extra connections, one of which
has binlog_annotate_rows_events set and one which does not.
> +INSERT INTO t3 VALUES (1,1), (2,2), (3,3);
> +DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.a=t2.a AND t2.a=t3.a;
> +
> +INSERT INTO xt1 VALUES (1,1), (2,2), (3,3);
> +INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
> +DELETE xt1, t2 FROM xt1 INNER JOIN t2 INNER JOIN t3 WHERE xt1.a=t2.a AND t2.a=t3.a;
> +
> +INSERT INTO xt1 VALUES (1,1), (2,2), (3,3);
> +INSERT INTO xt2 VALUES (1,1), (2,2), (3,3);
> +DELETE xt1, xt2 FROM xt1 INNER JOIN xt2 INNER JOIN t3 WHERE xt1.a=xt2.a AND xt2.a=t3.a;
Also add tests with a query containing linefeed and other special characters
(eg. insert of blob value and varchar with special character set), to test the
annotation of such queries.
> === added file 'mysql-test/include/binlog_start_pos.inc'
> --- mysql-test/include/binlog_start_pos.inc 1970-01-01 00:00:00 +0000
> +++ mysql-test/include/binlog_start_pos.inc 2010-03-24 06:25:13 +0000
> @@ -0,0 +1,5 @@
> +let $binlog_start_pos=240;
> +--disable_query_log
> +SET @binlog_start_pos=240;
> +--enable_query_log
> +
It would be nice with a short comment explaining what this include file does
and the magic value 240.
(I think what you've tried to do is to clean up this stuff a bit so that the
next change of format_description_event will be easier to integrate in the
test suite, which is good! So just requesting a short explanation here).
> === added file 'mysql-test/suite/binlog/r/binlog_row_annotate.result'
> --- mysql-test/suite/binlog/r/binlog_row_annotate.result 1970-01-01 00:00:00 +0000
> +++ mysql-test/suite/binlog/r/binlog_row_annotate.result 2010-03-24 06:25:13 +0000
> +/*!*/;
> +# at #
> +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
> +SET TIMESTAMP=1000000000/*!*/;
> +BEGIN
> +/*!*/;
> +# at #
> +# at #
> +# at #
> +# at #
> +# at #
> +#010909 4:46:40 server id # end_log_pos # Query: `DELETE test1.t1, test2.t2
> +FROM test1.t1 INNER JOIN test2.t2 INNER JOIN test3.t3
> +WHERE test1.t1.a=test2.t2.a AND test2.t2.a=test3.t3.a`
Right, here we see the problem ... this will cause an error if one tries to
apply this mysqlbinlog output to a server.
> === added file 'mysql-test/suite/binlog/t/binlog_row_annotate.test'
> --- mysql-test/suite/binlog/t/binlog_row_annotate.test 1970-01-01 00:00:00 +0000
> +++ mysql-test/suite/binlog/t/binlog_row_annotate.test 2010-03-24 06:25:14 +0000
> +--echo #
> +--echo #####################################################################################
> +--echo # mysqlbinlog --read-from-remote-server --print-annotate-rows-events
> +--echo # Only two Annotates should appear below:
> +--echo # The following Annotates should appear in this output:
These two lines of comment seem to contradict each other? Please fix/clarify.
> === modified file 'sql/handler.cc'
> --- sql/handler.cc 2010-03-15 11:51:23 +0000
> +++ sql/handler.cc 2010-03-24 06:25:16 +0000
> @@ -4594,7 +4594,8 @@
>
> /** @brief
> Write table maps for all (manually or automatically) locked tables
> - to the binary log.
> + to the binary log. Also, if binlog_annotate_rows_events is ON,
You have ^M (chr 13) Windows line endings in this line, and in others. Please
check the patch and remove all Windows line endings introduced.
> @@ -4648,7 +4652,8 @@
> check_table_binlog_row_based(thd, table))
> {
> int const has_trans= table->file->has_transactions();
> - int const error= thd->binlog_write_table_map(table, has_trans);
> + int const error= thd->binlog_write_table_map(table, has_trans,
> + &with_annotate);
I think we can avoid the extra complexity with passing the with_annotate
parameter.
Couldn't we write the annotate_rows_event _after_ the table maps? Then there
could just be a call to mysql_bin_log.write(Annotate_rows_log_event(thd))
after the loop that writes the table maps. (In fact if we moved the
"if (thd->get_binlog_table_maps() == 0)" from write_locked_table_maps() into
the caller binlog_log_row(), the writing of Annotate_rows_log_event could also
be moved there, which seems to me to be the natural place to put it).
Or is there some reason that the annotate event must come before the table
maps? If so, we can still avoid the with_annotate flag, but we need this
before the loop writing the table maps:
if (is_trans)
binlog_start_trans_and_stmt();
mysql_bin_log.write(Annotate_rows_log_event(thd))
> === modified file 'sql/log_event.cc'
> --- sql/log_event.cc 2010-03-15 11:51:23 +0000
> +++ sql/log_event.cc 2010-03-24 06:25:16 +0000
> +Annotate_rows_log_event::Annotate_rows_log_event(const char *buf,
> + uint event_len,
> + const Format_description_log_event *desc)
> + : Log_event(buf, desc),
> + m_save_thd_query_txt(0),
> + m_save_thd_query_len(0)
> +{
> + m_query_len= event_len - desc->common_header_len;
> + m_query_txt= (char*) buf + desc->common_header_len;
Instead of this cast, couldn't we make the m_query_txt member a const char * ?
(from a quick check of the patch, it seems we can).
> +}
> +
> +Annotate_rows_log_event::~Annotate_rows_log_event()
> +{
> +#ifndef MYSQL_CLIENT
> + if (m_save_thd_query_txt)
> + thd->set_query(m_save_thd_query_txt, m_save_thd_query_len);
> +#endif
> +}
I don't like this, it's much too magic that thd->query can change in the
destructor of a completely unrelated object.
I would suggest instead putting in explicit code to restore thd->query in the
places where it needs to be done (you can have a
Annotate_rows_log_event::restore_thd_query() method for that). This makes it
explicit in the code where the restoration happens.
But actually, I am wondering if it would be better not to change thd->query at
all? And instead just pick the query from a saved annotate_rows_log_event when
needed? But I haven't checked the code sufficient to see if this can be done
in a clean way, so think about it, and see if it makes sense.
> +#ifdef MYSQL_CLIENT
> +void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo)
> +{
> + if (!pinfo->short_form)
> + {
> + print_header(&pinfo->head_cache, pinfo, TRUE);
> + my_b_printf(&pinfo->head_cache, "\tQuery: `%s`\n", m_query_txt);
> + }
> +}
> +#endif
I think this will cause problems if the query contains linefeed characters,
right? The mysqlbinlog output will span multiple lines which will not be
marked as comment lines, so trying to apply the output (by piping through
`mysql`) will fail with a syntax error (or worse).
It seems to me we need some kind of quoting here.
Also, I see that mysqlbinlog is careful to make the query string zero
terminated (as required by my_b_printf("%s"), but that's a bit subtle. So
maybe that could also be avoided if some kind of quoting is enabled, or
alternatively add a comment about this zero-termination requirement for
Annotate_rows_log_event::print().
> === modified file 'sql/mysql_priv.h'
> --- sql/mysql_priv.h 2010-03-15 11:51:23 +0000
> +++ sql/mysql_priv.h 2010-03-24 06:25:17 +0000
> @@ -624,7 +624,12 @@
> /* BINLOG_DUMP options */
>
> #define BINLOG_DUMP_NON_BLOCK 1
> -
> +#endif //MYSQL_CLIENT
Make this #endif /* !MYSQL_CLIENT */
(as it is a negative test that this #endif ends)
> +
> +/* Extended BINLOG_DUMP options (passed to COM_BINLOG_DUMP_OPTIONS_EXT) */
> +#define BINLOG_SEND_ANNOTATE_ROWS_EVENT 1
> +
> +#ifndef MYSQL_CLIENT
> /* sql_show.cc:show_log_files() */
> #define SHOW_LOG_STATUS_FREE "FREE"
> #define SHOW_LOG_STATUS_INUSE "IN USE"
> === modified file 'sql/slave.cc'
> --- sql/slave.cc 2010-03-04 08:03:07 +0000
> +++ sql/slave.cc 2010-03-24 06:25:18 +0000
> @@ -1829,6 +1829,36 @@
> }
>
>
> +static int set_master_binlog_dump_options_ext(MYSQL *mysql,
> + bool *suppress_warnings)
> +{
> + uchar buf[1];
> + uchar flags= 0;
> + DBUG_ENTER("set_master_binlog_dump_options_ext");
> +
> + *suppress_warnings= FALSE;
> +
> + if (opt_log_slave_updates && opt_replicate_annotate_rows_events)
> + flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
> +
> + buf[0]= flags;
> +
> + if (simple_command(mysql, COM_BINLOG_DUMP_OPTIONS_EXT, buf, 1, 0))
> + {
> + if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
> + *suppress_warnings= TRUE;
> + else
> + sql_print_error("Error on COM_BINLOG_DUMP_OPTIONS_EXT: %d %s,"
> + " will retry in %d secs",
> + mysql_errno(mysql), mysql_error(mysql),
> + master_connect_retry);
> + DBUG_RETURN(1);
> + }
This will break replication from a master that does not know the
COM_BINLOG_DUMP_OPTIONS_EXT command. We could maybe log a warning in this
case (saying that query annotation is not available from master), but we
should not fail I think.
> +
> + DBUG_RETURN(0);
> +}
> @@ -2234,16 +2264,33 @@
> }
> exec_res= apply_event_and_update_pos(ev, thd, rli);
>
> - /*
> - Format_description_log_event should not be deleted because it will be
> - used to read info about the relay log's format; it will be deleted when
> - the SQL thread does not need it, i.e. when this thread terminates.
> - */
> - if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
> - {
> - DBUG_PRINT("info", ("Deleting the event after it has been executed"));
> - delete ev;
> - }
> + switch (ev->get_type_code()) {
> + case FORMAT_DESCRIPTION_EVENT:
> + // Format_description_log_event should not be deleted because it
> + // will be used to read info about the relay log's format;
> + // it will be deleted when the SQL thread does not need it,
> + // i.e. when this thread terminates.
> + break;
According to coding style, multi-line comments should use C-style /* ... */,
not C++-style //
http://forge.mysql.com/wiki/MySQL_Internals_Coding_Guidelines#Commenting_Co…
(Should be changed here and in several other places where it occurs).
> + case ANNOTATE_ROWS_EVENT:
> + // Annotate_rows event should not be deleted because after it has
> + // been applied, thd->query points to the string inside this event.
> + // The thd->query will be used to generate new Annotate_rows event
> + // during applying the subsequent Rows events.
> + rli->set_annotate_event((Annotate_rows_log_event*) ev);
> + break;
> + case DELETE_ROWS_EVENT:
> + case UPDATE_ROWS_EVENT:
> + case WRITE_ROWS_EVENT:
> + // After the last Rows event has been applied, the saved Annotate_rows
> + // event (if any) is not needed anymore and can be deleted.
> + if (((Rows_log_event*)ev)->get_flags(Rows_log_event::STMT_END_F))
> + rli->free_annotate_event();
This seems a natural place to explicitly restore thd->query rather than inside
the annotate event destructor (if such restoration is really needed).
> + /* fall through */
> + default:
> + DBUG_PRINT("info", ("Deleting the event after it has been executed"));
> + delete ev;
> + break;
> + }
1
0

[Maria-developers] Updated (by Serg): pluggable authentication (101)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: pluggable authentication
CREATION DATE..: Tue, 09 Mar 2010, 14:58
SUPERVISOR.....: Sergei
IMPLEMENTOR....: Sergei
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 101 (http://askmonty.org/worklog/?tid=101)
VERSION........: Server-5.2
STATUS.........: Complete
PRIORITY.......: 90
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Serg - Tue, 06 Apr 2010, 13:18)=-=-
Status updated.
--- /tmp/wklog.101.old.1262 2010-04-06 13:18:00.000000000 +0000
+++ /tmp/wklog.101.new.1262 2010-04-06 13:18:00.000000000 +0000
@@ -1 +1 @@
-Code-Review
+Complete
DESCRIPTION:
push the pluggable authentication feature
https://code.launchpad.net/~maria-captains/maria/5.2-pluggable-auth
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Serg): pluggable authentication (101)
by worklog-noreply@askmonty.org 06 Apr '10
by worklog-noreply@askmonty.org 06 Apr '10
06 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: pluggable authentication
CREATION DATE..: Tue, 09 Mar 2010, 14:58
SUPERVISOR.....: Sergei
IMPLEMENTOR....: Sergei
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 101 (http://askmonty.org/worklog/?tid=101)
VERSION........: Server-5.2
STATUS.........: Complete
PRIORITY.......: 90
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Serg - Tue, 06 Apr 2010, 13:18)=-=-
Status updated.
--- /tmp/wklog.101.old.1262 2010-04-06 13:18:00.000000000 +0000
+++ /tmp/wklog.101.new.1262 2010-04-06 13:18:00.000000000 +0000
@@ -1 +1 @@
-Code-Review
+Complete
DESCRIPTION:
push the pluggable authentication feature
https://code.launchpad.net/~maria-captains/maria/5.2-pluggable-auth
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Rev 2775: keep acl_user->auth_string and acl_user->salt always in sync in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 06 Apr '10
by serg@askmonty.org 06 Apr '10
06 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2775
revision-id: sergii(a)pisem.net-20100406110456-zhkf13tvdcywb9tb
parent: sergii(a)pisem.net-20100406110224-0wtdkmquq8wmdfer
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Tue 2010-04-06 13:04:56 +0200
message:
keep acl_user->auth_string and acl_user->salt always in sync
print authenticated via in show grants
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-04-05 09:50:31 +0000
+++ b/sql/sql_acl.cc 2010-04-06 11:04:56 +0000
@@ -287,9 +287,8 @@ static void init_check_host(void);
static void rebuild_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user,
my_bool exact);
-static bool update_user_table(THD *thd, TABLE *table,
- const char *host, const char *user,
- const char *new_password, uint new_password_len);
+static bool update_user_table(THD *, TABLE *, const char *, const char *,
+ const char *, uint);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
@@ -1161,7 +1160,12 @@ static void acl_update_user(const char *
acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
}
else
- set_user_salt(acl_user, password, password_len);
+ if (password)
+ {
+ acl_user->auth_string.str= strmake_root(&mem, password, password_len);
+ acl_user->auth_string.length= password_len;
+ set_user_salt(acl_user, password, password_len);
+ }
acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
@@ -1611,7 +1615,13 @@ bool change_password(THD *thd, const cha
goto end;
}
/* update loaded acl entry: */
- set_user_salt(acl_user, new_password, new_password_len);
+ if (acl_user->plugin.str == native_password_plugin_name.str ||
+ acl_user->plugin.str == old_password_plugin_name.str)
+ {
+ acl_user->auth_string.str= strmake_root(&mem, new_password, new_password_len);
+ acl_user->auth_string.length= new_password_len;
+ set_user_salt(acl_user, new_password, new_password_len);
+ }
if (update_user_table(thd, table,
acl_user->host.hostname ? acl_user->host.hostname : "",
@@ -4642,16 +4652,27 @@ bool mysql_show_grants(THD *thd,LEX_USER
global.append(lex_user->host.str,lex_user->host.length,
system_charset_info);
global.append ('\'');
- if (acl_user->salt_len)
+ if (acl_user->plugin.str == native_password_plugin_name.str ||
+ acl_user->plugin.str == old_password_plugin_name.str)
{
- char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
- if (acl_user->salt_len == SCRAMBLE_LENGTH)
- make_password_from_salt(passwd_buff, acl_user->salt);
- else
- make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
- global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
- global.append(passwd_buff);
- global.append('\'');
+ if (acl_user->auth_string.length)
+ {
+ DBUG_ASSERT(acl_user->salt_len);
+ global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
+ global.append(acl_user->auth_string.str, acl_user->auth_string.length);
+ global.append('\'');
+ }
+ }
+ else
+ {
+ global.append(STRING_WITH_LEN(" IDENTIFIED VIA "));
+ global.append(acl_user->plugin.str, acl_user->plugin.length);
+ if (acl_user->auth_string.length)
+ {
+ global.append(STRING_WITH_LEN(" USING '"));
+ global.append(acl_user->auth_string.str, acl_user->auth_string.length);
+ global.append('\'');
+ }
}
/* "show grants" SSL related stuff */
if (acl_user->ssl_type == SSL_TYPE_ANY)
1
0

[Maria-developers] Rev 2774: fix a warning in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 06 Apr '10
by serg@askmonty.org 06 Apr '10
06 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2774
revision-id: sergii(a)pisem.net-20100406110224-0wtdkmquq8wmdfer
parent: igor(a)askmonty.org-20100406065639-w39nrood9amqc5zk
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Tue 2010-04-06 13:02:24 +0200
message:
fix a warning
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2010-04-06 02:08:10 +0000
+++ b/mysys/mf_keycache.c 2010-04-06 11:02:24 +0000
@@ -5207,7 +5207,7 @@ int init_partitioned_key_cache(PARTITION
my_free(partition, MYF(0));
partition= 0;
}
- if (i == 0 && cnt < 0 || i > 0)
+ if ((i == 0 && cnt < 0) || i > 0)
{
/*
Here we have two cases:
1
0

[Maria-developers] Rev 2792: MWL#90: Subqueries: Inside-out execution for non-semijoin materialized in file:///home/psergey/dev/maria-5.3-subqueries-r12/
by Sergey Petrunya 06 Apr '10
by Sergey Petrunya 06 Apr '10
06 Apr '10
At file:///home/psergey/dev/maria-5.3-subqueries-r12/
------------------------------------------------------------
revno: 2792
revision-id: psergey(a)askmonty.org-20100406103533-0upq6g7sse9sjstz
parent: psergey(a)askmonty.org-20100406091710-xamea3aolh3rdspu
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r12
timestamp: Tue 2010-04-06 14:35:33 +0400
message:
MWL#90: Subqueries: Inside-out execution for non-semijoin materialized
subqueries that are AND-parts of the WHERE
- Make test results handle same-cost QEP races
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/subselect_mat.result 2010-04-06 10:35:33 +0000
@@ -98,9 +98,9 @@
explain extended
select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1i ref it1i1,it1i3 it1i3 9 materialized subselect.b1 1 100.00 Using index
-2 SUBQUERY t2i range it2i1,it2i3 it2i1 9 NULL 3 100.00 Using where; Using index for group-by
+1 PRIMARY SUBQUERY#2 ALL distinct_key # NULL # 3 100.00 #
+1 PRIMARY t1i ref it1i1,it1i3 # 9 # 1 100.00 #
+2 SUBQUERY t2i range it2i1,it2i3 # 9 # 3 100.00 #
Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where (`test`.`t1i`.`a1` = `materialized subselect`.`b1`)
select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
@@ -122,9 +122,9 @@
explain extended
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.b2 1 100.00 Using index
-2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
+1 PRIMARY SUBQUERY#2 ALL distinct_key # # # 3 100.00 #
+1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
+2 SUBQUERY t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
@@ -134,9 +134,9 @@
explain extended
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.min(b2) 1 100.00 Using index
-2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
+1 PRIMARY SUBQUERY#2 ALL distinct_key # # # 3 100.00 #
+1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
+2 SUBQUERY t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `materialized subselect`.`min(b2)`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
@@ -307,13 +307,13 @@
(a1, a2) in (select c1, c2 from t3i
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
-1 PRIMARY SUBQUERY#3 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
-1 PRIMARY t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.c2 1 100.00 Using where; Using index
-3 SUBQUERY t3i index it3i1,it3i2,it3i3 it3i3 18 NULL 4 100.00 Using index
-3 SUBQUERY SUBQUERY#4 eq_ref distinct_key distinct_key 18 test.t3i.c1,test.t3i.c2 1 100.00
-4 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
-2 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key # # # 5 0.00 #
+1 PRIMARY SUBQUERY#3 eq_ref distinct_key # # # 1 100.00 #
+1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
+3 SUBQUERY t3i index it3i1,it3i2,it3i3 # # # 4 100.00 #
+3 SUBQUERY SUBQUERY#4 eq_ref distinct_key # # # 1 100.00 #
+4 SUBQUERY t2i index it2i2 # # # 5 100.00 #
+2 SUBQUERY t2i index it2i1,it2i3 # # # 5 100.00 #
Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`materialized subselect`.`b2` = `test`.`t3i`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
select * from t1i
@@ -392,23 +392,23 @@
(a1, a2) in (select c1, c2 from t3i
where (c1, c2) in (select b1, b2 from t2i where b2 > '0')));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
-1 PRIMARY SUBQUERY#5 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer
-5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
-5 SUBQUERY SUBQUERY#6 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
-6 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
-4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
-3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
-7 UNION SUBQUERY#8 ALL distinct_key NULL NULL NULL 5 0.00
-7 UNION SUBQUERY#9 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
-7 UNION t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.c2 1 100.00 Using where; Using index
-9 SUBQUERY t3i index it3i1,it3i2,it3i3 it3i3 18 NULL 4 100.00 Using index
-9 SUBQUERY SUBQUERY#10 eq_ref distinct_key distinct_key 18 test.t3i.c1,test.t3i.c2 1 100.00
-10 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
-8 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
-NULL UNION RESULT <union1,7> ALL NULL NULL NULL NULL NULL NULL
+1 PRIMARY SUBQUERY#2 ALL distinct_key # # # 5 0.00 #
+1 PRIMARY SUBQUERY#5 eq_ref distinct_key # # # 1 100.00 #
+1 PRIMARY t1 ALL NULL # # # 3 100.00 #
+5 SUBQUERY t3 ALL NULL # # # 4 100.00 #
+5 SUBQUERY SUBQUERY#6 eq_ref distinct_key # # # 1 100.00 #
+6 SUBQUERY t2i index it2i2 # # # 5 100.00 #
+2 SUBQUERY t2 ALL NULL # # # 5 100.00 #
+4 SUBQUERY t3 ALL NULL # # # 4 100.00 #
+3 SUBQUERY t3 ALL NULL # # # 4 100.00 #
+7 UNION SUBQUERY#8 ALL distinct_key # # # 5 0.00 #
+7 UNION SUBQUERY#9 eq_ref distinct_key # # # 1 100.00 #
+7 UNION t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
+9 SUBQUERY t3i index it3i1,it3i2,it3i3 # # # 4 100.00 #
+9 SUBQUERY SUBQUERY#10 eq_ref distinct_key # # # 1 100.00 #
+10 SUBQUERY t2i index it2i2 # # # 5 100.00 #
+8 SUBQUERY t2i index it2i1,it2i3 # # # 5 100.00 #
+NULL UNION RESULT <union1,7> ALL NULL # # # NULL NULL #
Warnings:
Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>
(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`materialized subselect`.`b2` = `test`.`t3i`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i
` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))
(select * from t1
=== modified file 'mysql-test/t/subselect_mat.test'
--- a/mysql-test/t/subselect_mat.test 2010-04-05 20:16:45 +0000
+++ b/mysql-test/t/subselect_mat.test 2010-04-06 10:35:33 +0000
@@ -75,18 +75,21 @@
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
-explain extended
-select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
-select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
-
-explain extended
-select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
-select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
-
-explain extended
-select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
-select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
-
+--replace_column 6 # 8 # 11 #
+explain extended
+select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
+select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
+
+explain extended
+select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
+select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
+
+--replace_column 6 # 7 # 8 # 11 #
+explain extended
+select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
+select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
+
+--replace_column 6 # 7 # 8 # 11 #
explain extended
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
@@ -174,6 +177,7 @@
(a1, a2) in (select c1, c2 from t3
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
+--replace_column 6 # 7 # 8 # 11 #
explain extended
select * from t1i
where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
@@ -215,6 +219,7 @@
# multiple levels of nesting subqueries, unions
+--replace_column 6 # 7 # 8 # 11 #
explain extended
(select * from t1
where (a1, a2) in (select b1, b2 from t2
1
0

[Maria-developers] Rev 2791: MWL#90: Subqueries: Inside-out execution for non-semijoin materialized in file:///home/psergey/dev/maria-5.3-subqueries-r12/
by Sergey Petrunya 06 Apr '10
by Sergey Petrunya 06 Apr '10
06 Apr '10
At file:///home/psergey/dev/maria-5.3-subqueries-r12/
------------------------------------------------------------
revno: 2791
revision-id: psergey(a)askmonty.org-20100406091710-xamea3aolh3rdspu
parent: psergey(a)askmonty.org-20100406083401-36tcbqvit0wtilcx
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r12
timestamp: Tue 2010-04-06 13:17:10 +0400
message:
MWL#90: Subqueries: Inside-out execution for non-semijoin materialized
subqueries that are AND-parts of the WHERE
- Update test results
=== modified file 'mysql-test/r/metadata.result'
--- a/mysql-test/r/metadata.result 2008-10-10 11:44:10 +0000
+++ b/mysql-test/r/metadata.result 2010-04-06 09:17:10 +0000
@@ -55,7 +55,7 @@
2 female no
select t1.id from t1 union select t2.id from t2;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def id id 1 4 1 Y 32768 0 63
+def id id 1 4 1 Y 49152 0 63
id
1
2
@@ -66,7 +66,7 @@
set @arg00=1 ;
select @arg00 FROM t1 where a=1 union distinct select 1 FROM t1 where a=1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg00 @arg00 8 20 1 Y 32768 0 63
+def @arg00 @arg00 8 20 1 Y 49152 0 63
@arg00
1
select * from (select @arg00) aaa;
@@ -76,7 +76,7 @@
1
select 1 union select 1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def 1 1 8 20 1 N 32769 0 63
+def 1 1 8 20 1 N 49153 0 63
1
1
select * from (select 1 union select 1) aaa;
=== modified file 'mysql-test/suite/pbxt/r/metadata.result'
--- a/mysql-test/suite/pbxt/r/metadata.result 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/r/metadata.result 2010-04-06 09:17:10 +0000
@@ -55,7 +55,7 @@
2 female no
select t1.id from t1 union select t2.id from t2;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def id id 1 4 1 Y 32768 0 63
+def id id 1 4 1 Y 49152 0 63
id
1
2
@@ -66,7 +66,7 @@
set @arg00=1 ;
select @arg00 FROM t1 where a=1 union distinct select 1 FROM t1 where a=1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg00 @arg00 8 20 1 Y 32768 0 63
+def @arg00 @arg00 8 20 1 Y 49152 0 63
@arg00
1
select * from (select @arg00) aaa;
@@ -76,7 +76,7 @@
1
select 1 union select 1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def 1 1 8 20 1 N 32769 0 63
+def 1 1 8 20 1 N 49153 0 63
1
1
select * from (select 1 union select 1) aaa;
1
0

[Maria-developers] Rev 2790: MWL#90: Subqueries: Inside-out execution for non-semijoin materialized in file:///home/psergey/dev/maria-5.3-subqueries-r12/
by Sergey Petrunya 06 Apr '10
by Sergey Petrunya 06 Apr '10
06 Apr '10
At file:///home/psergey/dev/maria-5.3-subqueries-r12/
------------------------------------------------------------
revno: 2790
revision-id: psergey(a)askmonty.org-20100406083401-36tcbqvit0wtilcx
parent: psergey(a)askmonty.org-20100406081058-ihhw7esolj0mzc9a
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r12
timestamp: Tue 2010-04-06 12:34:01 +0400
message:
MWL#90: Subqueries: Inside-out execution for non-semijoin materialized
subqueries that are AND-parts of the WHERE
- Update test results (checked, we get 0 because the subquery is actually
evaluated by the EXPLAIN).
=== modified file 'mysql-test/r/myisam_mrr.result'
--- a/mysql-test/r/myisam_mrr.result 2010-03-11 21:43:31 +0000
+++ b/mysql-test/r/myisam_mrr.result 2010-04-06 08:34:01 +0000
@@ -347,7 +347,7 @@
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 ALL int_key int_key 5 3 33.33 Using index condition; Using filesort
+2 SUBQUERY t2 ALL int_key int_key 5 0 0.00 Using index condition; Using filesort
Warnings:
Note 1003 select min(`test`.`t1`.`pk`) AS `MIN(t1.pk)` from `test`.`t1` where 0
DROP TABLE t1, t2;
1
0

[Maria-developers] Rev 2789: MWL#90: Subqueries: Inside-out execution for in file:///home/psergey/dev/maria-5.3-subqueries-r12/
by Sergey Petrunya 06 Apr '10
by Sergey Petrunya 06 Apr '10
06 Apr '10
At file:///home/psergey/dev/maria-5.3-subqueries-r12/
------------------------------------------------------------
revno: 2789
revision-id: psergey(a)askmonty.org-20100406081058-ihhw7esolj0mzc9a
parent: psergey(a)askmonty.org-20100405201645-kuavh2rxc9whflc0
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r12
timestamp: Tue 2010-04-06 12:10:58 +0400
message:
MWL#90: Subqueries: Inside-out execution for
non-semijoin materialized subqueries that are AND-parts of the WHERE
- Update test results.
=== modified file 'mysql-test/r/group_min_max.result'
--- a/mysql-test/r/group_min_max.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/group_min_max.result 2010-04-06 08:10:58 +0000
@@ -2255,7 +2255,7 @@
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY SUBQUERY#2 ALL NULL NULL NULL NULL 8
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 8
1 PRIMARY t1_outer ref a a 5 materialized subselect.max(b) 2 Using index
2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
=== modified file 'mysql-test/r/having.result'
--- a/mysql-test/r/having.result 2010-04-05 20:16:45 +0000
+++ b/mysql-test/r/having.result 2010-04-06 08:10:58 +0000
@@ -249,11 +249,11 @@
group by t2.col1, t2.col2 having t2.col1 <= 10);
col1
10
-10
-10
20
30
10
+10
+10
select t1.col1 from t1
where t1.col2 in
(select t2.col2 from t2
@@ -262,11 +262,11 @@
(select min(t3.col1) from t3));
col1
10
-10
-10
20
30
10
+10
+10
select t1.col1 from t1
where t1.col2 in
(select t2.col2 from t2
=== modified file 'mysql-test/r/view.result'
--- a/mysql-test/r/view.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/r/view.result 2010-04-06 08:10:58 +0000
@@ -303,7 +303,7 @@
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
+2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using filesort
drop view v1;
drop table t1;
create table t1 (a int);
=== modified file 'mysql-test/suite/pbxt/r/group_min_max.result'
--- a/mysql-test/suite/pbxt/r/group_min_max.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/suite/pbxt/r/group_min_max.result 2010-04-06 08:10:58 +0000
@@ -2256,7 +2256,8 @@
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 15
+1 PRIMARY t1_outer ref a a 5 materialized subselect.max(b) 1 Using index
2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
=== modified file 'mysql-test/suite/pbxt/r/partition_hash.result'
--- a/mysql-test/suite/pbxt/r/partition_hash.result 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/r/partition_hash.result 2010-04-06 08:10:58 +0000
@@ -57,25 +57,25 @@
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
explain partitions select * from t1 where a is null or (a >= 5 and a <= 7);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p2,p3 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0,p2,p3 ALL NULL NULL NULL NULL 7 Using where
explain partitions select * from t1 where a is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1 where a is not null;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
explain partitions select * from t1 where a >= 1 and a < 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 5 Using where
explain partitions select * from t1 where a >= 3 and a <= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a > 2 and a < 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 3 and a <= 6;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a > 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
=== modified file 'mysql-test/suite/pbxt/r/partition_pruning.result'
--- a/mysql-test/suite/pbxt/r/partition_pruning.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/suite/pbxt/r/partition_pruning.result 2010-04-06 08:10:58 +0000
@@ -14,7 +14,7 @@
1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a=2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a=1 or a=2;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where
@@ -31,7 +31,7 @@
1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t2 where a=1 and b=1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 2 Using where
create table t3 (
a int
)
@@ -42,16 +42,16 @@
insert into t3 values (5),(15);
explain partitions select * from t3 where a=11;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 p1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t3 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t3 where a=10;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 p1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t3 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t3 where a=20;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t3 where a=30;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 0 Using where
create table t4 (a int not null, b int not null) partition by LIST (a+b) (
partition p0 values in (12),
partition p1 values in (14)
@@ -59,11 +59,11 @@
insert into t4 values (10,2), (10,4);
explain partitions select * from t4 where (a=10 and b=1) or (a=10 and b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t4 p0 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t4 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t4
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t4 p0 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t4 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t4 where (a=10 and b=2) or (a=10 and b=3)
or (a=10 and b = 4);
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -89,25 +89,25 @@
explain partitions select * from t5
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t5 where (a=10 and b=2) or (a=10 and b=3)
or (a=10 and b = 4);
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t5 where (c=1 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p1_p1sp0 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p1_p1sp0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t5 where (c=2 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
(c=2 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
(b=2 and c=2 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 3 Using where
create table t6 (a int not null) partition by LIST(a) (
partition p1 values in (1),
partition p3 values in (3),
@@ -121,34 +121,34 @@
1 SIMPLE t6 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a <= 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t6 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 9;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a >= 9;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p9 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t6 p9 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a > 0 and a < 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t6 p1,p3 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 5 and a < 12;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p7,p9 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 p7,p9 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a > 3 and a < 8 ;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p5,p7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p5,p7 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a >= 0 and a <= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t6 p1,p3,p5 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t6 where a >= 5 and a <= 12;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p5,p7,p9 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p5,p7,p9 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a >= 3 and a <= 8;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 3 and a < 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 0 Using where
drop table t6;
create table t6 (a int unsigned not null) partition by LIST(a) (
partition p1 values in (1),
@@ -163,34 +163,34 @@
1 SIMPLE t6 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a <= 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t6 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 9;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a >= 9;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p9 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t6 p9 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a > 0 and a < 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t6 p1,p3 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 5 and a < 12;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p7,p9 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 p7,p9 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t6 where a > 3 and a < 8 ;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p5,p7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p5,p7 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a >= 0 and a <= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t6 p1,p3,p5 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t6 where a >= 5 and a <= 12;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p5,p7,p9 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p5,p7,p9 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a >= 3 and a <= 8;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 3 and a < 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 0 Using where
create table t7 (a int not null) partition by RANGE(a) (
partition p10 values less than (10),
partition p30 values less than (30),
@@ -207,25 +207,25 @@
1 SIMPLE t7 p10 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a <= 10;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 p10,p30 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t7 p10,p30 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t7 where a = 10;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t7 where a < 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t7 p10,p30,p50,p70,p90 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t7 where a = 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a > 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a >= 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a > 11 and a < 29;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 2 Using where
drop table t7;
create table t7 (a int unsigned not null) partition by RANGE(a) (
partition p10 values less than (10),
@@ -243,25 +243,25 @@
1 SIMPLE t7 p10 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a <= 10;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 p10,p30 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t7 p10,p30 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t7 where a = 10;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t7 where a < 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t7 p10,p30,p50,p70,p90 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t7 where a = 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a > 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a >= 90;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t7 where a > 11 and a < 29;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 2 Using where
create table t8 (a date not null) partition by RANGE(YEAR(a)) (
partition p0 values less than (1980),
partition p1 values less than (1990),
@@ -270,7 +270,7 @@
insert into t8 values ('1985-05-05'),('1995-05-05');
explain partitions select * from t8 where a < '1980-02-02';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t8 p0,p1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t8 p0,p1 ALL NULL NULL NULL NULL 2 Using where
create table t9 (a date not null) partition by RANGE(TO_DAYS(a)) (
partition p0 values less than (732299), -- 2004-12-19
partition p1 values less than (732468), -- 2005-06-06
@@ -295,13 +295,13 @@
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a1 > 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a1 >= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a1 < 3 and a1 > 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where
drop table t1;
create table t3 (a int, b int)
partition by list(a) subpartition by hash(b) subpartitions 4 (
@@ -325,7 +325,7 @@
insert into t1 values (1),(2);
explain partitions select * from t1 where a is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a is not null;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
@@ -342,20 +342,20 @@
explain partitions
select * from t1 X, t1 Y where X.a = Y.a and (X.a=1 or X.a=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE X p1,p2 ALL a NULL NULL NULL 4 Using where
+1 SIMPLE X p1,p2 ALL a NULL NULL NULL 2 Using where
1 SIMPLE Y p1,p2 ref a a 4 test.X.a 1
drop table t1;
create table t1 (a int) partition by hash(a) partitions 20;
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a > 1 and a < 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a >= 1 and a < 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 1 and a <= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a >= 1 and a <= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2,p3 ALL NULL NULL NULL NULL 3 Using where
@@ -371,10 +371,10 @@
insert into t1 values (1,1),(2,2),(3,3);
explain partitions select * from t1 where b > 1 and b < 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0_p0sp2,p1_p1sp2,p2_p2sp2,p3_p3sp2 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p0_p0sp2,p1_p1sp2,p2_p2sp2,p3_p3sp2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where b > 1 and b < 3 and (a =1 or a =2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1_p1sp2,p2_p2sp2 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p1_p1sp2,p2_p2sp2 ALL NULL NULL NULL NULL 2 Using where
drop table t1;
create table t1 (a int) partition by list(a) (
partition p0 values in (1,2),
@@ -445,22 +445,22 @@
1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 1010
explain partitions select * from t2 where a < 801 and a > 200;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p1,p2,p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p1,p2,p3,p4 ALL NULL NULL NULL NULL 800 Using where
explain partitions select * from t2 where a < 801 and a > 800;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 200 Using where
explain partitions select * from t2 where a > 600;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where a > 600 and b = 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where a > 600 and b = 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where a > 600 and b = 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where b = 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 1010 Using where
@@ -515,19 +515,19 @@
1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 910
explain partitions select * from t2 where a = 101;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 110 Using where
explain partitions select * from t2 where a = 550;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 200 Using where
explain partitions select * from t2 where a = 833;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 200 Using where
explain partitions select * from t2 where (a = 100 OR a = 900);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0,p4 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p0,p4 ALL NULL NULL NULL NULL 310 Using where
explain partitions select * from t2 where (a > 100 AND a < 600);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 510 Using where
analyze table t2;
Table Op Msg_type Msg_text
test.t2 analyze status OK
@@ -692,7 +692,7 @@
NULL
explain partitions select * from t1 where f_int1 is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part4_part4sp0 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 part4_part4sp0 ALL NULL NULL NULL NULL 2 Using where
drop table t1;
create table t1 (a int not null, b int not null)
partition by list(a)
@@ -721,10 +721,10 @@
(2,1),(2,2),(2,3),(2,4), (NULL,1);
explain partitions select * from t1 where a IS NULL AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where (a IS NULL or a < 1) AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where (a IS NULL or a < 2) AND (b=1 OR b=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0_p0sp0,p0_p0sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 5 Using where
@@ -753,7 +753,7 @@
1
explain partitions select count(*) from t1 where s1 < 0 or s1 is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p3 ALL NULL NULL NULL NULL 2 Using where
drop table t1;
create table t1 (a char(32) primary key)
partition by key()
@@ -812,24 +812,24 @@
insert into t1 values (18446744073709551614-1);
explain partitions select * from t1 where a < 10;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1
where a >= 18446744073709551000-1 and a <= 18446744073709551000+1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1
where a between 18446744073709551001 and 18446744073709551002;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551000;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551613;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551614;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where
drop table t1;
create table t1 (a int)
partition by range(a) (
@@ -853,34 +853,34 @@
1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a=0xFE;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t2 where a=0xFE;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 0xFE AND a <= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t2 where a > 0xFE AND a <= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t1 where a >= 0xFE AND a <= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t2 where a >= 0xFE AND a <= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a < 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t2 where a < 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a <= 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t2 where a <= 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 4 Using where
drop table t1;
drop table t2;
create table t1(a bigint unsigned not null) partition by range(a+0) (
@@ -898,7 +898,7 @@
explain partitions select * from t1 where
a > 0xFFFFFFFFFFFFFFEC and a < 0xFFFFFFFFFFFFFFEE;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where
explain partitions select * from t1 where a>=0 and a <= 0xFFFFFFFFFFFFFFFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2,p3,p4 ALL NULL NULL NULL NULL 8 Using where
=== modified file 'mysql-test/suite/pbxt/r/partition_range.result'
--- a/mysql-test/suite/pbxt/r/partition_range.result 2009-10-16 12:45:42 +0000
+++ b/mysql-test/suite/pbxt/r/partition_range.result 2010-04-06 08:10:58 +0000
@@ -21,19 +21,19 @@
a
explain partitions select * from t1 where a is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 pnull ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a >= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a < 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 pnull ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a <= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull,p0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 pnull,p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where
drop table t1;
create table t1 (a int unsigned, b int unsigned)
partition by range (a)
@@ -63,19 +63,19 @@
a b
explain partitions select * from t1 where a is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a >= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a < 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a <= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1,p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1,p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a > 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where
drop table t1;
CREATE TABLE t1 (
a int not null,
=== modified file 'mysql-test/suite/pbxt/r/subselect.result'
--- a/mysql-test/suite/pbxt/r/subselect.result 2010-03-20 12:08:44 +0000
+++ b/mysql-test/suite/pbxt/r/subselect.result 2010-04-06 08:10:58 +0000
@@ -3420,18 +3420,20 @@
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
+AAA 8
BBB 4
CCC 7
-AAA 8
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 9
+1 PRIMARY t1 ref a a 8 materialized subselect.a 1 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2773)
by Igor Babaev 06 Apr '10
by Igor Babaev 06 Apr '10
06 Apr '10
#At lp:maria/5.2 based on revid:sergii@pisem.net-20100405095031-bgjy005pcftkp6g1
2773 Igor Babaev 2010-04-05 [merge]
Merge of the code for partitioned key cache (mwl#85) into 5.2.
added:
mysql-test/r/select_pkeycache.result
mysql-test/t/select_pkeycache-master.opt
mysql-test/t/select_pkeycache.test
modified:
include/keycache.h
mysql-test/r/information_schema.result
mysql-test/r/information_schema_all_engines.result
mysql-test/r/key_cache.result
mysql-test/suite/funcs_1/r/is_columns_is.result
mysql-test/suite/funcs_1/r/is_tables_is.result
mysql-test/suite/pbxt/r/mysqlshow.result
mysql-test/t/key_cache.test
mysys/mf_keycache.c
sql/handler.cc
sql/handler.h
sql/mysqld.cc
sql/set_var.cc
sql/set_var.h
sql/sql_show.cc
sql/sql_test.cc
sql/table.h
storage/myisam/mi_check.c
storage/myisam/mi_close.c
storage/myisam/mi_delete_all.c
storage/myisam/mi_extra.c
storage/myisam/mi_keycache.c
storage/myisam/mi_locking.c
storage/myisam/mi_page.c
storage/myisam/mi_panic.c
storage/myisam/mi_preload.c
storage/myisam/mi_test1.c
storage/myisam/mi_test2.c
storage/myisam/mi_test3.c
storage/myisam/myisam_ftdump.c
storage/myisam/myisamchk.c
storage/myisam/myisamdef.h
storage/myisam/myisamlog.c
=== modified file 'include/keycache.h'
--- a/include/keycache.h 2009-12-03 11:19:05 +0000
+++ b/include/keycache.h 2010-04-06 02:08:10 +0000
@@ -19,96 +19,156 @@
#define _keycache_h
C_MODE_START
-/* declare structures that is used by st_key_cache */
-struct st_block_link;
-typedef struct st_block_link BLOCK_LINK;
-struct st_keycache_page;
-typedef struct st_keycache_page KEYCACHE_PAGE;
-struct st_hash_link;
-typedef struct st_hash_link HASH_LINK;
-/* info about requests in a waiting queue */
-typedef struct st_keycache_wqueue
+/*
+ Currently the default key cache is created as non-partitioned at
+ the start of the server unless the server is started with the parameter
+ --key-cache-partitions that is greater than 0
+*/
+
+#define DEFAULT_KEY_CACHE_PARTITIONS 0
+
+/*
+ MAX_KEY_CACHE_PARTITIONS cannot be greater than
+ sizeof(MYISAM_SHARE::dirty_part_map)
+ Currently sizeof(MYISAM_SHARE::dirty_part_map)=sizeof(ulonglong)
+*/
+
+#define MAX_KEY_CACHE_PARTITIONS 64
+
+/* The structure to get statistical data about a key cache */
+
+typedef struct st_key_cache_statistics
{
- struct st_my_thread_var *last_thread; /* circular list of waiting threads */
-} KEYCACHE_WQUEUE;
+ ulonglong mem_size; /* memory for cache buffers/auxiliary structures */
+ ulonglong block_size; /* size of the each buffers in the key cache */
+ ulonglong blocks_used; /* maximum number of used blocks/buffers */
+ ulonglong blocks_unused; /* number of currently unused blocks */
+ ulonglong blocks_changed; /* number of currently dirty blocks */
+ ulonglong read_requests; /* number of read requests (read hits) */
+ ulonglong reads; /* number of actual reads from files into buffers */
+ ulonglong write_requests; /* number of write requests (write hits) */
+ ulonglong writes; /* number of actual writes from buffers into files */
+} KEY_CACHE_STATISTICS;
+
+#define NUM_LONG_KEY_CACHE_STAT_VARIABLES 3
-#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
+/* The type of a key cache object */
+typedef enum key_cache_type
+{
+ SIMPLE_KEY_CACHE,
+ PARTITIONED_KEY_CACHE
+} KEY_CACHE_TYPE;
+
+
+typedef
+ int (*INIT_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ int (*RESIZE_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ void (*CHANGE_KEY_CACHE_PARAM)
+ (void *keycache_cb,
+ uint division_limit, uint age_threshold);
+typedef
+ uchar* (*KEY_CACHE_READ)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int return_buffer);
+typedef
+ int (*KEY_CACHE_INSERT)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length);
+typedef
+ int (*KEY_CACHE_WRITE)
+ (void *keycache_cb,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int force_write);
+typedef
+ int (*FLUSH_KEY_BLOCKS)
+ (void *keycache_cb,
+ int file, void *file_extra,
+ enum flush_type type);
+typedef
+ int (*RESET_KEY_CACHE_COUNTERS)
+ (const char *name, void *keycache_cb);
+typedef
+ void (*END_KEY_CACHE)
+ (void *keycache_cb, my_bool cleanup);
+typedef
+ void (*GET_KEY_CACHE_STATISTICS)
+ (void *keycache_cb, uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats);
+typedef
+ ulonglong (*GET_KEY_CACHE_STAT_VALUE)
+ (void *keycache_cb, uint var_no);
/*
- The key cache structure
- It also contains read-only statistics parameters.
+ An object of the type KEY_CACHE_FUNCS contains pointers to all functions
+ from the key cache interface.
+ Currently a key cache can be of two types: simple and partitioned.
+ For each of them its own static structure of the type KEY_CACHE_FUNCS is
+ defined . The structures contain the pointers to the implementations of
+ the interface functions used by simple key caches and partitioned key
+ caches respectively. Pointers to these structures are assigned to key cache
+ objects at the time of their creation.
*/
+typedef struct st_key_cache_funcs
+{
+ INIT_KEY_CACHE init;
+ RESIZE_KEY_CACHE resize;
+ CHANGE_KEY_CACHE_PARAM change_param;
+ KEY_CACHE_READ read;
+ KEY_CACHE_INSERT insert;
+ KEY_CACHE_WRITE write;
+ FLUSH_KEY_BLOCKS flush;
+ RESET_KEY_CACHE_COUNTERS reset_counters;
+ END_KEY_CACHE end;
+ GET_KEY_CACHE_STATISTICS get_stats;
+ GET_KEY_CACHE_STAT_VALUE get_stat_val;
+} KEY_CACHE_FUNCS;
+
+
typedef struct st_key_cache
{
- my_bool key_cache_inited;
- my_bool in_resize; /* true during resize operation */
- my_bool resize_in_flush; /* true during flush of resize operation */
+ KEY_CACHE_TYPE key_cache_type; /* type of the key cache used for debugging */
+ void *keycache_cb; /* control block of the used key cache */
+ KEY_CACHE_FUNCS *interface_funcs; /* interface functions of the key cache */
+ ulonglong param_buff_size; /* size the memory allocated for the cache */
+ ulong param_block_size; /* size of the blocks in the key cache */
+ ulong param_division_limit; /* min. percentage of warm blocks */
+ ulong param_age_threshold; /* determines when hot block is downgraded */
+ ulong param_partitions; /* number of the key cache partitions */
+ my_bool key_cache_inited; /* <=> key cache has been created */
my_bool can_be_used; /* usage of cache for read/write is allowed */
- size_t key_cache_mem_size; /* specified size of the cache memory */
- uint key_cache_block_size; /* size of the page buffer of a cache block */
- ulong min_warm_blocks; /* min number of warm blocks; */
- ulong age_threshold; /* age threshold for hot blocks */
- ulonglong keycache_time; /* total number of block link operations */
- uint hash_entries; /* max number of entries in the hash table */
- int hash_links; /* max number of hash links */
- int hash_links_used; /* number of hash links currently used */
- int disk_blocks; /* max number of blocks in the cache */
- ulong blocks_used; /* maximum number of concurrently used blocks */
- ulong blocks_unused; /* number of currently unused blocks */
- ulong blocks_changed; /* number of currently dirty blocks */
- ulong warm_blocks; /* number of blocks in warm sub-chain */
- ulong cnt_for_resize_op; /* counter to block resize operation */
- long blocks_available; /* number of blocks available in the LRU chain */
- HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
- HASH_LINK *hash_link_root; /* memory for hash table links */
- HASH_LINK *free_hash_list; /* list of free hash links */
- BLOCK_LINK *free_block_list; /* list of free blocks */
- BLOCK_LINK *block_root; /* memory for block links */
- uchar HUGE_PTR *block_mem; /* memory for block buffers */
- BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */
- BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */
- pthread_mutex_t cache_lock; /* to lock access to the cache structure */
- KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
- /*
- Waiting for a zero resize count. Using a queue for symmetry though
- only one thread can wait here.
- */
- KEYCACHE_WQUEUE waiting_for_resize_cnt;
- KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */
- KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
- BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/
- BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/
-
- /*
- The following variables are and variables used to hold parameters for
- initializing the key cache.
- */
-
- ulonglong param_buff_size; /* size the memory allocated for the cache */
- ulong param_block_size; /* size of the blocks in the key cache */
- ulong param_division_limit; /* min. percentage of warm blocks */
- ulong param_age_threshold; /* determines when hot block is downgraded */
-
- /* Statistics variables. These are reset in reset_key_cache_counters(). */
- ulong global_blocks_changed; /* number of currently dirty blocks */
+ my_bool in_init; /* Set to 1 in MySQL during init/resize */
+ uint partitions; /* actual number of partitions */
+ size_t key_cache_mem_size; /* specified size of the cache memory */
+ ulong blocks_used; /* maximum number of concurrently used blocks */
+ ulong blocks_unused; /* number of currently unused blocks */
+ ulong global_blocks_changed; /* number of currently dirty blocks */
ulonglong global_cache_w_requests;/* number of write requests (write hits) */
ulonglong global_cache_write; /* number of writes from cache to files */
ulonglong global_cache_r_requests;/* number of read requests (read hits) */
ulonglong global_cache_read; /* number of reads from files to cache */
-
- int blocks; /* max number of blocks in the cache */
- my_bool in_init; /* Set to 1 in MySQL during init/resize */
} KEY_CACHE;
+
/* The default key cache */
extern KEY_CACHE dflt_key_cache_var, *dflt_key_cache;
extern int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
size_t use_mem, uint division_limit,
- uint age_threshold);
+ uint age_threshold, uint partitions);
extern int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
size_t use_mem, uint division_limit,
uint age_threshold);
@@ -122,12 +182,18 @@ extern int key_cache_insert(KEY_CACHE *k
File file, my_off_t filepos, int level,
uchar *buff, uint length);
extern int key_cache_write(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
uchar *buff, uint length,
- uint block_length,int force_write);
+ uint block_length, int force_write);
extern int flush_key_blocks(KEY_CACHE *keycache,
- int file, enum flush_type type);
+ int file, void *file_extra,
+ enum flush_type type);
extern void end_key_cache(KEY_CACHE *keycache, my_bool cleanup);
+extern void get_key_cache_statistics(KEY_CACHE *keycache,
+ uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats);
+extern ulonglong get_key_cache_stat_value(KEY_CACHE *keycache, uint var_no);
/* Functions to handle multiple key caches */
extern my_bool multi_keycache_init(void);
@@ -140,5 +206,11 @@ extern void multi_key_cache_change(KEY_C
KEY_CACHE *new_data);
extern int reset_key_cache_counters(const char *name,
KEY_CACHE *key_cache);
+extern int repartition_key_cache(KEY_CACHE *keycache,
+ uint key_cache_block_size,
+ size_t use_mem,
+ uint division_limit,
+ uint age_threshold,
+ uint partitions);
C_MODE_END
#endif /* _keycache_h */
=== modified file 'mysql-test/r/information_schema.result'
--- a/mysql-test/r/information_schema.result 2010-03-15 11:51:23 +0000
+++ b/mysql-test/r/information_schema.result 2010-03-29 21:16:12 +0000
@@ -69,6 +69,7 @@ INNODB_LOCK_WAITS
INNODB_RSEG
INNODB_TABLE_STATS
INNODB_TRX
+KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
=== modified file 'mysql-test/r/information_schema_all_engines.result'
--- a/mysql-test/r/information_schema_all_engines.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/r/information_schema_all_engines.result 2010-02-16 16:41:11 +0000
@@ -13,6 +13,7 @@ FILES
GLOBAL_STATUS
GLOBAL_VARIABLES
INDEX_STATISTICS
+KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
@@ -76,6 +77,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA
+KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@@ -139,6 +141,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA
+KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@@ -221,6 +224,7 @@ INNODB_LOCK_WAITS information_schema.INN
INNODB_RSEG information_schema.INNODB_RSEG 1
INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1
INNODB_TRX information_schema.INNODB_TRX 1
+KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PBXT_STATISTICS information_schema.PBXT_STATISTICS 1
@@ -259,6 +263,7 @@ Database: information_schema
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -312,6 +317,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -357,5 +363,5 @@ Wildcard: inf_rmation_schema
+--------------------+
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 48
+information_schema 49
mysql 22
=== modified file 'mysql-test/r/key_cache.result'
--- a/mysql-test/r/key_cache.result 2009-03-16 19:54:50 +0000
+++ b/mysql-test/r/key_cache.result 2010-04-01 21:42:40 +0000
@@ -1,5 +1,7 @@
drop table if exists t1, t2, t3;
-SET @save_key_buffer=@@key_buffer_size;
+SET @save_key_buffer_size=@@key_buffer_size;
+SET @save_key_cache_block_size=@@key_cache_block_size;
+SET @save_key_cache_partitions=@@key_cache_partitions;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@key_buffer_size @@small.key_buffer_size
2097152 131072
@@ -37,7 +39,7 @@ SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size;
@@medium.key_buffer_size
0
-SET @@global.key_buffer_size=@save_key_buffer;
+SET @@global.key_buffer_size=@save_key_buffer_size;
SELECT @@default.key_buffer_size;
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.key_buffer_size' at line 1
SELECT @@skr.storage_engine="test";
@@ -366,3 +368,432 @@ Variable_name Value
key_cache_block_size 1536
SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_block_size=@save_key_cache_block_size;
+select @@key_buffer_size;
+@@key_buffer_size
+2097152
+select @@key_cache_block_size;
+@@key_cache_block_size
+1024
+select @@key_cache_partitions;
+@@key_cache_partitions
+0
+create table t1 (
+p int not null auto_increment primary key,
+a char(10));
+create table t2 (
+p int not null auto_increment primary key,
+i int, a char(10), key k1(i), key k2(a));
+select @@key_cache_partitions;
+@@key_cache_partitions
+0
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+show status like 'key_%';
+Variable_name Value
+Key_blocks_not_flushed 0
+Key_blocks_unused KEY_BLOCKS_UNUSED
+Key_blocks_used 4
+Key_read_requests 22
+Key_reads 0
+Key_write_requests 26
+Key_writes 6
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t2 where a='zzzz';
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 4 # 0 29 0 32 9
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t1;
+delete from t2;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 4 # 0 29 0 32 9
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+set global key_cache_partitions=2;
+select @@key_cache_partitions;
+@@key_cache_partitions
+2
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 2097152 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+show status like 'key_%';
+Variable_name Value
+Key_blocks_not_flushed 0
+Key_blocks_unused KEY_BLOCKS_UNUSED
+Key_blocks_used 4
+Key_read_requests 22
+Key_reads 0
+Key_write_requests 26
+Key_writes 6
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t1;
+delete from t2;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+set global key_cache_partitions=1;
+select @@key_cache_partitions;
+@@key_cache_partitions
+1
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+show status like 'key_%';
+Variable_name Value
+Key_blocks_not_flushed 0
+Key_blocks_unused KEY_BLOCKS_UNUSED
+Key_blocks_used 4
+Key_read_requests 22
+Key_reads 0
+Key_write_requests 26
+Key_writes 6
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t1;
+delete from t2;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+flush tables;
+flush status;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 4 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 0 0 0 0
+set global key_buffer_size=32*1024;
+select @@key_buffer_size;
+@@key_buffer_size
+32768
+set global key_cache_partitions=2;
+select @@key_cache_partitions;
+@@key_cache_partitions
+2
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 0 0 0 0
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 0 0 0 0
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 6733 # 3684 103
+small NULL NULL 1048576 1024 # # 0 0 # 0 0
+select * from t1 where p between 1010 and 1020 ;
+p a
+select * from t2 where p between 1010 and 1020 ;
+p i a
+1010 2 pppp
+1011 2 yyyy
+1012 3 zzzz
+1013 2 qqqq
+1014 2 pppp
+1015 2 yyyy
+1016 3 zzzz
+1017 2 qqqq
+1018 2 pppp
+1019 2 yyyy
+1020 3 zzzz
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 6750 # 3684 103
+small NULL NULL 1048576 1024 # # 0 0 # 0 0
+flush tables;
+flush status;
+update t1 set a='zzzz' where a='qqqq';
+update t2 set i=1 where i=2;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3076 18 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+set global keycache1.key_buffer_size=256*1024;
+select @@keycache1.key_buffer_size;
+@@keycache1.key_buffer_size
+262144
+set global keycache1.key_cache_partitions=7;
+select @@keycache1.key_cache_partitions;
+@@keycache1.key_cache_partitions
+7
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3076 18 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 0 0 0 0
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 0 # 0 0 0 0 0
+cache index t1 key (`primary`) in keycache1;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+explain select p from t1 where p between 1010 and 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where; Using index
+select p from t1 where p between 1010 and 1020;
+p
+explain select i from t2 where p between 1010 and 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 28 Using where
+select i from t2 where p between 1010 and 1020;
+i
+1
+1
+3
+1
+1
+1
+3
+1
+1
+1
+3
+explain select count(*) from t1, t2 where t1.p = t2.i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index k1 k1 5 NULL 1024 Using index
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.i 1 Using index
+select count(*) from t1, t2 where t1.p = t2.i;
+count(*)
+256
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 14 3 0 0
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 3 # 0 14 3 0 0
+cache index t2 in keycache1;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+update t2 set p=p+3000, i=2 where a='qqqq';
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
+set global keycache2.key_buffer_size=1024*1024;
+cache index t2 in keycache2;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+insert into t2 values (2000, 3, 'yyyy');
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
+select * from information_schema.key_caches where key_cache_name like "key%"
+and partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
+cache index t2 in keycache1;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+update t2 set p=p+5000 where a='zzzz';
+select * from t2 where p between 1010 and 1020;
+p i a
+1010 1 pppp
+1011 1 yyyy
+1014 1 pppp
+1015 1 yyyy
+1018 1 pppp
+1019 1 yyyy
+explain select p from t2 where p between 1010 and 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 7 Using where; Using index
+select p from t2 where p between 1010 and 1020;
+p
+1010
+1011
+1014
+1015
+1018
+1019
+explain select i from t2 where a='yyyy' and i=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref k1,k2 k1 5 const 188 Using where
+select i from t2 where a='yyyy' and i=3;
+i
+3
+explain select a from t2 where a='yyyy' and i=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref k1,k2 k1 5 const 188 Using where
+select a from t2 where a='yyyy' and i=3 ;
+a
+yyyy
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=2*1024;
+insert into t2 values (7000, 3, 'yyyy');
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 262143 8192 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+insert into t2 values (8000, 3, 'yyyy');
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=64*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=2*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=0;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=0;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=128*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+drop table t1,t2;
+set global keycache1.key_buffer_size=0;
+set global keycache2.key_buffer_size=0;
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_partitions=@save_key_cache_partitions;
=== added file 'mysql-test/r/select_pkeycache.result'
--- a/mysql-test/r/select_pkeycache.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/select_pkeycache.result 2010-03-29 21:16:12 +0000
@@ -0,0 +1,4784 @@
+drop table if exists t1,t2,t3,t4,t11;
+drop table if exists t1_1,t1_2,t9_1,t9_2,t1aa,t2aa;
+drop view if exists v1;
+CREATE TABLE t1 (
+Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
+Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
+);
+INSERT INTO t1 VALUES (9410,9412);
+select period from t1;
+period
+9410
+select * from t1;
+Period Varor_period
+9410 9412
+select t1.* from t1;
+Period Varor_period
+9410 9412
+CREATE TABLE t2 (
+auto int not null auto_increment,
+fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL,
+companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+fld3 char(30) DEFAULT '' NOT NULL,
+fld4 char(35) DEFAULT '' NOT NULL,
+fld5 char(35) DEFAULT '' NOT NULL,
+fld6 char(4) DEFAULT '' NOT NULL,
+UNIQUE fld1 (fld1),
+KEY fld3 (fld3),
+PRIMARY KEY (auto)
+);
+select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%";
+fld3
+imaginable
+select fld3 from t2 where fld3 like "%cultivation" ;
+fld3
+cultivation
+select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3,companynr from t2 where companynr = 58 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3 from t2 order by fld3 desc limit 10;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select fld3 from t2 order by fld3 desc limit 5;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+select fld3 from t2 order by fld3 desc limit 5,5;
+fld3
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select t2.fld3 from t2 where fld3 = 'honeysuckle';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'h%le';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_';
+fld3
+select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
+fld3
+explain select t2.fld3 from t2 where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 ignore index (fld3,not_used);
+ERROR 42000: Key 'not_used' doesn't exist in table 't2'
+explain select fld3 from t2 use index (not_used);
+ERROR 42000: Key 'not_used' doesn't exist in table 't2'
+select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+fld3
+honeysuckle
+honoring
+explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index
+select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
+fld1 fld3
+148504 Colombo
+068305 Colombo
+000000 nondecreasing
+select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes';
+fld1 fld3
+232605 appendixes
+1232605 appendixes
+1232606 appendixes
+1232607 appendixes
+1232608 appendixes
+1232609 appendixes
+select fld1 from t2 where fld1=250501 or fld1="250502";
+fld1
+250501
+250502
+explain select fld1 from t2 where fld1=250501 or fld1="250502";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index
+select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
+fld1
+250501
+250502
+250505
+250601
+explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index
+select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
+fld1 fld3
+218401 faithful
+018007 fanatic
+228311 fated
+018017 featherweight
+218022 feed
+088303 feminine
+058004 Fenton
+038017 fetched
+018054 fetters
+208101 fiftieth
+238007 filial
+013606 fingerings
+218008 finishers
+038205 firearm
+188505 fitting
+202301 Fitzpatrick
+238008 fixedly
+012001 flanking
+018103 flint
+018104 flopping
+188007 flurried
+013602 foldout
+226205 foothill
+232102 forgivably
+228306 forthcoming
+186002 freakish
+208113 freest
+231315 freezes
+036002 funereal
+226209 furnishings
+198006 furthermore
+select fld3 from t2 where fld3 like "L%" and fld3 = "ok";
+fld3
+select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly");
+fld3
+Chantilly
+select fld1,fld3 from t2 where fld1 like "25050%";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select fld1,fld3 from t2 where fld1 like "25050_";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select distinct companynr from t2;
+companynr
+00
+37
+36
+50
+58
+29
+40
+53
+65
+41
+34
+68
+select distinct companynr from t2 order by companynr;
+companynr
+00
+29
+34
+36
+37
+40
+41
+50
+53
+58
+65
+68
+select distinct companynr from t2 order by companynr desc;
+companynr
+68
+65
+58
+53
+50
+41
+40
+37
+36
+34
+29
+00
+select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%";
+fld3 period
+obliterates 9410
+offload 9410
+opaquely 9410
+organizer 9410
+overestimating 9410
+overlay 9410
+select distinct fld3 from t2 where companynr = 34 order by fld3;
+fld3
+absentee
+accessed
+ahead
+alphabetic
+Asiaticizations
+attitude
+aye
+bankruptcies
+belays
+Blythe
+bomb
+boulevard
+bulldozes
+cannot
+caressing
+charcoal
+checksumming
+chess
+clubroom
+colorful
+cosy
+creator
+crying
+Darius
+diffusing
+duality
+Eiffel
+Epiphany
+Ernestine
+explorers
+exterminated
+famine
+forked
+Gershwins
+heaving
+Hodges
+Iraqis
+Italianization
+Lagos
+landslide
+libretto
+Majorca
+mastering
+narrowed
+occurred
+offerers
+Palestine
+Peruvianizes
+pharmaceutic
+poisoning
+population
+Pygmalion
+rats
+realest
+recording
+regimented
+retransmitting
+reviver
+rouses
+scars
+sicker
+sleepwalk
+stopped
+sugars
+translatable
+uncles
+unexpected
+uprisings
+versatility
+vest
+select distinct fld3 from t2 limit 10;
+fld3
+abates
+abiding
+Abraham
+abrogating
+absentee
+abut
+accessed
+accruing
+accumulating
+accuracies
+select distinct fld3 from t2 having fld3 like "A%" limit 10;
+fld3
+abates
+abiding
+Abraham
+abrogating
+absentee
+abut
+accessed
+accruing
+accumulating
+accuracies
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%";
+substring(fld3,1,3)
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+Adl
+adm
+Ado
+ads
+adv
+aer
+aff
+afi
+afl
+afo
+agi
+ahe
+aim
+air
+Ald
+alg
+ali
+all
+alp
+alr
+ama
+ame
+amm
+ana
+and
+ane
+Ang
+ani
+Ann
+Ant
+api
+app
+aqu
+Ara
+arc
+Arm
+arr
+Art
+Asi
+ask
+asp
+ass
+ast
+att
+aud
+Aug
+aut
+ave
+avo
+awe
+aye
+Azt
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10;
+a
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10;
+substring(fld3,1,3)
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10;
+a
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+create table t3 (
+period int not null,
+name char(32) not null,
+companynr int not null,
+price double(11,0),
+price2 double(11,0),
+key (period),
+key (name)
+);
+create temporary table tmp engine = myisam select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+alter table t3 add t2nr int not null auto_increment primary key first;
+drop table tmp;
+SET SQL_BIG_TABLES=1;
+select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10;
+namn
+Abraham Abraham
+abrogating abrogating
+admonishing admonishing
+Adolph Adolph
+afield afield
+aging aging
+ammonium ammonium
+analyzable analyzable
+animals animals
+animized animized
+SET SQL_BIG_TABLES=0;
+select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10;
+concat(fld3," ",fld3)
+Abraham Abraham
+abrogating abrogating
+admonishing admonishing
+Adolph Adolph
+afield afield
+aging aging
+ammonium ammonium
+analyzable analyzable
+animals animals
+animized animized
+select distinct fld5 from t2 limit 10;
+fld5
+neat
+Steinberg
+jarring
+tinily
+balled
+persist
+attainments
+fanatic
+measures
+rightfulness
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
+fld3 count(*)
+affixed 1
+and 1
+annoyers 1
+Anthony 1
+assayed 1
+assurers 1
+attendants 1
+bedlam 1
+bedpost 1
+boasted 1
+SET SQL_BIG_TABLES=1;
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
+fld3 count(*)
+affixed 1
+and 1
+annoyers 1
+Anthony 1
+assayed 1
+assurers 1
+attendants 1
+bedlam 1
+bedpost 1
+boasted 1
+SET SQL_BIG_TABLES=0;
+select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10;
+fld3 repeat("a",length(fld3)) count(*)
+circus aaaaaa 1
+cited aaaaa 1
+Colombo aaaaaaa 1
+congresswoman aaaaaaaaaaaaa 1
+contrition aaaaaaaaaa 1
+corny aaaaa 1
+cultivation aaaaaaaaaaa 1
+definiteness aaaaaaaaaaaa 1
+demultiplex aaaaaaaaaaa 1
+disappointing aaaaaaaaaaaaa 1
+select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2;
+companynr rtrim(space(512+companynr))
+37
+78
+101
+154
+311
+447
+512
+select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3;
+fld3
+explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index period period 4 NULL 1
+1 SIMPLE t1 ref period period 4 test.t3.period 4181
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index period period 4 NULL 1
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
+select period from t1;
+period
+9410
+select period from t1 where period=1900;
+period
+select fld3,period from t1,t2 where fld1 = 011401 order by period;
+fld3 period
+breaking 9410
+select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001;
+fld3 period
+breaking 1001
+explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const fld1 fld1 4 const 1
+1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1
+select fld3,period from t2,t1 where companynr*10 = 37*10;
+fld3 period
+breaking 9410
+Romans 9410
+intercepted 9410
+bewilderingly 9410
+astound 9410
+admonishing 9410
+sumac 9410
+flanking 9410
+combed 9410
+subjective 9410
+scatterbrain 9410
+Eulerian 9410
+Kane 9410
+overlay 9410
+perturb 9410
+goblins 9410
+annihilates 9410
+Wotan 9410
+snatching 9410
+concludes 9410
+laterally 9410
+yelped 9410
+grazing 9410
+Baird 9410
+celery 9410
+misunderstander 9410
+handgun 9410
+foldout 9410
+mystic 9410
+succumbed 9410
+Nabisco 9410
+fingerings 9410
+aging 9410
+afield 9410
+ammonium 9410
+boat 9410
+intelligibility 9410
+Augustine 9410
+teethe 9410
+dreaded 9410
+scholastics 9410
+audiology 9410
+wallet 9410
+parters 9410
+eschew 9410
+quitter 9410
+neat 9410
+Steinberg 9410
+jarring 9410
+tinily 9410
+balled 9410
+persist 9410
+attainments 9410
+fanatic 9410
+measures 9410
+rightfulness 9410
+capably 9410
+impulsive 9410
+starlet 9410
+terminators 9410
+untying 9410
+announces 9410
+featherweight 9410
+pessimist 9410
+daughter 9410
+decliner 9410
+lawgiver 9410
+stated 9410
+readable 9410
+attrition 9410
+cascade 9410
+motors 9410
+interrogate 9410
+pests 9410
+stairway 9410
+dopers 9410
+testicle 9410
+Parsifal 9410
+leavings 9410
+postulation 9410
+squeaking 9410
+contrasted 9410
+leftover 9410
+whiteners 9410
+erases 9410
+Punjab 9410
+Merritt 9410
+Quixotism 9410
+sweetish 9410
+dogging 9410
+scornfully 9410
+bellow 9410
+bills 9410
+cupboard 9410
+sureties 9410
+puddings 9410
+fetters 9410
+bivalves 9410
+incurring 9410
+Adolph 9410
+pithed 9410
+Miles 9410
+trimmings 9410
+tragedies 9410
+skulking 9410
+flint 9410
+flopping 9410
+relaxing 9410
+offload 9410
+suites 9410
+lists 9410
+animized 9410
+multilayer 9410
+standardizes 9410
+Judas 9410
+vacuuming 9410
+dentally 9410
+humanness 9410
+inch 9410
+Weissmuller 9410
+irresponsibly 9410
+luckily 9410
+culled 9410
+medical 9410
+bloodbath 9410
+subschema 9410
+animals 9410
+Micronesia 9410
+repetitions 9410
+Antares 9410
+ventilate 9410
+pityingly 9410
+interdependent 9410
+Graves 9410
+neonatal 9410
+chafe 9410
+honoring 9410
+realtor 9410
+elite 9410
+funereal 9410
+abrogating 9410
+sorters 9410
+Conley 9410
+lectured 9410
+Abraham 9410
+Hawaii 9410
+cage 9410
+hushes 9410
+Simla 9410
+reporters 9410
+Dutchman 9410
+descendants 9410
+groupings 9410
+dissociate 9410
+coexist 9410
+Beebe 9410
+Taoism 9410
+Connally 9410
+fetched 9410
+checkpoints 9410
+rusting 9410
+galling 9410
+obliterates 9410
+traitor 9410
+resumes 9410
+analyzable 9410
+terminator 9410
+gritty 9410
+firearm 9410
+minima 9410
+Selfridge 9410
+disable 9410
+witchcraft 9410
+betroth 9410
+Manhattanize 9410
+imprint 9410
+peeked 9410
+swelling 9410
+interrelationships 9410
+riser 9410
+Gandhian 9410
+peacock 9410
+bee 9410
+kanji 9410
+dental 9410
+scarf 9410
+chasm 9410
+insolence 9410
+syndicate 9410
+alike 9410
+imperial 9410
+convulsion 9410
+railway 9410
+validate 9410
+normalizes 9410
+comprehensive 9410
+chewing 9410
+denizen 9410
+schemer 9410
+chronicle 9410
+Kline 9410
+Anatole 9410
+partridges 9410
+brunch 9410
+recruited 9410
+dimensions 9410
+Chicana 9410
+announced 9410
+praised 9410
+employing 9410
+linear 9410
+quagmire 9410
+western 9410
+relishing 9410
+serving 9410
+scheduling 9410
+lore 9410
+eventful 9410
+arteriole 9410
+disentangle 9410
+cured 9410
+Fenton 9410
+avoidable 9410
+drains 9410
+detectably 9410
+husky 9410
+impelling 9410
+undoes 9410
+evened 9410
+squeezes 9410
+destroyer 9410
+rudeness 9410
+beaner 9410
+boorish 9410
+Everhart 9410
+encompass 9410
+mushrooms 9410
+Alison 9410
+externally 9410
+pellagra 9410
+cult 9410
+creek 9410
+Huffman 9410
+Majorca 9410
+governing 9410
+gadfly 9410
+reassigned 9410
+intentness 9410
+craziness 9410
+psychic 9410
+squabbled 9410
+burlesque 9410
+capped 9410
+extracted 9410
+DiMaggio 9410
+exclamation 9410
+subdirectory 9410
+Gothicism 9410
+feminine 9410
+metaphysically 9410
+sanding 9410
+Miltonism 9410
+freakish 9410
+index 9410
+straight 9410
+flurried 9410
+denotative 9410
+coming 9410
+commencements 9410
+gentleman 9410
+gifted 9410
+Shanghais 9410
+sportswriting 9410
+sloping 9410
+navies 9410
+leaflet 9410
+shooter 9410
+Joplin 9410
+babies 9410
+assails 9410
+admiring 9410
+swaying 9410
+Goldstine 9410
+fitting 9410
+Norwalk 9410
+analogy 9410
+deludes 9410
+cokes 9410
+Clayton 9410
+exhausts 9410
+causality 9410
+sating 9410
+icon 9410
+throttles 9410
+communicants 9410
+dehydrate 9410
+priceless 9410
+publicly 9410
+incidentals 9410
+commonplace 9410
+mumbles 9410
+furthermore 9410
+cautioned 9410
+parametrized 9410
+registration 9410
+sadly 9410
+positioning 9410
+babysitting 9410
+eternal 9410
+hoarder 9410
+congregates 9410
+rains 9410
+workers 9410
+sags 9410
+unplug 9410
+garage 9410
+boulder 9410
+specifics 9410
+Teresa 9410
+Winsett 9410
+convenient 9410
+buckboards 9410
+amenities 9410
+resplendent 9410
+sews 9410
+participated 9410
+Simon 9410
+certificates 9410
+Fitzpatrick 9410
+Evanston 9410
+misted 9410
+textures 9410
+save 9410
+count 9410
+rightful 9410
+chaperone 9410
+Lizzy 9410
+clenched 9410
+effortlessly 9410
+accessed 9410
+beaters 9410
+Hornblower 9410
+vests 9410
+indulgences 9410
+infallibly 9410
+unwilling 9410
+excrete 9410
+spools 9410
+crunches 9410
+overestimating 9410
+ineffective 9410
+humiliation 9410
+sophomore 9410
+star 9410
+rifles 9410
+dialysis 9410
+arriving 9410
+indulge 9410
+clockers 9410
+languages 9410
+Antarctica 9410
+percentage 9410
+ceiling 9410
+specification 9410
+regimented 9410
+ciphers 9410
+pictures 9410
+serpents 9410
+allot 9410
+realized 9410
+mayoral 9410
+opaquely 9410
+hostess 9410
+fiftieth 9410
+incorrectly 9410
+decomposition 9410
+stranglings 9410
+mixture 9410
+electroencephalography 9410
+similarities 9410
+charges 9410
+freest 9410
+Greenberg 9410
+tinting 9410
+expelled 9410
+warm 9410
+smoothed 9410
+deductions 9410
+Romano 9410
+bitterroot 9410
+corset 9410
+securing 9410
+environing 9410
+cute 9410
+Crays 9410
+heiress 9410
+inform 9410
+avenge 9410
+universals 9410
+Kinsey 9410
+ravines 9410
+bestseller 9410
+equilibrium 9410
+extents 9410
+relatively 9410
+pressure 9410
+critiques 9410
+befouled 9410
+rightfully 9410
+mechanizing 9410
+Latinizes 9410
+timesharing 9410
+Aden 9410
+embassies 9410
+males 9410
+shapelessly 9410
+mastering 9410
+Newtonian 9410
+finishers 9410
+abates 9410
+teem 9410
+kiting 9410
+stodgy 9410
+feed 9410
+guitars 9410
+airships 9410
+store 9410
+denounces 9410
+Pyle 9410
+Saxony 9410
+serializations 9410
+Peruvian 9410
+taxonomically 9410
+kingdom 9410
+stint 9410
+Sault 9410
+faithful 9410
+Ganymede 9410
+tidiness 9410
+gainful 9410
+contrary 9410
+Tipperary 9410
+tropics 9410
+theorizers 9410
+renew 9410
+already 9410
+terminal 9410
+Hegelian 9410
+hypothesizer 9410
+warningly 9410
+journalizing 9410
+nested 9410
+Lars 9410
+saplings 9410
+foothill 9410
+labeled 9410
+imperiously 9410
+reporters 9410
+furnishings 9410
+precipitable 9410
+discounts 9410
+excises 9410
+Stalin 9410
+despot 9410
+ripeness 9410
+Arabia 9410
+unruly 9410
+mournfulness 9410
+boom 9410
+slaughter 9410
+Sabine 9410
+handy 9410
+rural 9410
+organizer 9410
+shipyard 9410
+civics 9410
+inaccuracy 9410
+rules 9410
+juveniles 9410
+comprised 9410
+investigations 9410
+stabilizes 9410
+seminaries 9410
+Hunter 9410
+sporty 9410
+test 9410
+weasels 9410
+CERN 9410
+tempering 9410
+afore 9410
+Galatean 9410
+techniques 9410
+error 9410
+veranda 9410
+severely 9410
+Cassites 9410
+forthcoming 9410
+guides 9410
+vanish 9410
+lied 9410
+sawtooth 9410
+fated 9410
+gradually 9410
+widens 9410
+preclude 9410
+evenhandedly 9410
+percentage 9410
+disobedience 9410
+humility 9410
+gleaning 9410
+petted 9410
+bloater 9410
+minion 9410
+marginal 9410
+apiary 9410
+measures 9410
+precaution 9410
+repelled 9410
+primary 9410
+coverings 9410
+Artemia 9410
+navigate 9410
+spatial 9410
+Gurkha 9410
+meanwhile 9410
+Melinda 9410
+Butterfield 9410
+Aldrich 9410
+previewing 9410
+glut 9410
+unaffected 9410
+inmate 9410
+mineral 9410
+impending 9410
+meditation 9410
+ideas 9410
+miniaturizes 9410
+lewdly 9410
+title 9410
+youthfulness 9410
+creak 9410
+Chippewa 9410
+clamored 9410
+freezes 9410
+forgivably 9410
+reduce 9410
+McGovern 9410
+Nazis 9410
+epistle 9410
+socializes 9410
+conceptions 9410
+Kevin 9410
+uncovering 9410
+chews 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+raining 9410
+infest 9410
+compartment 9410
+minting 9410
+ducks 9410
+roped 9410
+waltz 9410
+Lillian 9410
+repressions 9410
+chillingly 9410
+noncritical 9410
+lithograph 9410
+spongers 9410
+parenthood 9410
+posed 9410
+instruments 9410
+filial 9410
+fixedly 9410
+relives 9410
+Pandora 9410
+watering 9410
+ungrateful 9410
+secures 9410
+poison 9410
+dusted 9410
+encompasses 9410
+presentation 9410
+Kantian 9410
+select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price;
+fld3 period price price2
+admonishing 1002 28357832 8723648
+analyzable 1002 28357832 8723648
+annihilates 1001 5987435 234724
+Antares 1002 28357832 8723648
+astound 1001 5987435 234724
+audiology 1001 5987435 234724
+Augustine 1002 28357832 8723648
+Baird 1002 28357832 8723648
+bewilderingly 1001 5987435 234724
+breaking 1001 5987435 234724
+Conley 1001 5987435 234724
+dentally 1002 28357832 8723648
+dissociate 1002 28357832 8723648
+elite 1001 5987435 234724
+eschew 1001 5987435 234724
+Eulerian 1001 5987435 234724
+flanking 1001 5987435 234724
+foldout 1002 28357832 8723648
+funereal 1002 28357832 8723648
+galling 1002 28357832 8723648
+Graves 1001 5987435 234724
+grazing 1001 5987435 234724
+groupings 1001 5987435 234724
+handgun 1001 5987435 234724
+humility 1002 28357832 8723648
+impulsive 1002 28357832 8723648
+inch 1001 5987435 234724
+intelligibility 1001 5987435 234724
+jarring 1001 5987435 234724
+lawgiver 1001 5987435 234724
+lectured 1002 28357832 8723648
+Merritt 1002 28357832 8723648
+neonatal 1001 5987435 234724
+offload 1002 28357832 8723648
+parters 1002 28357832 8723648
+pityingly 1002 28357832 8723648
+puddings 1002 28357832 8723648
+Punjab 1001 5987435 234724
+quitter 1002 28357832 8723648
+realtor 1001 5987435 234724
+relaxing 1001 5987435 234724
+repetitions 1001 5987435 234724
+resumes 1001 5987435 234724
+Romans 1002 28357832 8723648
+rusting 1001 5987435 234724
+scholastics 1001 5987435 234724
+skulking 1002 28357832 8723648
+stated 1002 28357832 8723648
+suites 1002 28357832 8723648
+sureties 1001 5987435 234724
+testicle 1002 28357832 8723648
+tinily 1002 28357832 8723648
+tragedies 1001 5987435 234724
+trimmings 1001 5987435 234724
+vacuuming 1001 5987435 234724
+ventilate 1001 5987435 234724
+wallet 1001 5987435 234724
+Weissmuller 1002 28357832 8723648
+Wotan 1002 28357832 8723648
+select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37;
+fld1 fld3 period price price2
+018201 relaxing 1001 5987435 234724
+018601 vacuuming 1001 5987435 234724
+018801 inch 1001 5987435 234724
+018811 repetitions 1001 5987435 234724
+create table t4 (
+companynr tinyint(2) unsigned zerofill NOT NULL default '00',
+companyname char(30) NOT NULL default '',
+PRIMARY KEY (companynr),
+UNIQUE KEY companyname(companyname)
+) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames';
+select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
+companynr companyname
+00 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
+companynr companyname
+00 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select * from t1,t1 t12;
+Period Varor_period Period Varor_period
+9410 9412 9410 9412
+select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505;
+fld1 fld1
+250501 250501
+250502 250501
+250503 250501
+250504 250501
+250505 250501
+250501 250502
+250502 250502
+250503 250502
+250504 250502
+250505 250502
+250501 250503
+250502 250503
+250503 250503
+250504 250503
+250505 250503
+250501 250504
+250502 250504
+250503 250504
+250504 250504
+250505 250504
+250501 250505
+250502 250505
+250503 250505
+250504 250505
+250505 250505
+insert into t2 (fld1, companynr) values (999999,99);
+select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
+companynr companyname
+99 NULL
+select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null;
+count(*)
+1199
+explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists
+select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+companynr companyname
+select count(*) from t2 left join t4 using (companynr) where companynr is not null;
+count(*)
+1200
+explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+delete from t2 where fld1=999999;
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
+companynr companynr
+37 36
+41 40
+explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909);
+period
+9410
+select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6)));
+period
+9410
+select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1;
+fld1
+250501
+250502
+250503
+250505
+select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606);
+fld1
+250502
+250503
+select fld1 from t2 where fld1 between 250502 and 250504;
+fld1
+250502
+250503
+250504
+select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ;
+fld3
+label
+labeled
+labeled
+landslide
+laterally
+leaflet
+lewdly
+Lillian
+luckily
+select count(*) from t1;
+count(*)
+1
+select companynr,count(*),sum(fld1) from t2 group by companynr;
+companynr count(*) sum(fld1)
+00 82 10355753
+29 95 14473298
+34 70 17788966
+36 215 22786296
+37 588 83602098
+40 37 6618386
+41 52 12816335
+50 11 1595438
+53 4 793210
+58 23 2254293
+65 10 2284055
+68 12 3097288
+select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
+companynr count(*)
+68 12
+65 10
+58 23
+53 4
+50 11
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 100.00 Using where
+Warnings:
+Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> ''))
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
+companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
+29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
+34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
+companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
+37 1 1 5987435 5987435 5987435 5987435.0000
+37 2 1 28357832 28357832 28357832 28357832.0000
+37 3 1 39654943 39654943 39654943 39654943.0000
+37 11 1 5987435 5987435 5987435 5987435.0000
+37 12 1 28357832 28357832 28357832 28357832.0000
+37 13 1 39654943 39654943 39654943 39654943.0000
+37 21 1 5987435 5987435 5987435 5987435.0000
+37 22 1 28357832 28357832 28357832 28357832.0000
+37 23 1 39654943 39654943 39654943 39654943.0000
+37 31 1 5987435 5987435 5987435 5987435.0000
+select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
+companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
+37 1 1 5987435 5987435 5987435 5987435.0000
+37 2 1 28357832 28357832 28357832 28357832.0000
+37 3 1 39654943 39654943 39654943 39654943.0000
+37 11 1 5987435 5987435 5987435 5987435.0000
+37 12 1 28357832 28357832 28357832 28357832.0000
+37 13 1 39654943 39654943 39654943 39654943.0000
+37 21 1 5987435 5987435 5987435 5987435.0000
+37 22 1 28357832 28357832 28357832 28357832.0000
+37 23 1 39654943 39654943 39654943 39654943.0000
+37 31 1 5987435 5987435 5987435 5987435.0000
+select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
+companynr count(price) sum(price) min(price) max(price) avg(price)
+37 12543 309394878010 5987435 39654943 24666736.6667
+78 8362 414611089292 726498 98439034 49582766.0000
+101 4181 3489454238 834598 834598 834598.0000
+154 4181 4112197254950 983543950 983543950 983543950.0000
+311 4181 979599938 234298 234298 234298.0000
+447 4181 9929180954 2374834 2374834 2374834.0000
+512 4181 3288532102 786542 786542 786542.0000
+select distinct mod(companynr,10) from t4 group by companynr;
+mod(companynr,10)
+0
+9
+4
+6
+7
+1
+3
+8
+5
+select distinct 1 from t4 group by companynr;
+1
+1
+select count(distinct fld1) from t2;
+count(distinct fld1)
+1199
+select companynr,count(distinct fld1) from t2 group by companynr;
+companynr count(distinct fld1)
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(*) from t2 group by companynr;
+companynr count(*)
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr;
+companynr count(distinct concat(fld1,repeat(65,1000)))
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr;
+companynr count(distinct concat(fld1,repeat(65,200)))
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct floor(fld1/100)) from t2 group by companynr;
+companynr count(distinct floor(fld1/100))
+00 47
+29 35
+34 14
+36 69
+37 108
+40 16
+41 11
+50 9
+53 1
+58 1
+65 1
+68 1
+select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr;
+companynr count(distinct concat(repeat(65,1000),floor(fld1/100)))
+00 47
+29 35
+34 14
+36 69
+37 108
+40 16
+41 11
+50 9
+53 1
+58 1
+65 1
+68 1
+select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10;
+sum(fld1) fld3
+11402 Romans
+select name,count(*) from t3 where name='cloakroom' group by name;
+name count(*)
+cloakroom 4181
+select name,count(*) from t3 where name='cloakroom' and price>10 group by name;
+name count(*)
+cloakroom 4181
+select count(*) from t3 where name='cloakroom' and price2=823742;
+count(*)
+4181
+select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name;
+name count(*)
+cloakroom 4181
+select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name;
+name count(*)
+extramarital 4181
+gazer 4181
+gems 4181
+Iranizes 4181
+spates 4181
+tucked 4181
+violinist 4181
+select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
+fld3 count(*)
+spates 4181
+select companynr|0,companyname from t4 group by 1;
+companynr|0 companyname
+0 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname;
+companynr companyname count(*)
+29 company 1 95
+68 company 10 12
+50 company 11 11
+34 company 2 70
+36 company 3 215
+37 company 4 588
+40 company 5 37
+41 company 6 52
+53 company 7 4
+58 company 8 23
+65 company 9 10
+00 Unknown 82
+select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
+fld1 count(*)
+158402 4181
+select sum(Period)/count(*) from t1;
+sum(Period)/count(*)
+9410.0000
+select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr;
+companynr count sum diff func
+37 12543 309394878010 0.0000 464091
+78 8362 414611089292 0.0000 652236
+101 4181 3489454238 0.0000 422281
+154 4181 4112197254950 0.0000 643874
+311 4181 979599938 0.0000 1300291
+447 4181 9929180954 0.0000 1868907
+512 4181 3288532102 0.0000 2140672
+select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg;
+companynr avg
+154 983543950.0000
+select companynr,count(*) from t2 group by companynr order by 2 desc;
+companynr count(*)
+37 588
+36 215
+29 95
+00 82
+34 70
+41 52
+40 37
+58 23
+68 12
+50 11
+65 10
+53 4
+select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc;
+companynr count(*)
+41 52
+58 23
+68 12
+50 11
+65 10
+53 4
+select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4;
+fld4 fld1 count(price) sum(price) min(price) max(price) avg(price)
+teethe 000001 1 5987435 5987435 5987435 5987435.0000
+dreaded 011401 1 5987435 5987435 5987435 5987435.0000
+scholastics 011402 1 28357832 28357832 28357832 28357832.0000
+audiology 011403 1 39654943 39654943 39654943 39654943.0000
+wallet 011501 1 5987435 5987435 5987435 5987435.0000
+parters 011701 1 5987435 5987435 5987435 5987435.0000
+eschew 011702 1 28357832 28357832 28357832 28357832.0000
+quitter 011703 1 39654943 39654943 39654943 39654943.0000
+neat 012001 1 5987435 5987435 5987435 5987435.0000
+Steinberg 012003 1 39654943 39654943 39654943 39654943.0000
+balled 012301 1 5987435 5987435 5987435 5987435.0000
+persist 012302 1 28357832 28357832 28357832 28357832.0000
+attainments 012303 1 39654943 39654943 39654943 39654943.0000
+capably 012501 1 5987435 5987435 5987435 5987435.0000
+impulsive 012602 1 28357832 28357832 28357832 28357832.0000
+starlet 012603 1 39654943 39654943 39654943 39654943.0000
+featherweight 012701 1 5987435 5987435 5987435 5987435.0000
+pessimist 012702 1 28357832 28357832 28357832 28357832.0000
+daughter 012703 1 39654943 39654943 39654943 39654943.0000
+lawgiver 013601 1 5987435 5987435 5987435 5987435.0000
+stated 013602 1 28357832 28357832 28357832 28357832.0000
+readable 013603 1 39654943 39654943 39654943 39654943.0000
+testicle 013801 1 5987435 5987435 5987435 5987435.0000
+Parsifal 013802 1 28357832 28357832 28357832 28357832.0000
+leavings 013803 1 39654943 39654943 39654943 39654943.0000
+squeaking 013901 1 5987435 5987435 5987435 5987435.0000
+contrasted 016001 1 5987435 5987435 5987435 5987435.0000
+leftover 016201 1 5987435 5987435 5987435 5987435.0000
+whiteners 016202 1 28357832 28357832 28357832 28357832.0000
+erases 016301 1 5987435 5987435 5987435 5987435.0000
+Punjab 016302 1 28357832 28357832 28357832 28357832.0000
+Merritt 016303 1 39654943 39654943 39654943 39654943.0000
+sweetish 018001 1 5987435 5987435 5987435 5987435.0000
+dogging 018002 1 28357832 28357832 28357832 28357832.0000
+scornfully 018003 1 39654943 39654943 39654943 39654943.0000
+fetters 018012 1 28357832 28357832 28357832 28357832.0000
+bivalves 018013 1 39654943 39654943 39654943 39654943.0000
+skulking 018021 1 5987435 5987435 5987435 5987435.0000
+flint 018022 1 28357832 28357832 28357832 28357832.0000
+flopping 018023 1 39654943 39654943 39654943 39654943.0000
+Judas 018032 1 28357832 28357832 28357832 28357832.0000
+vacuuming 018033 1 39654943 39654943 39654943 39654943.0000
+medical 018041 1 5987435 5987435 5987435 5987435.0000
+bloodbath 018042 1 28357832 28357832 28357832 28357832.0000
+subschema 018043 1 39654943 39654943 39654943 39654943.0000
+interdependent 018051 1 5987435 5987435 5987435 5987435.0000
+Graves 018052 1 28357832 28357832 28357832 28357832.0000
+neonatal 018053 1 39654943 39654943 39654943 39654943.0000
+sorters 018061 1 5987435 5987435 5987435 5987435.0000
+epistle 018062 1 28357832 28357832 28357832 28357832.0000
+Conley 018101 1 5987435 5987435 5987435 5987435.0000
+lectured 018102 1 28357832 28357832 28357832 28357832.0000
+Abraham 018103 1 39654943 39654943 39654943 39654943.0000
+cage 018201 1 5987435 5987435 5987435 5987435.0000
+hushes 018202 1 28357832 28357832 28357832 28357832.0000
+Simla 018402 1 28357832 28357832 28357832 28357832.0000
+reporters 018403 1 39654943 39654943 39654943 39654943.0000
+coexist 018601 1 5987435 5987435 5987435 5987435.0000
+Beebe 018602 1 28357832 28357832 28357832 28357832.0000
+Taoism 018603 1 39654943 39654943 39654943 39654943.0000
+Connally 018801 1 5987435 5987435 5987435 5987435.0000
+fetched 018802 1 28357832 28357832 28357832 28357832.0000
+checkpoints 018803 1 39654943 39654943 39654943 39654943.0000
+gritty 018811 1 5987435 5987435 5987435 5987435.0000
+firearm 018812 1 28357832 28357832 28357832 28357832.0000
+minima 019101 1 5987435 5987435 5987435 5987435.0000
+Selfridge 019102 1 28357832 28357832 28357832 28357832.0000
+disable 019103 1 39654943 39654943 39654943 39654943.0000
+witchcraft 019201 1 5987435 5987435 5987435 5987435.0000
+betroth 030501 1 5987435 5987435 5987435 5987435.0000
+Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000
+imprint 030503 1 39654943 39654943 39654943 39654943.0000
+swelling 031901 1 5987435 5987435 5987435 5987435.0000
+interrelationships 036001 1 5987435 5987435 5987435 5987435.0000
+riser 036002 1 28357832 28357832 28357832 28357832.0000
+bee 038001 1 5987435 5987435 5987435 5987435.0000
+kanji 038002 1 28357832 28357832 28357832 28357832.0000
+dental 038003 1 39654943 39654943 39654943 39654943.0000
+railway 038011 1 5987435 5987435 5987435 5987435.0000
+validate 038012 1 28357832 28357832 28357832 28357832.0000
+normalizes 038013 1 39654943 39654943 39654943 39654943.0000
+Kline 038101 1 5987435 5987435 5987435 5987435.0000
+Anatole 038102 1 28357832 28357832 28357832 28357832.0000
+partridges 038103 1 39654943 39654943 39654943 39654943.0000
+recruited 038201 1 5987435 5987435 5987435 5987435.0000
+dimensions 038202 1 28357832 28357832 28357832 28357832.0000
+Chicana 038203 1 39654943 39654943 39654943 39654943.0000
+select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3;
+companynr fld3 sum(price)
+512 boat 786542
+512 capably 786542
+512 cupboard 786542
+512 decliner 786542
+512 descendants 786542
+512 dopers 786542
+512 erases 786542
+512 Micronesia 786542
+512 Miles 786542
+512 skies 786542
+select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr;
+companynr count(*) min(fld3) max(fld3) sum(price) avg(price)
+00 1 Omaha Omaha 5987435 5987435.0000
+36 1 dubbed dubbed 28357832 28357832.0000
+37 83 Abraham Wotan 1908978016 22999735.1325
+50 2 scribbled tapestry 68012775 34006387.5000
+select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1;
+t3.companynr+0 t2nr fld3 sum(price)
+37 1 Omaha 5987435
+37 11401 breaking 5987435
+37 11402 Romans 28357832
+37 11403 intercepted 39654943
+37 11501 bewilderingly 5987435
+37 11701 astound 5987435
+37 11702 admonishing 28357832
+37 11703 sumac 39654943
+37 12001 flanking 5987435
+37 12003 combed 39654943
+37 12301 Eulerian 5987435
+37 12302 dubbed 28357832
+37 12303 Kane 39654943
+37 12501 annihilates 5987435
+37 12602 Wotan 28357832
+37 12603 snatching 39654943
+37 12701 grazing 5987435
+37 12702 Baird 28357832
+37 12703 celery 39654943
+37 13601 handgun 5987435
+37 13602 foldout 28357832
+37 13603 mystic 39654943
+37 13801 intelligibility 5987435
+37 13802 Augustine 28357832
+37 13803 teethe 39654943
+37 13901 scholastics 5987435
+37 16001 audiology 5987435
+37 16201 wallet 5987435
+37 16202 parters 28357832
+37 16301 eschew 5987435
+37 16302 quitter 28357832
+37 16303 neat 39654943
+37 18001 jarring 5987435
+37 18002 tinily 28357832
+37 18003 balled 39654943
+37 18012 impulsive 28357832
+37 18013 starlet 39654943
+37 18021 lawgiver 5987435
+37 18022 stated 28357832
+37 18023 readable 39654943
+37 18032 testicle 28357832
+37 18033 Parsifal 39654943
+37 18041 Punjab 5987435
+37 18042 Merritt 28357832
+37 18043 Quixotism 39654943
+37 18051 sureties 5987435
+37 18052 puddings 28357832
+37 18053 tapestry 39654943
+37 18061 trimmings 5987435
+37 18062 humility 28357832
+37 18101 tragedies 5987435
+37 18102 skulking 28357832
+37 18103 flint 39654943
+37 18201 relaxing 5987435
+37 18202 offload 28357832
+37 18402 suites 28357832
+37 18403 lists 39654943
+37 18601 vacuuming 5987435
+37 18602 dentally 28357832
+37 18603 humanness 39654943
+37 18801 inch 5987435
+37 18802 Weissmuller 28357832
+37 18803 irresponsibly 39654943
+37 18811 repetitions 5987435
+37 18812 Antares 28357832
+37 19101 ventilate 5987435
+37 19102 pityingly 28357832
+37 19103 interdependent 39654943
+37 19201 Graves 5987435
+37 30501 neonatal 5987435
+37 30502 scribbled 28357832
+37 30503 chafe 39654943
+37 31901 realtor 5987435
+37 36001 elite 5987435
+37 36002 funereal 28357832
+37 38001 Conley 5987435
+37 38002 lectured 28357832
+37 38003 Abraham 39654943
+37 38011 groupings 5987435
+37 38012 dissociate 28357832
+37 38013 coexist 39654943
+37 38101 rusting 5987435
+37 38102 galling 28357832
+37 38103 obliterates 39654943
+37 38201 resumes 5987435
+37 38202 analyzable 28357832
+37 38203 terminator 39654943
+select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008;
+sum(price)
+234298
+select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1;
+fld1 sum(price)
+038008 234298
+explain select fld3 from t2 where 1>2 or 2>3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select fld3 from t2 where fld1=fld1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
+companynr fld1
+34 250501
+34 250502
+select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502;
+companynr fld1
+34 250501
+34 250502
+select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000;
+companynr count sum
+00 82 10355753
+29 95 14473298
+34 70 17788966
+37 588 83602098
+41 52 12816335
+select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ;
+companynr
+00
+29
+34
+37
+41
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40;
+companynr companyname count(*)
+68 company 10 12
+50 company 11 11
+40 company 5 37
+41 company 6 52
+53 company 7 4
+58 company 8 23
+65 company 9 10
+select count(*) from t2;
+count(*)
+1199
+select count(*) from t2 where fld1 < 098024;
+count(*)
+387
+select min(fld1) from t2 where fld1>= 098024;
+min(fld1)
+98024
+select max(fld1) from t2 where fld1>= 098024;
+max(fld1)
+1232609
+select count(*) from t3 where price2=76234234;
+count(*)
+4181
+select count(*) from t3 where companynr=512 and price2=76234234;
+count(*)
+4181
+explain select min(fld1),max(fld1),count(*) from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+select min(fld1),max(fld1),count(*) from t2;
+min(fld1) max(fld1) count(*)
+0 1232609 1199
+select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742;
+min(t2nr) max(t2nr)
+2115 2115
+select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78;
+count(*) min(t2nr) max(t2nr)
+4181 4 41804
+select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20;
+t2nr count(*)
+9 1
+19 1
+29 1
+39 1
+49 1
+59 1
+69 1
+79 1
+89 1
+99 1
+109 1
+119 1
+129 1
+139 1
+149 1
+159 1
+169 1
+179 1
+189 1
+199 1
+select max(t2nr) from t3 where price=983543950;
+max(t2nr)
+41807
+select t1.period from t3 = t1 limit 1;
+period
+1001
+select t1.period from t1 as t1 limit 1;
+period
+9410
+select t1.period as "Nuvarande period" from t1 as t1 limit 1;
+Nuvarande period
+9410
+select period as ok_period from t1 limit 1;
+ok_period
+9410
+select period as ok_period from t1 group by ok_period limit 1;
+ok_period
+9410
+select 1+1 as summa from t1 group by summa limit 1;
+summa
+2
+select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1;
+Nuvarande period
+9410
+show tables;
+Tables_in_test
+t1
+t2
+t3
+t4
+show tables from test like "s%";
+Tables_in_test (s%)
+show tables from test like "t?";
+Tables_in_test (t?)
+show full columns from t2;
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(11) NULL NO PRI NULL auto_increment #
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+companynr tinyint(2) unsigned zerofill NULL NO 00 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
+show full columns from t2 from test like 'f%';
+Field Type Collation Null Key Default Extra Privileges Comment
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
+show full columns from t2 from test like 's%';
+Field Type Collation Null Key Default Extra Privileges Comment
+show keys from t2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE
+t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE
+t2 1 fld3 1 fld3 A NULL NULL NULL BTREE
+drop table t4, t3, t2, t1;
+DO 1;
+DO benchmark(100,1+1),1,1;
+do default;
+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 '' at line 1
+do foobar;
+ERROR 42S22: Unknown column 'foobar' in 'field list'
+CREATE TABLE t1 (
+id mediumint(8) unsigned NOT NULL auto_increment,
+pseudo varchar(35) NOT NULL default '',
+PRIMARY KEY (id),
+UNIQUE KEY pseudo (pseudo)
+);
+INSERT INTO t1 (pseudo) VALUES ('test');
+INSERT INTO t1 (pseudo) VALUES ('test1');
+SELECT 1 as rnd1 from t1 where rand() > 2;
+rnd1
+DROP TABLE t1;
+CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL);
+CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35);
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+gvid the_success the_fail the_size the_time
+Warnings:
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+gvid the_success the_fail the_size the_time
+DROP TABLE t1,t2;
+create table t1 ( A_Id bigint(20) NOT NULL default '0', A_UpdateBy char(10) NOT NULL default '', A_UpdateDate bigint(20) NOT NULL default '0', A_UpdateSerial int(11) NOT NULL default '0', other_types bigint(20) NOT NULL default '0', wss_type bigint(20) NOT NULL default '0');
+INSERT INTO t1 VALUES (102935998719055004,'brade',1029359987,2,102935229116544068,102935229216544093);
+select wss_type from t1 where wss_type ='102935229216544106';
+wss_type
+select wss_type from t1 where wss_type ='102935229216544105';
+wss_type
+select wss_type from t1 where wss_type ='102935229216544104';
+wss_type
+select wss_type from t1 where wss_type ='102935229216544093';
+wss_type
+102935229216544093
+select wss_type from t1 where wss_type =102935229216544093;
+wss_type
+102935229216544093
+drop table t1;
+select 1+2,"aaaa",3.13*2.0 into @a,@b,@c;
+select @a;
+@a
+3
+select @b;
+@b
+aaaa
+select @c;
+@c
+6.260
+create table t1 (a int not null auto_increment primary key);
+insert into t1 values ();
+insert into t1 values ();
+insert into t1 values ();
+select * from (t1 as t2 left join t1 as t3 using (a)), t1;
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1, (t1 as t2 left join t1 as t3 using (a));
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) straight_join t1;
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1 straight_join (t1 as t2 left join t1 as t3 using (a));
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 on t1.a>1;
+a a
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 using ( a );
+a
+1
+2
+3
+select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) using ( a );
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) left outer join t1 on t1.a>1;
+a a
+1 2
+1 3
+2 2
+2 3
+3 2
+3 3
+select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+1 NULL
+2 1
+2 2
+2 3
+3 1
+3 2
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) left join t1 using ( a );
+a
+1
+2
+3
+select * from t1 left join (t1 as t2 left join t1 as t3 using (a)) using ( a );
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
+a
+1
+2
+3
+select * from t1 natural left join (t1 as t2 left join t1 as t3 using (a));
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
+a a
+NULL 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1 right join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) right outer join t1 using ( a );
+a
+1
+2
+3
+select * from t1 right outer join (t1 as t2 left join t1 as t3 using (a)) using ( a );
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) natural right join t1;
+a
+1
+2
+3
+select * from t1 natural right join (t1 as t2 left join t1 as t3 using (a));
+a
+1
+2
+3
+select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
+a
+1
+2
+3
+drop table t1;
+CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
+CREATE TABLE t2 ( id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (2517), (2518), (2519), (2520), (2521), (2522);
+select * from t1, t2 WHERE t1.t2_id = t2.id and t1.t2_id > 0 order by t1.id LIMIT 0, 5;
+aa id t2_id id
+2 8299 2517 2517
+3 8301 2518 2518
+4 8302 2519 2519
+5 8303 2520 2520
+6 8304 2521 2521
+drop table t1,t2;
+create table t1 (id1 int NOT NULL);
+create table t2 (id2 int NOT NULL);
+create table t3 (id3 int NOT NULL);
+create table t4 (id4 int NOT NULL, id44 int NOT NULL, KEY (id4));
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t2 values (1);
+insert into t4 values (1,1);
+explain select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3
+left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t4 const id4 NULL NULL NULL 1
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where
+select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3
+left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
+id1 id2 id3 id4 id44
+1 1 NULL NULL NULL
+drop table t1,t2,t3,t4;
+create table t1(s varchar(10) not null);
+create table t2(s varchar(10) not null primary key);
+create table t3(s varchar(10) not null primary key);
+insert into t1 values ('one\t'), ('two\t');
+insert into t2 values ('one\r'), ('two\t');
+insert into t3 values ('one '), ('two\t');
+select * from t1 where s = 'one';
+s
+select * from t2 where s = 'one';
+s
+select * from t3 where s = 'one';
+s
+one
+select * from t1,t2 where t1.s = t2.s;
+s s
+two two
+select * from t2,t3 where t2.s = t3.s;
+s s
+two two
+drop table t1, t2, t3;
+create table t1 (a integer, b integer, index(a), index(b));
+create table t2 (c integer, d integer, index(c), index(d));
+insert into t1 values (1,2), (2,2), (3,2), (4,2);
+insert into t2 values (1,3), (2,3), (3,4), (4,4);
+explain select * from t1 left join t2 on a=c where d in (4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer
+select * from t1 left join t2 on a=c where d in (4);
+a b c d
+3 2 3 4
+4 2 4 4
+explain select * from t1 left join t2 on a=c where d = 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer
+select * from t1 left join t2 on a=c where d = 4;
+a b c d
+3 2 3 4
+4 2 4 4
+drop table t1, t2;
+CREATE TABLE t1 (
+i int(11) NOT NULL default '0',
+c char(10) NOT NULL default '',
+PRIMARY KEY (i),
+UNIQUE KEY c (c)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,'a');
+INSERT INTO t1 VALUES (2,'b');
+INSERT INTO t1 VALUES (3,'c');
+EXPLAIN SELECT i FROM t1 WHERE i=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+DROP TABLE t1;
+CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
+CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
+INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
+INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+DROP TABLE t1, t2;
+CREATE TABLE t1 ( city char(30) );
+INSERT INTO t1 VALUES ('London');
+INSERT INTO t1 VALUES ('Paris');
+SELECT * FROM t1 WHERE city='London';
+city
+London
+SELECT * FROM t1 WHERE city='london';
+city
+London
+EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+SELECT * FROM t1 WHERE city='London' AND city='london';
+city
+London
+EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+city
+London
+DROP TABLE t1;
+create table t1 (a int(11) unsigned, b int(11) unsigned);
+insert into t1 values (1,0), (1,1), (1,2);
+select a-b from t1 order by 1;
+a-b
+0
+1
+18446744073709551615
+select a-b , (a-b < 0) from t1 order by 1;
+a-b (a-b < 0)
+0 0
+1 0
+18446744073709551615 0
+select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
+d (a-b >= 0) b
+1 1 0
+0 1 1
+18446744073709551615 1 2
+select cast((a - b) as unsigned) from t1 order by 1;
+cast((a - b) as unsigned)
+0
+1
+18446744073709551615
+drop table t1;
+create table t1 (a int(11));
+select all all * from t1;
+a
+select distinct distinct * from t1;
+a
+select all distinct * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+select distinct all * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+drop table t1;
+CREATE TABLE t1 (
+kunde_intern_id int(10) unsigned NOT NULL default '0',
+kunde_id int(10) unsigned NOT NULL default '0',
+FK_firma_id int(10) unsigned NOT NULL default '0',
+aktuell enum('Ja','Nein') NOT NULL default 'Ja',
+vorname varchar(128) NOT NULL default '',
+nachname varchar(128) NOT NULL default '',
+geloescht enum('Ja','Nein') NOT NULL default 'Nein',
+firma varchar(128) NOT NULL default ''
+);
+INSERT INTO t1 VALUES
+(3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'),
+(3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX');
+SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1
+WHERE
+(
+(
+( '' != '' AND firma LIKE CONCAT('%', '', '%'))
+OR
+(vorname LIKE CONCAT('%', 'Vorname1', '%') AND
+nachname LIKE CONCAT('%', '1Nachname', '%') AND
+'Vorname1' != '' AND 'xxxx' != '')
+)
+AND
+(
+aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2
+)
+)
+;
+kunde_id FK_firma_id aktuell vorname nachname geloescht
+SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname,
+geloescht FROM t1
+WHERE
+(
+(
+aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2
+)
+AND
+(
+( '' != '' AND firma LIKE CONCAT('%', '', '%') )
+OR
+( vorname LIKE CONCAT('%', 'Vorname1', '%') AND
+nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND
+'xxxx' != '')
+)
+)
+;
+kunde_id FK_firma_id aktuell vorname nachname geloescht
+SELECT COUNT(*) FROM t1 WHERE
+( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1))
+AND FK_firma_id = 2;
+COUNT(*)
+0
+drop table t1;
+CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b));
+INSERT INTO t1 VALUES (0x8000000000000000);
+SELECT b FROM t1 WHERE b=0x8000000000000000;
+b
+9223372036854775808
+DROP TABLE t1;
+CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL);
+CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL);
+INSERT INTO `t2` VALUES (0,'READ');
+CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL);
+INSERT INTO `t3` VALUES (1,'fs');
+select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0);
+id name gid uid ident level
+1 fs NULL NULL 0 READ
+drop table t1,t2,t3;
+CREATE TABLE t1 (
+acct_id int(11) NOT NULL default '0',
+profile_id smallint(6) default NULL,
+UNIQUE KEY t1$acct_id (acct_id),
+KEY t1$profile_id (profile_id)
+);
+INSERT INTO t1 VALUES (132,17),(133,18);
+CREATE TABLE t2 (
+profile_id smallint(6) default NULL,
+queue_id int(11) default NULL,
+seq int(11) default NULL,
+KEY t2$queue_id (queue_id)
+);
+INSERT INTO t2 VALUES (17,31,4),(17,30,3),(17,36,2),(17,37,1);
+CREATE TABLE t3 (
+id int(11) NOT NULL default '0',
+qtype int(11) default NULL,
+seq int(11) default NULL,
+warn_lvl int(11) default NULL,
+crit_lvl int(11) default NULL,
+rr1 tinyint(4) NOT NULL default '0',
+rr2 int(11) default NULL,
+default_queue tinyint(4) NOT NULL default '0',
+KEY t3$qtype (qtype),
+KEY t3$id (id)
+);
+INSERT INTO t3 VALUES (30,1,29,NULL,NULL,0,NULL,0),(31,1,28,NULL,NULL,0,NULL,0),
+(36,1,34,NULL,NULL,0,NULL,0),(37,1,35,NULL,NULL,0,121,0);
+SELECT COUNT(*) FROM t1 a STRAIGHT_JOIN t2 pq STRAIGHT_JOIN t3 q
+WHERE
+(pq.profile_id = a.profile_id) AND (a.acct_id = 132) AND
+(pq.queue_id = q.id) AND (q.rr1 <> 1);
+COUNT(*)
+4
+drop table t1,t2,t3;
+create table t1 (f1 int);
+insert into t1 values (1),(NULL);
+create table t2 (f2 int, f3 int, f4 int);
+create index idx1 on t2 (f4);
+insert into t2 values (1,2,3),(2,4,6);
+select A.f2 from t1 left join t2 A on A.f2 = f1 where A.f3=(select min(f3)
+from t2 C where A.f4 = C.f4) or A.f3 IS NULL;
+f2
+1
+NULL
+drop table t1,t2;
+create table t2 (a tinyint unsigned);
+create index t2i on t2(a);
+insert into t2 values (0), (254), (255);
+explain select * from t2 where a > -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index t2i t2i 2 NULL 3 Using where; Using index
+select * from t2 where a > -1;
+a
+0
+254
+255
+drop table t2;
+CREATE TABLE t1 (a int, b int, c int);
+INSERT INTO t1
+SELECT 50, 3, 3 FROM DUAL
+WHERE NOT EXISTS
+(SELECT * FROM t1 WHERE a = 50 AND b = 3);
+SELECT * FROM t1;
+a b c
+50 3 3
+INSERT INTO t1
+SELECT 50, 3, 3 FROM DUAL
+WHERE NOT EXISTS
+(SELECT * FROM t1 WHERE a = 50 AND b = 3);
+select found_rows();
+found_rows()
+0
+SELECT * FROM t1;
+a b c
+50 3 3
+select count(*) from t1;
+count(*)
+1
+select found_rows();
+found_rows()
+1
+select count(*) from t1 limit 2,3;
+count(*)
+select found_rows();
+found_rows()
+0
+select SQL_CALC_FOUND_ROWS count(*) from t1 limit 2,3;
+count(*)
+select found_rows();
+found_rows()
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT);
+(SELECT a, b AS c FROM t1) ORDER BY c+1;
+a c
+(SELECT a, b AS c FROM t1) ORDER BY b+1;
+a c
+SELECT a, b AS c FROM t1 ORDER BY c+1;
+a c
+SELECT a, b AS c FROM t1 ORDER BY b+1;
+a c
+drop table t1;
+create table t1(f1 int, f2 int);
+create table t2(f3 int);
+select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,1));
+f1
+select f1 from t1,t2 where f1=f2 and (f1,NULL) = ((1,1));
+f1
+select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,NULL));
+f1
+insert into t1 values(1,1),(2,null);
+insert into t2 values(2);
+select * from t1,t2 where f1=f3 and (f1,f2) = (2,null);
+f1 f2 f3
+select * from t1,t2 where f1=f3 and (f1,f2) <=> (2,null);
+f1 f2 f3
+2 NULL 2
+drop table t1,t2;
+create table t1 (f1 int not null auto_increment primary key, f2 varchar(10));
+create table t11 like t1;
+insert into t1 values(1,""),(2,"");
+show table status like 't1%';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 10 Dynamic 2 20 X X X X X X X X latin1_swedish_ci NULL
+t11 MyISAM 10 Dynamic 0 0 X X X X X X X X latin1_swedish_ci NULL
+select 123 as a from t1 where f1 is null;
+a
+drop table t1,t11;
+CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL, UNIQUE idx (a,b) );
+INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4);
+CREATE TABLE t2 ( a INT NOT NULL, b INT NOT NULL, e INT );
+INSERT INTO t2 VALUES ( 1,10,1), (1,10,2), (1,11,1), (1,11,2), (1,2,1), (1,2,2),(1,2,3);
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2 LEFT JOIN
+t1 ON t2.a = t1.a AND t2.b = t1.b GROUP BY a, b, c;
+a b c d
+1 2 1 1
+1 2 2 1
+1 2 3 1
+1 10 2
+1 11 2
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2 LEFT JOIN
+t1 ON t2.a = t1.a AND t2.b = t1.b GROUP BY t1.a, t1.b, c;
+a b c d
+1 10 4
+1 2 1 1
+1 2 2 1
+1 2 3 1
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2 LEFT JOIN
+t1 ON t2.a = t1.a AND t2.b = t1.b GROUP BY t2.a, t2.b, c;
+a b c d
+1 2 1 1
+1 2 2 1
+1 2 3 1
+1 10 2
+1 11 2
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2,t1
+WHERE t2.a = t1.a AND t2.b = t1.b GROUP BY a, b, c;
+a b c d
+1 2 1 1
+1 2 2 1
+1 2 3 1
+DROP TABLE IF EXISTS t1, t2;
+create table t1 (f1 int primary key, f2 int);
+create table t2 (f3 int, f4 int, primary key(f3,f4));
+insert into t1 values (1,1);
+insert into t2 values (1,1),(1,2);
+select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1;
+count(f2) >0
+1
+drop table t1,t2;
+create table t1 (f1 int,f2 int);
+insert into t1 values(1,1);
+create table t2 (f3 int, f4 int, primary key(f3,f4));
+insert into t2 values(1,1);
+select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2));
+f1 f2
+1 1
+drop table t1,t2;
+CREATE TABLE t1(a int, b int, c int, KEY b(b), KEY c(c));
+insert into t1 values (1,0,0),(2,0,0);
+CREATE TABLE t2 (a int, b varchar(2), c varchar(2), PRIMARY KEY(a));
+insert into t2 values (1,'',''), (2,'','');
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a,b), KEY a (a), KEY b (b));
+insert into t3 values (1,1),(1,2);
+explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
+where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
+t2.b like '%%' order by t2.b limit 0,1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref b,c b 5 const 1 Using where; Using temporary; Using filesort
+1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index; Using join buffer
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 (a int, INDEX idx(a));
+INSERT INTO t1 VALUES (2), (3), (1);
+EXPLAIN SELECT * FROM t1 IGNORE INDEX (idx);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+EXPLAIN SELECT * FROM t1 IGNORE INDEX (a);
+ERROR 42000: Key 'a' doesn't exist in table 't1'
+EXPLAIN SELECT * FROM t1 FORCE INDEX (a);
+ERROR 42000: Key 'a' doesn't exist in table 't1'
+DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,1), (2,1), (4,10);
+CREATE TABLE t2 (a int PRIMARY KEY, b int, KEY b (b));
+INSERT INTO t2 VALUES (1,NULL), (2,10);
+ALTER TABLE t1 ENABLE KEYS;
+EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index b b 5 NULL 2 Using index
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+a b a b
+1 NULL 1 1
+1 NULL 2 1
+1 NULL 4 10
+2 10 4 10
+EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index b b 5 NULL 2 Using index
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+a b a b
+1 NULL 1 1
+1 NULL 2 1
+1 NULL 4 10
+2 10 4 10
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1));
+CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2));
+INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941);
+INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941);
+explain select max(key1) from t1 where key1 <= 0.6158;
+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
+explain select max(key2) from t2 where key2 <= 1.6158;
+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
+explain select min(key1) from t1 where key1 >= 0.3762;
+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
+explain select min(key2) from t2 where key2 >= 1.3762;
+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
+explain select max(key1), min(key2) from t1, t2
+where key1 <= 0.6158 and key2 >= 1.3762;
+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
+explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
+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
+explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
+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 max(key1) from t1 where key1 <= 0.6158;
+max(key1)
+0.615800023078918
+select max(key2) from t2 where key2 <= 1.6158;
+max(key2)
+1.61580002307892
+select min(key1) from t1 where key1 >= 0.3762;
+min(key1)
+0.376199990510941
+select min(key2) from t2 where key2 >= 1.3762;
+min(key2)
+1.37619996070862
+select max(key1), min(key2) from t1, t2
+where key1 <= 0.6158 and key2 >= 1.3762;
+max(key1) min(key2)
+0.615800023078918 1.37619996070862
+select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
+max(key1)
+0.615800023078918
+select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
+min(key1)
+0.376199990510941
+DROP TABLE t1,t2;
+CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL);
+INSERT INTO t1 VALUES (10);
+SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1;
+i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01')
+1 1 1 1
+DROP TABLE t1;
+create table t1(a bigint unsigned, b bigint);
+insert into t1 values (0xfffffffffffffffff, 0xfffffffffffffffff),
+(0x10000000000000000, 0x10000000000000000),
+(0x8fffffffffffffff, 0x8fffffffffffffff);
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+Warning 1264 Out of range value for column 'b' at row 1
+Warning 1264 Out of range value for column 'a' at row 2
+Warning 1264 Out of range value for column 'b' at row 2
+Warning 1264 Out of range value for column 'b' at row 3
+select hex(a), hex(b) from t1;
+hex(a) hex(b)
+FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF
+8FFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF
+drop table t1;
+CREATE TABLE t1 (c0 int);
+CREATE TABLE t2 (c0 int);
+INSERT INTO t1 VALUES(@@connect_timeout);
+INSERT INTO t2 VALUES(@@connect_timeout);
+SELECT * FROM t1 JOIN t2 ON t1.c0 = t2.c0 WHERE (t1.c0 <=> @@connect_timeout);
+c0 c0
+X X
+DROP TABLE t1, t2;
+End of 4.1 tests
+CREATE TABLE t1 (
+K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
+K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
+F2I4 int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES
+('W%RT', '0100', 1),
+('W-RT', '0100', 1),
+('WART', '0100', 1),
+('WART', '0200', 1),
+('WERT', '0100', 2),
+('WORT','0200', 2),
+('WT', '0100', 2),
+('W_RT', '0100', 2),
+('WaRT', '0100', 3),
+('WART', '0300', 3),
+('WRT' , '0400', 3),
+('WURM', '0500', 3),
+('W%T', '0600', 4),
+('WA%T', '0700', 4),
+('WA_T', '0800', 4);
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND
+(F2I4 = 2 AND K2C4 = 'WART' OR (F2I4 = 2 OR K4N4 = '0200'));
+K2C4 K4N4 F2I4
+WART 0200 1
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND (K2C4 = 'WART' OR K4N4 = '0200');
+K2C4 K4N4 F2I4
+WART 0100 1
+WART 0200 1
+WART 0300 3
+DROP TABLE t1;
+create table t1 (a int, b int);
+create table t2 like t1;
+select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
+a
+select t1.a from ((t1 inner join t2 on t1.a=t2.a)) where t2.a=1;
+a
+select x.a, y.a, z.a from ( (t1 x inner join t2 y on x.a=y.a) inner join t2 z on y.a=z.a) WHERE x.a=1;
+a a a
+drop table t1,t2;
+create table t1 (s1 varchar(5));
+insert into t1 values ('Wall');
+select min(s1) from t1 group by s1 with rollup;
+min(s1)
+Wall
+Wall
+drop table t1;
+create table t1 (s1 int) engine=myisam;
+insert into t1 values (0);
+select avg(distinct s1) from t1 group by s1 with rollup;
+avg(distinct s1)
+0.0000
+0.0000
+drop table t1;
+create table t1 (s1 int);
+insert into t1 values (null),(1);
+select distinct avg(s1) as x from t1 group by s1 with rollup;
+x
+NULL
+1.0000
+drop table t1;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+INSERT INTO t2 VALUES (2), (4), (6);
+SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+a
+2
+4
+EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer
+DROP TABLE t1,t2;
+select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0;
+x'10' + 0 X'10' + 0 b'10' + 0 B'10' + 0
+16 16 2 2
+create table t1 (f1 varchar(6) default NULL, f2 int(6) primary key not null);
+create table t2 (f3 varchar(5) not null, f4 varchar(5) not null, UNIQUE KEY UKEY (f3,f4));
+insert into t1 values (" 2", 2);
+insert into t2 values (" 2", " one "),(" 2", " two ");
+select * from t1 left join t2 on f1 = f3;
+f1 f2 f3 f4
+ 2 2 2 one
+ 2 2 2 two
+drop table t1,t2;
+create table t1 (empnum smallint, grp int);
+create table t2 (empnum int, name char(5));
+insert into t1 values(1,1);
+insert into t2 values(1,'bob');
+create view v1 as select * from t2 inner join t1 using (empnum);
+select * from v1;
+empnum name grp
+1 bob 1
+drop table t1,t2;
+drop view v1;
+create table t1 (pk int primary key, b int);
+create table t2 (pk int primary key, c int);
+select pk from t1 inner join t2 using (pk);
+pk
+drop table t1,t2;
+create table t1 (s1 int, s2 char(5), s3 decimal(10));
+create view v1 as select s1, s2, 'x' as s3 from t1;
+select * from t1 natural join v1;
+s1 s2 s3
+insert into t1 values (1,'x',5);
+select * from t1 natural join v1;
+s1 s2 s3
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'x'
+drop table t1;
+drop view v1;
+create table t1(a1 int);
+create table t2(a2 int);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create view v2 (c) as select a1 from t1;
+select * from t1 natural left join t2;
+a1 a2
+1 1
+1 2
+2 1
+2 2
+select * from t1 natural right join t2;
+a2 a1
+1 1
+1 2
+2 1
+2 2
+select * from v2 natural left join t2;
+c a2
+1 1
+1 2
+2 1
+2 2
+select * from v2 natural right join t2;
+a2 c
+1 1
+1 2
+2 1
+2 2
+drop table t1, t2;
+drop view v2;
+create table t1 (a int(10), t1_val int(10));
+create table t2 (b int(10), t2_val int(10));
+create table t3 (a int(10), b int(10));
+insert into t1 values (1,1),(2,2);
+insert into t2 values (1,1),(2,2),(3,3);
+insert into t3 values (1,1),(2,1),(3,1),(4,1);
+select * from t1 natural join t2 natural join t3;
+a b t1_val t2_val
+1 1 1 1
+2 1 2 1
+select * from t1 natural join t3 natural join t2;
+b a t1_val t2_val
+1 1 1 1
+1 2 2 1
+drop table t1, t2, t3;
+DO IFNULL(NULL, NULL);
+SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
+CAST(IFNULL(NULL, NULL) AS DECIMAL)
+NULL
+SELECT ABS(IFNULL(NULL, NULL));
+ABS(IFNULL(NULL, NULL))
+NULL
+SELECT IFNULL(NULL, NULL);
+IFNULL(NULL, NULL)
+NULL
+SET @OLD_SQL_MODE12595=@@SQL_MODE, @@SQL_MODE='';
+SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
+Variable_name Value
+sql_mode
+CREATE TABLE BUG_12595(a varchar(100));
+INSERT INTO BUG_12595 VALUES ('hakan%'), ('hakank'), ("ha%an");
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
+a
+hakan%
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
+a
+hakan%
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
+a
+hakan%
+hakank
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '';
+a
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha%%an' ESCAPE '%';
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE '\\';
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
+a
+ha%an
+SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
+SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
+Variable_name Value
+sql_mode NO_BACKSLASH_ESCAPES
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
+a
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
+a
+hakan%
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '\\';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\n%' ESCAPE '\n';
+ERROR HY000: Incorrect arguments to ESCAPE
+SET @@SQL_MODE=@OLD_SQL_MODE12595;
+DROP TABLE BUG_12595;
+create table t1 (a char(1));
+create table t2 (a char(1));
+insert into t1 values ('a'),('b'),('c');
+insert into t2 values ('b'),('c'),('d');
+select a from t1 natural join t2;
+a
+b
+c
+select * from t1 natural join t2 where a = 'b';
+a
+b
+drop table t1, t2;
+CREATE TABLE t1 (`id` TINYINT);
+CREATE TABLE t2 (`id` TINYINT);
+CREATE TABLE t3 (`id` TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t3 VALUES (3);
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.notacolumn=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+drop table t1, t2, t3;
+create table t1 (a int(10),b int(10));
+create table t2 (a int(10),b int(10));
+insert into t1 values (1,10),(2,20),(3,30);
+insert into t2 values (1,10);
+select * from t1 inner join t2 using (A);
+a b b
+1 10 10
+select * from t1 inner join t2 using (a);
+a b b
+1 10 10
+drop table t1, t2;
+create table t1 (a int, c int);
+create table t2 (b int);
+create table t3 (b int, a int);
+create table t4 (c int);
+insert into t1 values (1,1);
+insert into t2 values (1);
+insert into t3 values (1,1);
+insert into t4 values (1);
+select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+a c b b a
+1 1 1 1 1
+select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+ERROR 42S22: Unknown column 't1.a' in 'on clause'
+select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c);
+a c b b a c
+1 1 1 1 1 1
+select * from t1 join t2 join t4 using (c);
+c a b
+1 1 1
+drop table t1, t2, t3, t4;
+create table t1(x int, y int);
+create table t2(x int, y int);
+create table t3(x int, primary key(x));
+insert into t1 values (1, 1), (2, 1), (3, 1), (4, 3), (5, 6), (6, 6);
+insert into t2 values (1, 1), (2, 1), (3, 3), (4, 6), (5, 6);
+insert into t3 values (1), (2), (3), (4), (5);
+select t1.x, t3.x from t1, t2, t3 where t1.x = t2.x and t3.x >= t1.y and t3.x <= t2.y;
+x x
+1 1
+2 1
+3 1
+3 2
+3 3
+4 3
+4 4
+4 5
+drop table t1,t2,t3;
+create table t1 (id char(16) not null default '', primary key (id));
+insert into t1 values ('100'),('101'),('102');
+create table t2 (id char(16) default null);
+insert into t2 values (1);
+create view v1 as select t1.id from t1;
+create view v2 as select t2.id from t2;
+create view v3 as select (t1.id+2) as id from t1 natural left join t2;
+select t1.id from t1 left join v2 using (id);
+id
+100
+101
+102
+select t1.id from v2 right join t1 using (id);
+id
+100
+101
+102
+select t1.id from t1 left join v3 using (id);
+id
+100
+101
+102
+select * from t1 left join v2 using (id);
+id
+100
+101
+102
+select * from v2 right join t1 using (id);
+id
+100
+101
+102
+select * from t1 left join v3 using (id);
+id
+100
+101
+102
+select v1.id from v1 left join v2 using (id);
+id
+100
+101
+102
+select v1.id from v2 right join v1 using (id);
+id
+100
+101
+102
+select v1.id from v1 left join v3 using (id);
+id
+100
+101
+102
+select * from v1 left join v2 using (id);
+id
+100
+101
+102
+select * from v2 right join v1 using (id);
+id
+100
+101
+102
+select * from v1 left join v3 using (id);
+id
+100
+101
+102
+drop table t1, t2;
+drop view v1, v2, v3;
+create table t1 (id int(11) not null default '0');
+insert into t1 values (123),(191),(192);
+create table t2 (id char(16) character set utf8 not null);
+insert into t2 values ('58013'),('58014'),('58015'),('58016');
+create table t3 (a_id int(11) not null, b_id char(16) character set utf8);
+insert into t3 values (123,null),(123,null),(123,null),(123,null),(123,null),(123,'58013');
+select count(*)
+from t1 inner join (t3 left join t2 on t2.id = t3.b_id) on t1.id = t3.a_id;
+count(*)
+6
+select count(*)
+from t1 inner join (t2 right join t3 on t2.id = t3.b_id) on t1.id = t3.a_id;
+count(*)
+6
+drop table t1,t2,t3;
+create table t1 (a int);
+create table t2 (b int);
+create table t3 (c int);
+select * from t1 join t2 join t3 on (t1.a=t3.c);
+a b c
+select * from t1 join t2 left join t3 on (t1.a=t3.c);
+a b c
+select * from t1 join t2 right join t3 on (t1.a=t3.c);
+a b c
+select * from t1 join t2 straight_join t3 on (t1.a=t3.c);
+a b c
+drop table t1, t2 ,t3;
+create table t1(f1 int, f2 date);
+insert into t1 values(1,'2005-01-01'),(2,'2005-09-01'),(3,'2005-09-30'),
+(4,'2005-10-01'),(5,'2005-12-30');
+select * from t1 where f2 >= 0 order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+3 2005-09-30
+4 2005-10-01
+5 2005-12-30
+select * from t1 where f2 >= '0000-00-00' order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+3 2005-09-30
+4 2005-10-01
+5 2005-12-30
+select * from t1 where f2 >= '2005-09-31' order by f2;
+f1 f2
+4 2005-10-01
+5 2005-12-30
+select * from t1 where f2 >= '2005-09-3a' order by f2;
+f1 f2
+3 2005-09-30
+4 2005-10-01
+5 2005-12-30
+Warnings:
+Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1
+select * from t1 where f2 <= '2005-09-31' order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+3 2005-09-30
+select * from t1 where f2 <= '2005-09-3a' order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+Warnings:
+Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1
+drop table t1;
+create table t1 (f1 int, f2 int);
+insert into t1 values (1, 30), (2, 20), (3, 10);
+create algorithm=merge view v1 as select f1, f2 from t1;
+create algorithm=merge view v2 (f2, f1) as select f1, f2 from t1;
+create algorithm=merge view v3 as select t1.f1 as f2, t1.f2 as f1 from t1;
+select t1.f1 as x1, f1 from t1 order by t1.f1;
+x1 f1
+1 1
+2 2
+3 3
+select v1.f1 as x1, f1 from v1 order by v1.f1;
+x1 f1
+1 1
+2 2
+3 3
+select v2.f1 as x1, f1 from v2 order by v2.f1;
+x1 f1
+10 10
+20 20
+30 30
+select v3.f1 as x1, f1 from v3 order by v3.f1;
+x1 f1
+10 10
+20 20
+30 30
+select f1, f2, v1.f1 as x1 from v1 order by v1.f1;
+f1 f2 x1
+1 30 1
+2 20 2
+3 10 3
+select f1, f2, v2.f1 as x1 from v2 order by v2.f1;
+f1 f2 x1
+10 3 10
+20 2 20
+30 1 30
+select f1, f2, v3.f1 as x1 from v3 order by v3.f1;
+f1 f2 x1
+10 3 10
+20 2 20
+30 1 30
+drop table t1;
+drop view v1, v2, v3;
+CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a));
+CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a));
+CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32),
+PRIMARY KEY(key_a,key_b));
+INSERT INTO t1 VALUES (0,'');
+INSERT INTO t1 VALUES (1,'i');
+INSERT INTO t1 VALUES (2,'j');
+INSERT INTO t1 VALUES (3,'k');
+INSERT INTO t2 VALUES (1,'r');
+INSERT INTO t2 VALUES (2,'s');
+INSERT INTO t2 VALUES (3,'t');
+INSERT INTO t3 VALUES (1,5,'x');
+INSERT INTO t3 VALUES (1,6,'y');
+INSERT INTO t3 VALUES (2,5,'xx');
+INSERT INTO t3 VALUES (2,6,'yy');
+INSERT INTO t3 VALUES (2,7,'zz');
+INSERT INTO t3 VALUES (3,5,'xxx');
+SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+key_a foo
+2 xx
+EXPLAIN SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1
+SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+key_a foo
+2 xx
+EXPLAIN SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1
+DROP TABLE t1,t2,t3;
+create table t1 (f1 int);
+insert into t1 values(1),(2);
+create table t2 (f2 int, f3 int, key(f2));
+insert into t2 values(1,1),(2,2);
+create table t3 (f4 int not null);
+insert into t3 values (2),(2),(2);
+select f1,(select count(*) from t2,t3 where f2=f1 and f3=f4) as count from t1;
+f1 count
+1 0
+2 3
+drop table t1,t2,t3;
+create table t1 (f1 int unique);
+create table t2 (f2 int unique);
+create table t3 (f3 int unique);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+insert into t3 values(1),(NULL);
+select * from t3 where f3 is null;
+f3
+NULL
+select t2.f2 from t1 left join t2 on f1=f2 join t3 on f1=f3 where f1=1;
+f2
+1
+drop table t1,t2,t3;
+create table t1(f1 char, f2 char not null);
+insert into t1 values(null,'a');
+create table t2 (f2 char not null);
+insert into t2 values('b');
+select * from t1 left join t2 on f1=t2.f2 where t1.f2='a';
+f1 f2 f2
+NULL a NULL
+drop table t1,t2;
+select * from (select * left join t on f1=f2) tt;
+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 'on f1=f2) tt' at line 1
+CREATE TABLE t1 (sku int PRIMARY KEY, pr int);
+CREATE TABLE t2 (sku int PRIMARY KEY, sppr int, name varchar(255));
+INSERT INTO t1 VALUES
+(10, 10), (20, 10), (30, 20), (40, 30), (50, 10), (60, 10);
+INSERT INTO t2 VALUES
+(10, 10, 'aaa'), (20, 10, 'bbb'), (30, 10, 'ccc'), (40, 20, 'ddd'),
+(50, 10, 'eee'), (60, 20, 'fff'), (70, 20, 'ggg'), (80, 30, 'hhh');
+SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
+FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku);
+sku sppr name sku pr
+20 10 bbb 10 10
+20 10 bbb 20 10
+EXPLAIN
+SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
+FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where
+DROP TABLE t1,t2;
+CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
+INSERT t1 SET i = 0;
+UPDATE t1 SET i = -1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = CAST(i - 1 AS SIGNED);
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = i - 1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+255
+DROP TABLE t1;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 (a int, b int, c int, e int, primary key(a,b,c));
+insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C;
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+select 'In next EXPLAIN, B.rows must be exactly 10:' Z;
+Z
+In next EXPLAIN, B.rows must be exactly 10:
+explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5
+and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A range PRIMARY PRIMARY 12 NULL 4 Using where
+1 SIMPLE B ref PRIMARY PRIMARY 8 const,test.A.e 10
+drop table t1, t2;
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b));
+INSERT INTO t1 VALUES (1, 3), (9,4), (7,5), (4,5), (6,2),
+(3,1), (5,1), (8,9), (2,2), (0,9);
+CREATE TABLE t2 (c int, d int, f int, INDEX(c,f));
+INSERT INTO t2 VALUES
+(1,0,0), (1,0,1), (2,0,0), (2,0,1), (3,0,0), (4,0,1),
+(5,0,0), (5,0,1), (6,0,0), (0,0,1), (7,0,0), (7,0,1),
+(0,0,0), (0,0,1), (8,0,0), (8,0,1), (9,0,0), (9,0,1);
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where
+DROP TABLE t1, t2;
+create table t1 (
+a int unsigned not null auto_increment primary key,
+b bit not null,
+c bit not null
+);
+create table t2 (
+a int unsigned not null auto_increment primary key,
+b bit not null,
+c int unsigned not null,
+d varchar(50)
+);
+insert into t1 (b,c) values (0,1), (0,1);
+insert into t2 (b,c) values (0,1);
+select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
+from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
+where t1.b <> 1 order by t1.a;
+a t1.b + 0 t1.c + 0 a t2.b + 0 c d
+1 0 1 1 0 1 NULL
+2 0 1 NULL NULL NULL NULL
+drop table t1,t2;
+SELECT 0.9888889889 * 1.011111411911;
+0.9888889889 * 1.011111411911
+0.9998769417899202067879
+prepare stmt from 'select 1 as " a "';
+Warnings:
+Warning 1466 Leading spaces are removed from name ' a '
+execute stmt;
+a
+1
+CREATE TABLE t1 (a int NOT NULL PRIMARY KEY, b int NOT NULL);
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
+CREATE TABLE t2 (c int NOT NULL, INDEX idx(c));
+INSERT INTO t2 VALUES
+(1), (1), (1), (1), (1), (1), (1), (1),
+(2), (2), (2), (2),
+(3), (3),
+(4);
+EXPLAIN SELECT b FROM t1, t2 WHERE b=c AND a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 ref idx idx 4 const 7 Using index
+EXPLAIN SELECT b FROM t1, t2 WHERE b=c AND a=4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 ref idx idx 4 const 1 Using index
+DROP TABLE t1, t2;
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a int);
+INSERT INTO t1 VALUES (1,2), (2,NULL), (3,2);
+CREATE TABLE t2 (b int, c INT, INDEX idx1(b));
+INSERT INTO t2 VALUES (2,1), (3,2);
+CREATE TABLE t3 (d int, e int, INDEX idx1(d));
+INSERT INTO t3 VALUES (2,10), (2,20), (1,30), (2,40), (2,50);
+EXPLAIN
+SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
+WHERE t1.id=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 const idx1 NULL NULL NULL 1
+1 SIMPLE t3 ref idx1 idx1 5 const 3 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
+WHERE t1.id=2;
+id a b c d e
+2 NULL NULL NULL 2 10
+2 NULL NULL NULL 2 20
+2 NULL NULL NULL 2 40
+2 NULL NULL NULL 2 50
+DROP TABLE t1,t2,t3;
+create table t1 (c1 varchar(1), c2 int, c3 int, c4 int, c5 int, c6 int,
+c7 int, c8 int, c9 int, fulltext key (`c1`));
+select distinct match (`c1`) against ('z') , c2, c3, c4,c5, c6,c7, c8
+from t1 where c9=1 order by c2, c2;
+match (`c1`) against ('z') c2 c3 c4 c5 c6 c7 c8
+drop table t1;
+CREATE TABLE t1 (pk varchar(10) PRIMARY KEY, fk varchar(16));
+CREATE TABLE t2 (pk varchar(16) PRIMARY KEY, fk varchar(10));
+INSERT INTO t1 VALUES
+('d','dddd'), ('i','iii'), ('a','aa'), ('b','bb'), ('g','gg'),
+('e','eee'), ('c','cccc'), ('h','hhh'), ('j','jjj'), ('f','fff');
+INSERT INTO t2 VALUES
+('jjj', 'j'), ('cc','c'), ('ccc','c'), ('aaa', 'a'), ('jjjj','j'),
+('hhh','h'), ('gg','g'), ('fff','f'), ('ee','e'), ('ffff','f'),
+('bbb','b'), ('ff','f'), ('cccc','c'), ('dddd','d'), ('jj','j'),
+('aaaa','a'), ('bb','b'), ('eeee','e'), ('aa','a'), ('hh','h');
+EXPLAIN SELECT t2.*
+FROM t1 JOIN t2 ON t2.fk=t1.pk
+WHERE t2.fk < 'c' AND t2.pk=t1.fk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
+EXPLAIN SELECT t2.*
+FROM t1 JOIN t2 ON t2.fk=t1.pk
+WHERE t2.fk BETWEEN 'a' AND 'b' AND t2.pk=t1.fk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
+EXPLAIN SELECT t2.*
+FROM t1 JOIN t2 ON t2.fk=t1.pk
+WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
+CREATE TABLE t2 (a int, b varchar(20) NOT NULL,
+PRIMARY KEY (a), UNIQUE KEY (b));
+INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c');
+INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
+EXPLAIN SELECT t1.a FROM t1 LEFT JOIN t2 ON t2.b=t1.b WHERE t1.a=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+DROP TABLE t1,t2;
+CREATE TABLE t1(id int PRIMARY KEY, b int, e int);
+CREATE TABLE t2(i int, a int, INDEX si(i), INDEX ai(a));
+CREATE TABLE t3(a int PRIMARY KEY, c char(4), INDEX ci(c));
+INSERT INTO t1 VALUES
+(1,10,19), (2,20,22), (4,41,42), (9,93,95), (7, 77,79),
+(6,63,67), (5,55,58), (3,38,39), (8,81,89);
+INSERT INTO t2 VALUES
+(21,210), (41,410), (82,820), (83,830), (84,840),
+(65,650), (51,510), (37,370), (94,940), (76,760),
+(22,220), (33,330), (40,400), (95,950), (38,380),
+(67,670), (88,880), (57,570), (96,960), (97,970);
+INSERT INTO t3 VALUES
+(210,'bb'), (950,'ii'), (400,'ab'), (500,'ee'), (220,'gg'),
+(440,'gg'), (310,'eg'), (380,'ee'), (840,'bb'), (830,'ff'),
+(230,'aa'), (960,'ii'), (410,'aa'), (510,'ee'), (290,'bb'),
+(450,'gg'), (320,'dd'), (390,'hh'), (850,'jj'), (860,'ff');
+EXPLAIN
+SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
+WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
+t3.a=t2.a AND t3.c IN ('bb','ee');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si si 5 NULL 4 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN
+SELECT t3.a FROM t1,t2,t3
+WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
+t3.a=t2.a AND t3.c IN ('bb','ee') ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si,ai si 5 NULL 4 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN
+SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
+WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
+t3.c IN ('bb','ee');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si si 5 NULL 2 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN
+SELECT t3.a FROM t1,t2,t3
+WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
+t3.c IN ('bb','ee');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 ( f1 int primary key, f2 int, f3 int, f4 int, f5 int, f6 int, checked_out int);
+CREATE TABLE t2 ( f11 int PRIMARY KEY );
+INSERT INTO t1 VALUES (1,1,1,0,0,0,0),(2,1,1,3,8,1,0),(3,1,1,4,12,1,0);
+INSERT INTO t2 VALUES (62);
+SELECT * FROM t1 LEFT JOIN t2 ON f11 = t1.checked_out GROUP BY f1 ORDER BY f2, f3, f4, f5 LIMIT 0, 1;
+f1 f2 f3 f4 f5 f6 checked_out f11
+1 1 1 0 0 0 0 NULL
+DROP TABLE t1, t2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a int);
+INSERT into t1 values (1), (2), (3);
+SELECT * FROM t1 LIMIT 2, -1;
+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 '-1' at line 1
+DROP TABLE t1;
+CREATE TABLE t1 (
+ID_with_null int NULL,
+ID_better int NOT NULL,
+INDEX idx1 (ID_with_null),
+INDEX idx2 (ID_better)
+);
+INSERT INTO t1 VALUES (1,1), (2,1), (null,3), (null,3), (null,3), (null,3);
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+SELECT COUNT(*) FROM t1 WHERE ID_with_null IS NULL;
+COUNT(*)
+128
+SELECT COUNT(*) FROM t1 WHERE ID_better=1;
+COUNT(*)
+2
+EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP INDEX idx1 ON t1;
+CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
+EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP TABLE t1;
+CREATE TABLE t1 (
+ID1_with_null int NULL,
+ID2_with_null int NULL,
+ID_better int NOT NULL,
+INDEX idx1 (ID1_with_null, ID2_with_null),
+INDEX idx2 (ID_better)
+);
+INSERT INTO t1 VALUES (1,1,1), (2,2,1), (3,null,3), (null,3,3), (null,null,3),
+(3,null,3), (null,3,3), (null,null,3), (3,null,3), (null,3,3), (null,null,3);
+INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null=3;
+COUNT(*)
+24
+SELECT COUNT(*) FROM t1 WHERE ID1_with_null=3 AND ID2_with_null IS NULL;
+COUNT(*)
+24
+SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null IS NULL;
+COUNT(*)
+192
+SELECT COUNT(*) FROM t1 WHERE ID_better=1;
+COUNT(*)
+2
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP INDEX idx1 ON t1;
+CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND
+(ID2_with_null=1 OR ID2_with_null=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, ts TIMESTAMP, KEY ts(ts));
+INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+CREATE TABLE t2 (a INT, dt1 DATETIME, dt2 DATETIME, PRIMARY KEY (a));
+INSERT INTO t2 VALUES (30, "2006-01-01 00:00:00", "2999-12-31 00:00:00");
+INSERT INTO t2 SELECT a+1,dt1,dt2 FROM t2;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+EXPLAIN
+SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30
+AND t1.ts BETWEEN t2.dt1 AND t2.dt2
+AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t1 range ts ts 4 NULL 1 Using where
+Warnings:
+Warning 1292 Incorrect datetime value: '2999-12-31 00:00:00' for column 'ts' at row 1
+SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30
+AND t1.ts BETWEEN t2.dt1 AND t2.dt2
+AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
+a ts a dt1 dt2
+30 2006-01-03 23:00:00 30 2006-01-01 00:00:00 2999-12-31 00:00:00
+Warnings:
+Warning 1292 Incorrect datetime value: '2999-12-31 00:00:00' for column 'ts' at row 1
+DROP TABLE t1,t2;
+create table t1 (a bigint unsigned);
+insert into t1 values
+(if(1, 9223372036854775808, 1)),
+(case when 1 then 9223372036854775808 else 1 end),
+(coalesce(9223372036854775808, 1));
+select * from t1;
+a
+9223372036854775808
+9223372036854775808
+9223372036854775808
+drop table t1;
+create table t1 select
+if(1, 9223372036854775808, 1) i,
+case when 1 then 9223372036854775808 else 1 end c,
+coalesce(9223372036854775808, 1) co;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` decimal(19,0) NOT NULL DEFAULT '0',
+ `c` decimal(19,0) NOT NULL DEFAULT '0',
+ `co` decimal(19,0) NOT NULL DEFAULT '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+select
+if(1, cast(1111111111111111111 as unsigned), 1) i,
+case when 1 then cast(1111111111111111111 as unsigned) else 1 end c,
+coalesce(cast(1111111111111111111 as unsigned), 1) co;
+i c co
+1111111111111111111 1111111111111111111 1111111111111111111
+CREATE TABLE t1 (name varchar(255));
+CREATE TABLE t2 (name varchar(255), n int, KEY (name(3)));
+INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
+INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
+INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
+INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
+SELECT * FROM t2;
+name n
+bb 1
+aa 2
+cc 3
+cc 4
+cc 5
+bb 6
+cc 7
+SELECT * FROM t2 ORDER BY name;
+name n
+aa 2
+bb 1
+bb 6
+cc 4
+cc 3
+cc 5
+cc 7
+SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
+name LENGTH(name) n
+aa 2 2
+bb 2 1
+bb 3 6
+cc 4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref name name 6 const 3 Using where
+SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+name LENGTH(name) n
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+name LENGTH(name) n
+cc 5 3
+cc 4 4
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where; Using filesort
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+name LENGTH(name) n
+cc 4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref name name 6 test.t1.name 2
+SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+name name n
+ccc NULL NULL
+bb bb 1
+bb bb 6
+cc cc 3
+cc cc 5
+cc cc 7
+aa aa 2
+aa aa 2
+DROP TABLE t1,t2;
+CREATE TABLE t1 (name text);
+CREATE TABLE t2 (name text, n int, KEY (name(3)));
+INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
+INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
+INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
+INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
+SELECT * FROM t2;
+name n
+bb 1
+aa 2
+cc 3
+cc 4
+cc 5
+bb 6
+cc 7
+SELECT * FROM t2 ORDER BY name;
+name n
+aa 2
+bb 1
+bb 6
+cc 4
+cc 3
+cc 5
+cc 7
+SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
+name LENGTH(name) n
+aa 2 2
+bb 2 1
+bb 3 6
+cc 4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref name name 6 const 3 Using where
+SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+name LENGTH(name) n
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+name LENGTH(name) n
+cc 5 3
+cc 4 4
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where; Using filesort
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+name LENGTH(name) n
+cc 4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref name name 6 test.t1.name 2
+SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+name name n
+ccc NULL NULL
+bb bb 1
+bb bb 6
+cc cc 3
+cc cc 5
+cc cc 7
+aa aa 2
+aa aa 2
+DROP TABLE t1,t2;
+CREATE TABLE t1 (
+access_id int NOT NULL default '0',
+name varchar(20) default NULL,
+rank int NOT NULL default '0',
+KEY idx (access_id)
+);
+CREATE TABLE t2 (
+faq_group_id int NOT NULL default '0',
+faq_id int NOT NULL default '0',
+access_id int default NULL,
+UNIQUE KEY idx1 (faq_id),
+KEY idx2 (faq_group_id,faq_id)
+);
+INSERT INTO t1 VALUES
+(1,'Everyone',2),(2,'Help',3),(3,'Technical Support',1),(4,'Chat User',4);
+INSERT INTO t2 VALUES
+(261,265,1),(490,494,1);
+SELECT t2.faq_id
+FROM t1 INNER JOIN t2 IGNORE INDEX (idx1)
+ON (t1.access_id = t2.access_id)
+LEFT JOIN t2 t
+ON (t.faq_group_id = t2.faq_group_id AND
+find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
+WHERE
+t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
+faq_id
+265
+SELECT t2.faq_id
+FROM t1 INNER JOIN t2
+ON (t1.access_id = t2.access_id)
+LEFT JOIN t2 t
+ON (t.faq_group_id = t2.faq_group_id AND
+find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
+WHERE
+t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
+faq_id
+265
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a INT, b INT, KEY inx (b,a));
+INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1, 6), (1,7);
+EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER JOIN t1 f2
+ON ( f1.b=f2.b AND f1.a<f2.a )
+WHERE 1 AND f1.b NOT IN (100,2232,3343,51111);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE f1 index inx inx 10 NULL 7 Using where; Using index
+1 SIMPLE f2 ref inx inx 5 test.f1.b 1 Using where; Using index
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (1,11), (2,22), (2,22);
+EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2)))))))))))))))))))))))))))))))) > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+31 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
+32 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
+EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) > 0;
+ERROR HY000: Too high level of nesting for select
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 int(11) NOT NULL AUTO_INCREMENT,
+c2 varchar(1000) DEFAULT NULL,
+c3 bigint(20) DEFAULT NULL,
+c4 bigint(20) DEFAULT NULL,
+PRIMARY KEY (c1)
+);
+EXPLAIN EXTENDED
+SELECT join_2.c1
+FROM
+t1 AS join_0,
+t1 AS join_1,
+t1 AS join_2,
+t1 AS join_3,
+t1 AS join_4,
+t1 AS join_5,
+t1 AS join_6,
+t1 AS join_7
+WHERE
+join_0.c1=join_1.c1 AND
+join_1.c1=join_2.c1 AND
+join_2.c1=join_3.c1 AND
+join_3.c1=join_4.c1 AND
+join_4.c1=join_5.c1 AND
+join_5.c1=join_6.c1 AND
+join_6.c1=join_7.c1
+OR
+join_0.c2 < '?' AND
+join_1.c2 < '?' AND
+join_2.c2 > '?' AND
+join_2.c2 < '!' AND
+join_3.c2 > '?' AND
+join_4.c2 = '?' AND
+join_5.c2 <> '?' AND
+join_6.c2 <> '?' AND
+join_7.c2 >= '?' AND
+join_0.c1=join_1.c1 AND
+join_1.c1=join_2.c1 AND
+join_2.c1=join_3.c1 AND
+join_3.c1=join_4.c1 AND
+join_4.c1=join_5.c1 AND
+join_5.c1=join_6.c1 AND
+join_6.c1=join_7.c1
+GROUP BY
+join_3.c1,
+join_2.c1,
+join_7.c1,
+join_1.c1,
+join_0.c1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
+SHOW WARNINGS;
+Level Code Message
+Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
+DROP TABLE t1;
+SELECT 1 AS ` `;
+
+1
+Warnings:
+Warning 1474 Name ' ' has become ''
+SELECT 1 AS ` `;
+
+1
+Warnings:
+Warning 1474 Name ' ' has become ''
+SELECT 1 AS ` x`;
+x
+1
+Warnings:
+Warning 1466 Leading spaces are removed from name ' x'
+CREATE VIEW v1 AS SELECT 1 AS ``;
+ERROR 42000: Incorrect column name ''
+CREATE VIEW v1 AS SELECT 1 AS ` `;
+ERROR 42000: Incorrect column name ' '
+CREATE VIEW v1 AS SELECT 1 AS ` `;
+ERROR 42000: Incorrect column name ' '
+CREATE VIEW v1 AS SELECT (SELECT 1 AS ` `);
+ERROR 42000: Incorrect column name ' '
+CREATE VIEW v1 AS SELECT 1 AS ` x`;
+Warnings:
+Warning 1466 Leading spaces are removed from name ' x'
+SELECT `x` FROM v1;
+x
+1
+ALTER VIEW v1 AS SELECT 1 AS ` `;
+ERROR 42000: Incorrect column name ' '
+DROP VIEW v1;
+select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT'
+ and '2007/10/20 00:00:00 GMT';
+str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT'
+ and '2007/10/20 00:00:00 GMT'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT'
+Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT'
+select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6';
+str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007/10/01 00:00:00 GMT-6'
+select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6';
+str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007/10/2000:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007-10-1 00:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007-10-01 x00:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:x00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 x12:34:56 GMT-6'
+select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6';
+str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6'
+select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6';
+str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6'
+select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56';
+str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'
+1
+select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00';
+str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'
+0
+select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00';
+str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'
+1
+select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00';
+str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34'
+select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34';
+str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'
+1
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'
+1
+select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00'
+ and '2007/10/20 00:00:00';
+str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00'
+ and '2007/10/20 00:00:00'
+1
+set SQL_MODE=TRADITIONAL;
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34'
+select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34';
+str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34'
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34:00'
+select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01'
+ and '2007/10/20';
+str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01'
+ and '2007/10/20'
+0
+Warnings:
+Warning 1292 Incorrect datetime value: '2007-10-00' for column '2007/09/01' at row 1
+Warning 1292 Incorrect datetime value: '2007-10-00' for column '2007/10/20' at row 1
+set SQL_MODE=DEFAULT;
+select str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20';
+str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: ''
+select str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20';
+str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'
+0
+select str_to_date('','%Y-%m-%d %H:%i') = '2007-10-01 12:34';
+str_to_date('','%Y-%m-%d %H:%i') = '2007-10-01 12:34'
+0
+select str_to_date(NULL,'%Y-%m-%d %H:%i') = '2007-10-01 12:34';
+str_to_date(NULL,'%Y-%m-%d %H:%i') = '2007-10-01 12:34'
+NULL
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = ''
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: ''
+select str_to_date('1','%Y-%m-%d') = '1';
+str_to_date('1','%Y-%m-%d') = '1'
+0
+Warnings:
+Warning 1292 Truncated incorrect date value: '1'
+select str_to_date('1','%Y-%m-%d') = '1';
+str_to_date('1','%Y-%m-%d') = '1'
+0
+Warnings:
+Warning 1292 Truncated incorrect date value: '1'
+select str_to_date('','%Y-%m-%d') = '';
+str_to_date('','%Y-%m-%d') = ''
+0
+Warnings:
+Warning 1292 Truncated incorrect date value: ''
+select str_to_date('1000-01-01','%Y-%m-%d') between '0000-00-00' and NULL;
+str_to_date('1000-01-01','%Y-%m-%d') between '0000-00-00' and NULL
+0
+select str_to_date('1000-01-01','%Y-%m-%d') between NULL and '2000-00-00';
+str_to_date('1000-01-01','%Y-%m-%d') between NULL and '2000-00-00'
+0
+select str_to_date('1000-01-01','%Y-%m-%d') between NULL and NULL;
+str_to_date('1000-01-01','%Y-%m-%d') between NULL and NULL
+0
+CREATE TABLE t1 (c11 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t2 (c21 INT UNSIGNED NOT NULL,
+c22 INT DEFAULT NULL,
+KEY(c21, c22));
+CREATE TABLE t3 (c31 INT UNSIGNED NOT NULL DEFAULT 0,
+c32 INT DEFAULT NULL,
+c33 INT NOT NULL,
+c34 INT UNSIGNED DEFAULT 0,
+KEY (c33, c34, c32));
+INSERT INTO t1 values (),(),(),(),();
+INSERT INTO t2 SELECT a.c11, b.c11 FROM t1 a, t1 b;
+INSERT INTO t3 VALUES (1, 1, 1, 0),
+(2, 2, 0, 0),
+(3, 3, 1, 0),
+(4, 4, 0, 0),
+(5, 5, 1, 0);
+SELECT c32 FROM t1, t2, t3 WHERE t1.c11 IN (1, 3, 5) AND
+t3.c31 = t1.c11 AND t2.c21 = t1.c11 AND
+t3.c33 = 1 AND t2.c22 in (1, 3)
+ORDER BY c32;
+c32
+1
+1
+3
+3
+5
+5
+SELECT c32 FROM t1, t2, t3 WHERE t1.c11 IN (1, 3, 5) AND
+t3.c31 = t1.c11 AND t2.c21 = t1.c11 AND
+t3.c33 = 1 AND t2.c22 in (1, 3)
+ORDER BY c32 DESC;
+c32
+5
+5
+3
+3
+1
+1
+DROP TABLE t1, t2, t3;
+
+#
+# Bug#30736: Row Size Too Large Error Creating a Table and
+# Inserting Data.
+#
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+
+CREATE TABLE t1(
+c1 DECIMAL(10, 2),
+c2 FLOAT);
+
+INSERT INTO t1 VALUES (0, 1), (2, 3), (4, 5);
+
+CREATE TABLE t2(
+c3 DECIMAL(10, 2))
+SELECT
+c1 * c2 AS c3
+FROM t1;
+
+SELECT * FROM t1;
+c1 c2
+0.00 1
+2.00 3
+4.00 5
+
+SELECT * FROM t2;
+c3
+0.00
+6.00
+20.00
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+CREATE TABLE t1 (c1 BIGINT NOT NULL);
+INSERT INTO t1 (c1) VALUES (1);
+SELECT * FROM t1 WHERE c1 > NULL + 1;
+c1
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY);
+INSERT INTO t1 (a) VALUES ('foo0'), ('bar0'), ('baz0');
+SELECT * FROM t1 WHERE a IN (CONCAT('foo', 0), 'bar');
+a
+foo0
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT);
+CREATE TABLE t2 (a INT, c INT, KEY(a));
+INSERT INTO t1 VALUES (1, 1), (2, 2);
+INSERT INTO t2 VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
+(2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
+(3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
+(4, 1), (4, 2), (4, 3), (4, 4), (4, 5);
+FLUSH STATUS;
+SELECT DISTINCT b FROM t1 LEFT JOIN t2 USING(a) WHERE c <= 3;
+b
+1
+2
+SHOW STATUS LIKE 'Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 6
+DROP TABLE t1, t2;
+CREATE TABLE t1 (f1 bigint(20) NOT NULL default '0',
+f2 int(11) NOT NULL default '0',
+f3 bigint(20) NOT NULL default '0',
+f4 varchar(255) NOT NULL default '',
+PRIMARY KEY (f1),
+KEY key1 (f4),
+KEY key2 (f2));
+CREATE TABLE t2 (f1 int(11) NOT NULL default '0',
+f2 enum('A1','A2','A3') NOT NULL default 'A1',
+f3 int(11) NOT NULL default '0',
+PRIMARY KEY (f1),
+KEY key1 (f3));
+CREATE TABLE t3 (f1 bigint(20) NOT NULL default '0',
+f2 datetime NOT NULL default '1980-01-01 00:00:00',
+PRIMARY KEY (f1));
+insert into t1 values (1, 1, 1, 'abc');
+insert into t1 values (2, 1, 2, 'def');
+insert into t1 values (3, 1, 2, 'def');
+insert into t2 values (1, 'A1', 1);
+insert into t3 values (1, '1980-01-01');
+SELECT a.f3, cr.f4, count(*) count
+FROM t2 a
+STRAIGHT_JOIN t1 cr ON cr.f2 = a.f1
+LEFT JOIN
+(t1 cr2
+JOIN t3 ae2 ON cr2.f3 = ae2.f1
+) ON a.f1 = cr2.f2 AND ae2.f2 < now() - INTERVAL 7 DAY AND
+cr.f4 = cr2.f4
+GROUP BY a.f3, cr.f4;
+f3 f4 count
+1 abc 1
+1 def 2
+drop table t1, t2, t3;
+CREATE TABLE t1 (a INT KEY, b INT);
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
+EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 1)) limit 2
+EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = `test`.`t1`.`b`) and (`test`.`t1`.`a` > 1)) limit 2
+DROP TABLE t1;
+#
+# Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when
+# forcing a spatial index
+#
+CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a));
+INSERT INTO t1 VALUES
+(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')),
+(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'));
+EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL a NULL NULL NULL 2
+SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
+1
+1
+1
+1
+1
+EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL a NULL NULL NULL 2
+SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
+1
+1
+1
+1
+1
+DROP TABLE t1;
+#
+# Bug #48291 : crash with row() operator,select into @var, and
+# subquery returning multiple rows
+#
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (2),(3);
+# Should not crash
+SELECT 1 FROM t1 WHERE a <> 1 AND NOT
+ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1))
+INTO @var0;
+ERROR 21000: Subquery returns more than 1 row
+DROP TABLE t1;
+#
+# Bug #48458: simple query tries to allocate enormous amount of
+# memory
+#
+CREATE TABLE t1(a INT NOT NULL, b YEAR);
+INSERT INTO t1 VALUES ();
+Warnings:
+Warning 1364 Field 'a' doesn't have a default value
+CREATE TABLE t2(c INT);
+# Should not err out because of out-of-memory
+SELECT 1 FROM t2 JOIN t1 ON 1=1
+WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a);
+1
+DROP TABLE t1,t2;
+#
+# Bug #49199: Optimizer handles incorrectly:
+# field='const1' AND field='const2' in some cases
+
+CREATE TABLE t1(a DATETIME NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+a
+2001-01-01 00:00:00
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATE NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+a
+2001-01-01
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01' AS `a` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a TIMESTAMP NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+a
+2001-01-01 00:00:00
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+a b
+2001-01-01 00:00:00 2001-01-01
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+a b
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 0
+SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
+a b
+2001-01-01 00:00:00 2001-01-01
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
+SELECT x.a, y.a, z.a FROM t1 x
+JOIN t1 y ON x.a=y.a
+JOIN t1 z ON y.a=z.a
+WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
+a a a
+2001-01-01 00:00:00 2001-01-01 00:00:00 2001-01-01 00:00:00
+EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x
+JOIN t1 y ON x.a=y.a
+JOIN t1 z ON y.a=z.a
+WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE x system NULL NULL NULL NULL 1 100.00
+1 SIMPLE y system NULL NULL NULL NULL 1 100.00
+1 SIMPLE z system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1
+DROP TABLE t1;
+#
+# Bug #49897: crash in ptr_compare when char(0) NOT NULL
+# column is used for ORDER BY
+#
+SET @old_sort_buffer_size= @@session.sort_buffer_size;
+SET @@sort_buffer_size= 40000;
+CREATE TABLE t1(a CHAR(0) NOT NULL);
+INSERT INTO t1 VALUES (0), (0), (0);
+INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12;
+EXPLAIN SELECT a FROM t1 ORDER BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492
+SELECT a FROM t1 ORDER BY a;
+DROP TABLE t1;
+CREATE TABLE t1(a CHAR(0) NOT NULL, b CHAR(0) NOT NULL, c int);
+INSERT INTO t1 VALUES (0, 0, 0), (0, 0, 2), (0, 0, 1);
+INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12;
+EXPLAIN SELECT a FROM t1 ORDER BY a LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492
+SELECT a FROM t1 ORDER BY a LIMIT 5;
+a
+
+
+
+
+
+EXPLAIN SELECT * FROM t1 ORDER BY a, b LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492
+SELECT * FROM t1 ORDER BY a, b LIMIT 5;
+a b c
+ 0
+ 2
+ 1
+ 0
+ 2
+EXPLAIN SELECT * FROM t1 ORDER BY a, b, c LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 Using filesort
+SELECT * FROM t1 ORDER BY a, b, c LIMIT 5;
+a b c
+ 0
+ 0
+ 0
+ 0
+ 0
+EXPLAIN SELECT * FROM t1 ORDER BY c, a LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 Using filesort
+SELECT * FROM t1 ORDER BY c, a LIMIT 5;
+a b c
+ 0
+ 0
+ 0
+ 0
+ 0
+SET @@sort_buffer_size= @old_sort_buffer_size;
+DROP TABLE t1;
+End of 5.0 tests
+create table t1(a INT, KEY (a));
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+SELECT a FROM t1 ORDER BY a LIMIT 2;
+a
+1
+2
+SELECT a FROM t1 ORDER BY a LIMIT 2,4294967296;
+a
+3
+4
+5
+SELECT a FROM t1 ORDER BY a LIMIT 2,4294967297;
+a
+3
+4
+5
+DROP TABLE t1;
+CREATE TABLE A (date_key date);
+CREATE TABLE C (
+pk int,
+int_nokey int,
+int_key int,
+date_key date NOT NULL,
+date_nokey date,
+varchar_key varchar(1)
+);
+INSERT INTO C VALUES
+(1,1,1,'0000-00-00',NULL,NULL),
+(1,1,1,'0000-00-00',NULL,NULL);
+SELECT 1 FROM C WHERE pk > ANY (SELECT 1 FROM C);
+1
+SELECT COUNT(DISTINCT 1) FROM C
+WHERE date_key = (SELECT 1 FROM A WHERE C.date_key IS NULL) GROUP BY pk;
+COUNT(DISTINCT 1)
+SELECT date_nokey FROM C
+WHERE int_key IN (SELECT 1 FROM A)
+HAVING date_nokey = '10:41:7'
+ORDER BY date_key;
+date_nokey
+Warnings:
+Warning 1292 Incorrect date value: '10:41:7' for column 'date_nokey' at row 1
+DROP TABLE A,C;
+CREATE TABLE t1 (a INT NOT NULL, b INT);
+INSERT INTO t1 VALUES (1, 1);
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND a=a) OR b > 2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '1' AS `a`,'1' AS `b` from `test`.`t1` where 1
+SELECT * FROM t1 WHERE (a=a AND a=a) OR b > 2;
+a b
+1 1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL);
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND b=b AND c=c) OR b > 20;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1003 select '0' AS `a`,'0' AS `b`,'0' AS `c` from `test`.`t1` where 1
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND a=a AND b=b) OR b > 20;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1003 select '0' AS `a`,'0' AS `b`,'0' AS `c` from `test`.`t1` where 1
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND b=b AND a=a) OR b > 20;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1003 select '0' AS `a`,'0' AS `b`,'0' AS `c` from `test`.`t1` where 1
+DROP TABLE t1;
+#
+# Bug#45266: Uninitialized variable lead to an empty result.
+#
+drop table if exists A,AA,B,BB;
+CREATE TABLE `A` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`date_key` date NOT NULL,
+`date_nokey` date NOT NULL,
+`datetime_key` datetime NOT NULL,
+`int_nokey` int(11) NOT NULL,
+`time_key` time NOT NULL,
+`time_nokey` time NOT NULL,
+PRIMARY KEY (`pk`),
+KEY `date_key` (`date_key`),
+KEY `time_key` (`time_key`),
+KEY `datetime_key` (`datetime_key`)
+);
+CREATE TABLE `AA` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) NOT NULL,
+`time_key` time NOT NULL,
+KEY `time_key` (`time_key`),
+PRIMARY KEY (`pk`)
+);
+CREATE TABLE `B` (
+`date_nokey` date NOT NULL,
+`date_key` date NOT NULL,
+`time_key` time NOT NULL,
+`datetime_nokey` datetime NOT NULL,
+`varchar_key` varchar(1) NOT NULL,
+KEY `date_key` (`date_key`),
+KEY `time_key` (`time_key`),
+KEY `varchar_key` (`varchar_key`)
+);
+INSERT INTO `B` VALUES ('2003-07-28','2003-07-28','15:13:38','0000-00-00 00:00:00','f'),('0000-00-00','0000-00-00','00:05:48','2004-07-02 14:34:13','x');
+CREATE TABLE `BB` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) NOT NULL,
+`date_key` date NOT NULL,
+`varchar_nokey` varchar(1) NOT NULL,
+`date_nokey` date NOT NULL,
+PRIMARY KEY (`pk`),
+KEY `date_key` (`date_key`)
+);
+INSERT INTO `BB` VALUES (10,8,'0000-00-00','i','0000-00-00'),(11,0,'2005-08-18','','2005-08-18');
+SELECT table1 . `pk` AS field1
+FROM
+(BB AS table1 INNER JOIN
+(AA AS table2 STRAIGHT_JOIN A AS table3
+ON ( table3 . `date_key` = table2 . `pk` ))
+ON ( table3 . `datetime_key` = table2 . `int_nokey` ))
+WHERE ( table3 . `date_key` <= 4 AND table2 . `pk` = table1 . `varchar_nokey`)
+GROUP BY field1 ;
+field1
+SELECT table3 .`date_key` field1
+FROM
+B table1 LEFT JOIN B table3 JOIN
+(BB table6 JOIN A table7 ON table6 .`varchar_nokey`)
+ON table6 .`int_nokey` ON table6 .`date_key`
+ WHERE NOT ( table1 .`varchar_key` AND table7 .`pk`) GROUP BY field1;
+field1
+NULL
+SELECT table4 . `time_nokey` AS field1 FROM
+(AA AS table1 CROSS JOIN
+(AA AS table2 STRAIGHT_JOIN
+(B AS table3 STRAIGHT_JOIN A AS table4
+ON ( table4 . `date_key` = table3 . `time_key` ))
+ON ( table4 . `pk` = table3 . `date_nokey` ))
+ON ( table4 . `time_key` = table3 . `datetime_nokey` ))
+WHERE ( table4 . `time_key` < table1 . `time_key` AND
+table1 . `int_nokey` != 'f')
+GROUP BY field1 ORDER BY field1 , field1;
+field1
+SELECT table1 .`time_key` field2 FROM B table1 LEFT JOIN BB JOIN A table5 ON table5 .`date_nokey` ON table5 .`int_nokey` GROUP BY field2;
+field2
+00:05:48
+15:13:38
+drop table A,AA,B,BB;
+#end of test for bug#45266
+#
+# BUG#48052: Valgrind warning - uninitialized value in init_read_record()
+#
+CREATE TABLE t1 (
+pk int(11) NOT NULL,
+i int(11) DEFAULT NULL,
+v varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (2,7,'m');
+INSERT INTO t1 VALUES (3,9,'m');
+SELECT v
+FROM t1
+WHERE NOT pk > 0
+HAVING v <= 't'
+ORDER BY pk;
+v
+DROP TABLE t1;
+#
+# Bug#49489 Uninitialized cache led to a wrong result.
+#
+CREATE TABLE t1(c1 DOUBLE(5,4));
+INSERT INTO t1 VALUES (9.1234);
+SELECT * FROM t1 WHERE c1 < 9.12345;
+c1
+9.1234
+DROP TABLE t1;
+# End of test for bug#49489.
+#
+# Bug #49517: Inconsistent behavior while using
+# NULLable BIGINT and INT columns in comparison
+#
+CREATE TABLE t1(a BIGINT UNSIGNED NOT NULL, b BIGINT NULL, c INT NULL);
+INSERT INTO t1 VALUES(105, NULL, NULL);
+SELECT * FROM t1 WHERE b < 102;
+a b c
+SELECT * FROM t1 WHERE c < 102;
+a b c
+SELECT * FROM t1 WHERE 102 < b;
+a b c
+SELECT * FROM t1 WHERE 102 < c;
+a b c
+DROP TABLE t1;
+End of 5.1 tests
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_is.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-04-02 10:03:39 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-04-06 02:08:10 +0000
@@ -230,6 +230,18 @@ NULL information_schema INNODB_TRX trx_s
NULL information_schema INNODB_TRX trx_state 2 NO varchar 13 39 NULL NULL utf8 utf8_general_ci varchar(13) select
NULL information_schema INNODB_TRX trx_wait_started 5 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select
NULL information_schema INNODB_TRX trx_weight 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES KEY_CACHE_NAME 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
+NULL information_schema KEY_CACHES PARTITIONS 2 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
+NULL information_schema KEY_CACHES PARTITION_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
+NULL information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
@@ -743,6 +755,18 @@ NULL information_schema INNODB_TRX trx_w
NULL information_schema INNODB_TRX trx_weight bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema INNODB_TRX trx_mysql_thread_id bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema INNODB_TRX trx_query varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema KEY_CACHES KEY_CACHE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema KEY_CACHES PARTITIONS int NULL NULL NULL NULL int(3) unsigned
+NULL information_schema KEY_CACHES PARTITION_NUMBER int NULL NULL NULL NULL int(3) unsigned
+NULL information_schema KEY_CACHES FULL_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES BLOCK_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES USED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES UNUSED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES DIRTY_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES READ_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES READS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES WRITE_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES WRITES bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
=== modified file 'mysql-test/suite/funcs_1/r/is_tables_is.result'
--- a/mysql-test/suite/funcs_1/r/is_tables_is.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/suite/funcs_1/r/is_tables_is.result 2010-04-06 02:08:10 +0000
@@ -590,6 +590,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME KEY_CACHES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -1688,6 +1711,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME KEY_CACHES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
=== modified file 'mysql-test/suite/pbxt/r/mysqlshow.result'
--- a/mysql-test/suite/pbxt/r/mysqlshow.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/suite/pbxt/r/mysqlshow.result 2010-03-31 18:45:41 +0000
@@ -91,6 +91,7 @@ Database: information_schema
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -144,6 +145,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
=== modified file 'mysql-test/t/key_cache.test'
--- a/mysql-test/t/key_cache.test 2008-03-27 16:43:17 +0000
+++ b/mysql-test/t/key_cache.test 2010-04-01 21:42:40 +0000
@@ -1,11 +1,13 @@
#
-# Test of multiple key caches
+# Test of multiple key caches, simple an partitioned
#
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
-SET @save_key_buffer=@@key_buffer_size;
+SET @save_key_buffer_size=@@key_buffer_size;
+SET @save_key_cache_block_size=@@key_cache_block_size;
+SET @save_key_cache_partitions=@@key_cache_partitions;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@ -33,7 +35,7 @@ SELECT @@`default`.key_buffer_size;
SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size;
-SET @@global.key_buffer_size=@save_key_buffer;
+SET @@global.key_buffer_size=@save_key_buffer_size;
#
# Errors
@@ -247,3 +249,270 @@ SET GLOBAL key_cache_block_size= @bug284
DROP TABLE t1;
# End of 4.1 tests
+
+#
+# Test cases for partitioned key caches
+#
+
+# Test usage of the KEY_CACHE table from information schema
+# for a simple key cache
+
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_block_size=@save_key_cache_block_size;
+select @@key_buffer_size;
+select @@key_cache_block_size;
+select @@key_cache_partitions;
+
+create table t1 (
+ p int not null auto_increment primary key,
+ a char(10));
+create table t2 (
+ p int not null auto_increment primary key,
+ i int, a char(10), key k1(i), key k2(a));
+
+select @@key_cache_partitions;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
+show status like 'key_%';
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+delete from t2 where a='zzzz';
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+delete from t1;
+delete from t2;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+# For the key cache with 2 partitions execute the same sequence of
+# statements as for the simple cache above.
+# The statistical information on the number of i/o requests and
+# the number of is expected to be the same.
+
+set global key_cache_partitions=2;
+select @@key_cache_partitions;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
+show status like 'key_%';
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+delete from t1;
+delete from t2;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+# Check that we can work with one partition with the same results
+
+set global key_cache_partitions=1;
+select @@key_cache_partitions;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
+show status like 'key_%';
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+delete from t1;
+delete from t2;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+flush tables; flush status;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+# Switch back to 2 partitions
+
+set global key_buffer_size=32*1024;
+select @@key_buffer_size;
+set global key_cache_partitions=2;
+select @@key_cache_partitions;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+# Add more rows to tables t1 and t2
+
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+
+--replace_column 6 # 7 # 10 #
+select * from information_schema.key_caches where partition_number is null;
+
+select * from t1 where p between 1010 and 1020 ;
+select * from t2 where p between 1010 and 1020 ;
+--replace_column 6 # 7 # 10 #
+select * from information_schema.key_caches where partition_number is null;
+
+flush tables; flush status;
+update t1 set a='zzzz' where a='qqqq';
+update t2 set i=1 where i=2;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+# Now test how we can work with 7 partitions
+
+set global keycache1.key_buffer_size=256*1024;
+select @@keycache1.key_buffer_size;
+set global keycache1.key_cache_partitions=7;
+select @@keycache1.key_cache_partitions;
+
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+
+cache index t1 key (`primary`) in keycache1;
+
+explain select p from t1 where p between 1010 and 1020;
+select p from t1 where p between 1010 and 1020;
+explain select i from t2 where p between 1010 and 1020;
+select i from t2 where p between 1010 and 1020;
+explain select count(*) from t1, t2 where t1.p = t2.i;
+select count(*) from t1, t2 where t1.p = t2.i;
+
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+
+cache index t2 in keycache1;
+update t2 set p=p+3000, i=2 where a='qqqq';
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+
+set global keycache2.key_buffer_size=1024*1024;
+cache index t2 in keycache2;
+insert into t2 values (2000, 3, 'yyyy');
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and partition_number is null;
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
+
+cache index t2 in keycache1;
+update t2 set p=p+5000 where a='zzzz';
+select * from t2 where p between 1010 and 1020;
+explain select p from t2 where p between 1010 and 1020;
+select p from t2 where p between 1010 and 1020;
+explain select i from t2 where a='yyyy' and i=3;
+select i from t2 where a='yyyy' and i=3;
+explain select a from t2 where a='yyyy' and i=3;
+select a from t2 where a='yyyy' and i=3 ;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_cache_block_size=2*1024;
+insert into t2 values (7000, 3, 'yyyy');
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+insert into t2 values (8000, 3, 'yyyy');
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_buffer_size=64*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_cache_block_size=2*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_buffer_size=0;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_buffer_size=0;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_buffer_size=128*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+set global keycache1.key_cache_block_size=1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
+
+drop table t1,t2;
+
+set global keycache1.key_buffer_size=0;
+set global keycache2.key_buffer_size=0;
+
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_partitions=@save_key_cache_partitions;
+
+#End of 5.1 tests
=== added file 'mysql-test/t/select_pkeycache-master.opt'
--- a/mysql-test/t/select_pkeycache-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/select_pkeycache-master.opt 2010-02-16 16:41:11 +0000
@@ -0,0 +1 @@
+--key_cache_partitions=7
=== added file 'mysql-test/t/select_pkeycache.test'
--- a/mysql-test/t/select_pkeycache.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/select_pkeycache.test 2010-02-16 16:41:11 +0000
@@ -0,0 +1,8 @@
+
+#
+# Run select.test partitioned default key cache (with 7 partitions)
+# (see setting the number of partitions in select_pkecache-master.opt)
+# The result is expected the same as for select.test
+#
+
+--source t/select.test
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2010-03-30 12:36:49 +0000
+++ b/mysys/mf_keycache.c 2010-04-06 02:08:10 +0000
@@ -13,12 +13,43 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
/**
- @file
+ @file
+ The file contains the following modules:
+
+ Simple Key Cache Module
+
+ Partitioned Key Cache Module
+
+ Key Cache Interface Module
+
+*/
+
+#include "mysys_priv.h"
+#include "mysys_err.h"
+#include <keycache.h>
+#include "my_static.h"
+#include <m_string.h>
+#include <my_bit.h>
+#include <errno.h>
+#include <stdarg.h>
+
+/******************************************************************************
+ Simple Key Cache Module
+
+ The module contains implementations of all key cache interface functions
+ employed by partitioned key caches.
+
+******************************************************************************/
+
+/*
These functions handle keyblock cacheing for ISAM and MyISAM tables.
One cache can handle many files.
It must contain buffers of the same blocksize.
+
init_key_cache() should be used to init cache handler.
The free list (free_block_list) is a stack like structure.
@@ -37,9 +68,7 @@
blocks_unused is the sum of never used blocks in the pool and of currently
free blocks. blocks_used is the number of blocks fetched from the pool and
as such gives the maximum number of in-use blocks at any time.
-*/
-/*
Key Cache Locking
=================
@@ -104,14 +133,77 @@
I/O finished.
*/
-#include "mysys_priv.h"
-#include "mysys_err.h"
-#include <keycache.h>
-#include "my_static.h"
-#include <m_string.h>
-#include <my_bit.h>
-#include <errno.h>
-#include <stdarg.h>
+/* declare structures that is used by st_key_cache */
+
+struct st_block_link;
+typedef struct st_block_link BLOCK_LINK;
+struct st_keycache_page;
+typedef struct st_keycache_page KEYCACHE_PAGE;
+struct st_hash_link;
+typedef struct st_hash_link HASH_LINK;
+
+/* info about requests in a waiting queue */
+typedef struct st_keycache_wqueue
+{
+ struct st_my_thread_var *last_thread; /* circular list of waiting threads */
+} KEYCACHE_WQUEUE;
+
+#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
+
+/* Control block for a simple (non-partitioned) key cache */
+
+typedef struct st_simple_key_cache_cb
+{
+ my_bool key_cache_inited; /* <=> control block is allocated */
+ my_bool in_resize; /* true during resize operation */
+ my_bool resize_in_flush; /* true during flush of resize operation */
+ my_bool can_be_used; /* usage of cache for read/write is allowed */
+ size_t key_cache_mem_size; /* specified size of the cache memory */
+ uint key_cache_block_size; /* size of the page buffer of a cache block */
+ ulong min_warm_blocks; /* min number of warm blocks; */
+ ulong age_threshold; /* age threshold for hot blocks */
+ ulonglong keycache_time; /* total number of block link operations */
+ uint hash_entries; /* max number of entries in the hash table */
+ int hash_links; /* max number of hash links */
+ int hash_links_used; /* number of hash links currently used */
+ int disk_blocks; /* max number of blocks in the cache */
+ ulong blocks_used; /* maximum number of concurrently used blocks */
+ ulong blocks_unused; /* number of currently unused blocks */
+ ulong blocks_changed; /* number of currently dirty blocks */
+ ulong warm_blocks; /* number of blocks in warm sub-chain */
+ ulong cnt_for_resize_op; /* counter to block resize operation */
+ long blocks_available; /* number of blocks available in the LRU chain */
+ HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
+ HASH_LINK *hash_link_root; /* memory for hash table links */
+ HASH_LINK *free_hash_list; /* list of free hash links */
+ BLOCK_LINK *free_block_list; /* list of free blocks */
+ BLOCK_LINK *block_root; /* memory for block links */
+ uchar HUGE_PTR *block_mem; /* memory for block buffers */
+ BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */
+ BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */
+ pthread_mutex_t cache_lock; /* to lock access to the cache structure */
+ KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
+ /*
+ Waiting for a zero resize count. Using a queue for symmetry though
+ only one thread can wait here.
+ */
+ KEYCACHE_WQUEUE waiting_for_resize_cnt;
+ KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */
+ KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
+ BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/
+ BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/
+
+ /* Statistics variables. These are reset in reset_key_cache_counters(). */
+ ulong global_blocks_changed; /* number of currently dirty blocks */
+ ulonglong global_cache_w_requests;/* number of write requests (write hits) */
+ ulonglong global_cache_write; /* number of writes from cache to files */
+ ulonglong global_cache_r_requests;/* number of read requests (read hits) */
+ ulonglong global_cache_read; /* number of reads from files to cache */
+
+ int blocks; /* max number of blocks in the cache */
+ uint hash_factor; /* factor used to calculate hash function */
+ my_bool in_init; /* Set to 1 in MySQL during init/resize */
+} SIMPLE_KEY_CACHE_CB;
/*
Some compilation flags have been added specifically for this module
@@ -223,7 +315,8 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cac
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
-static int flush_all_key_blocks(KEY_CACHE *keycache);
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache);
+static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup);
#ifdef THREAD
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
pthread_mutex_t *mutex);
@@ -232,15 +325,16 @@ static void release_whole_queue(KEYCACHE
#define wait_on_queue(wqueue, mutex) do {} while (0)
#define release_whole_queue(wqueue) do {} while (0)
#endif
-static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block);
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
#if !defined(DBUG_OFF)
-static void test_key_cache(KEY_CACHE *keycache,
+static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
const char *where, my_bool lock);
#endif
-
+#define KEYCACHE_BASE_EXPR(f, pos) \
+ ((ulong) ((pos) / keycache->key_cache_block_size) + (ulong) (f))
#define KEYCACHE_HASH(f, pos) \
-(((ulong) ((pos) / keycache->key_cache_block_size) + \
- (ulong) (f)) & (keycache->hash_entries-1))
+ ((KEYCACHE_BASE_EXPR(f, pos) / keycache->hash_factor) & \
+ (keycache->hash_entries-1))
#define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
#define DEFAULT_KEYCACHE_DEBUG_LOG "keycache_debug.log"
@@ -336,9 +430,10 @@ static int keycache_pthread_cond_signal(
#define inline /* disabled inline for easier debugging */
static int fail_block(BLOCK_LINK *block);
static int fail_hlink(HASH_LINK *hlink);
-static int cache_empty(KEY_CACHE *keycache);
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache);
#endif
+
static inline uint next_power(uint value)
{
return (uint) my_round_up_to_next_power((uint32) value) << 1;
@@ -346,19 +441,32 @@ static inline uint next_power(uint value
/*
- Initialize a key cache
+ Initialize a simple key cache
SYNOPSIS
- init_key_cache()
- keycache pointer to a key cache data structure
- key_cache_block_size size of blocks to keep cached data
- use_mem total memory to use for the key cache
- division_limit division limit (may be zero)
- age_threshold age threshold (may be zero)
+ init_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem memory to use for the key cache buferrs/structures
+ division_limit division limit (may be zero)
+ age_threshold age threshold (may be zero)
+
+ DESCRIPTION
+ This function is the implementation of the init_key_cache interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function builds a simple key cache and initializes the control block
+ structure of the type SIMPLE_KEY_CACHE_CB that is used for this key cache.
+ The parameter keycache is supposed to point to this structure.
+ The parameter key_cache_block_size specifies the size of the blocks in
+ the key cache to be built. The parameters division_limit and age_threshhold
+ determine the initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for key cache blocks
+ and auxiliary structures.
RETURN VALUE
number of blocks in the key cache, if successful,
- 0 - otherwise.
+ <= 0 - otherwise.
NOTES.
if keycache->key_cache_inited != 0 we assume that the key cache
@@ -367,17 +475,17 @@ static inline uint next_power(uint value
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
*/
-int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+static
+int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
ulong blocks, hash_links;
size_t length;
int error;
- DBUG_ENTER("init_key_cache");
+ DBUG_ENTER("init_simple_key_cache");
DBUG_ASSERT(key_cache_block_size >= 512);
KEYCACHE_DEBUG_OPEN;
@@ -387,12 +495,15 @@ int init_key_cache(KEY_CACHE *keycache,
DBUG_RETURN(0);
}
+ keycache->blocks_used= keycache->blocks_unused= 0;
+ keycache->global_blocks_changed= 0;
keycache->global_cache_w_requests= keycache->global_cache_r_requests= 0;
keycache->global_cache_read= keycache->global_cache_write= 0;
keycache->disk_blocks= -1;
if (! keycache->key_cache_inited)
{
keycache->key_cache_inited= 1;
+ keycache->hash_factor= 1;
/*
Initialize these variables once only.
Their value must survive re-initialization during resizing.
@@ -534,51 +645,42 @@ err:
/*
- Resize a key cache
+ Prepare for resizing a simple key cache
SYNOPSIS
- resize_key_cache()
- keycache pointer to a key cache data structure
- key_cache_block_size size of blocks to keep cached data
- use_mem total memory to use for the new key cache
- division_limit new division limit (if not zero)
- age_threshold new age threshold (if not zero)
-
- RETURN VALUE
- number of blocks in the key cache, if successful,
- 0 - otherwise.
+ prepare_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ with_resize_queue <=> resize queue is used
+ release_lock <=> release the key cache lock before return
- NOTES.
- The function first compares the memory size and the block size parameters
- with the key cache values.
+ DESCRIPTION
+ This function flushes all dirty pages from a simple key cache and after
+ this it destroys the key cache calling end_simple_key_cache. The function
+ takes the parameter keycache as a pointer to the control block
+ structure of the type SIMPLE_KEY_CACHE_CB for this key cache.
+ The parameter with_resize_queue determines weather the resize queue is
+ involved (MySQL server never uses this queue). The parameter release_lock
+ says weather the key cache lock must be released before return from
+ the function.
- If they differ the function free the the memory allocated for the
- old key cache blocks by calling the end_key_cache function and
- then rebuilds the key cache with new blocks by calling
- init_key_cache.
+ RETURN VALUE
+ 0 - on success,
+ 1 - otherwise.
- The function starts the operation only when all other threads
- performing operations with the key cache let her to proceed
- (when cnt_for_resize=0).
+ NOTES
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
*/
-int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+static
+int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool release_lock)
{
- int blocks;
- DBUG_ENTER("resize_key_cache");
-
- if (!keycache->key_cache_inited)
- DBUG_RETURN(keycache->disk_blocks);
-
- if(key_cache_block_size == keycache->key_cache_block_size &&
- use_mem == keycache->key_cache_mem_size)
- {
- change_key_cache_param(keycache, division_limit, age_threshold);
- DBUG_RETURN(keycache->disk_blocks);
- }
-
+ int res= 0;
+ DBUG_ENTER("prepare_resize_simple_key_cache");
+
keycache_pthread_mutex_lock(&keycache->cache_lock);
#ifdef THREAD
@@ -588,7 +690,7 @@ int resize_key_cache(KEY_CACHE *keycache
one resizer only. In set_var.cc keycache->in_init is used to block
multiple attempts.
*/
- while (keycache->in_resize)
+ while (with_resize_queue && keycache->in_resize)
{
/* purecov: begin inspected */
wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
@@ -613,8 +715,8 @@ int resize_key_cache(KEY_CACHE *keycache
{
/* TODO: if this happens, we should write a warning in the log file ! */
keycache->resize_in_flush= 0;
- blocks= 0;
keycache->can_be_used= 0;
+ res= 1;
goto finish;
}
DBUG_ASSERT(cache_empty(keycache));
@@ -640,29 +742,144 @@ int resize_key_cache(KEY_CACHE *keycache
#else
KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0);
#endif
-
- /*
- Free old cache structures, allocate new structures, and initialize
- them. Note that the cache_lock mutex and the resize_queue are left
- untouched. We do not lose the cache_lock and will release it only at
- the end of this function.
- */
- end_key_cache(keycache, 0); /* Don't free mutex */
- /* The following will work even if use_mem is 0 */
- blocks= init_key_cache(keycache, key_cache_block_size, use_mem,
- division_limit, age_threshold);
+
+ end_simple_key_cache(keycache, 0);
finish:
+ if (release_lock)
+ keycache_pthread_mutex_unlock(&keycache->cache_lock);
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Finalize resizing a simple key cache
+
+ SYNOPSIS
+ finish_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ with_resize_queue <=> resize queue is used
+ acquire_lock <=> acquire the key cache lock at start
+
+ DESCRIPTION
+ This function performs finalizing actions for the operation of
+ resizing a simple key cache. The function takes the parameter
+ keycache as a pointer to the control block structure of the type
+ SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
+ in_resize in this structure to FALSE.
+ The parameter with_resize_queue determines weather the resize queue
+ is involved (MySQL server never uses this queue).
+ The parameter acquire_lock says weather the key cache lock must be
+ acquired at the start of the function.
+
+ RETURN VALUE
+ none
+
+ NOTES
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
+*/
+
+static
+void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool acquire_lock)
+{
+ DBUG_ENTER("finish_resize_simple_key_cache");
+
+ if (acquire_lock)
+ keycache_pthread_mutex_lock(&keycache->cache_lock);
+
+ safe_mutex_assert_owner(&keycache->cache_lock);
+
/*
Mark the resize finished. This allows other threads to start a
resize or to request new cache blocks.
*/
keycache->in_resize= 0;
-
- /* Signal waiting threads. */
- release_whole_queue(&keycache->resize_queue);
+
+ if (with_resize_queue)
+ {
+ /* Signal waiting threads. */
+ release_whole_queue(&keycache->resize_queue);
+ }
keycache_pthread_mutex_unlock(&keycache->cache_lock);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Resize a simple key cache
+
+ SYNOPSIS
+ resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem memory to use for the key cache buffers/structures
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the resize_key_cache interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
+ cache to be resized.
+ The parameter key_cache_block_size specifies the new size of the blocks in
+ the key cache. The parameters division_limit and age_threshold
+ determine the new initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for key cache blocks
+ and auxiliary structures in the new key cache.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES.
+ The function first calls the function prepare_resize_simple_key_cache
+ to flush all dirty blocks from key cache, to free memory used
+ for key cache blocks and auxiliary structures. After this the
+ function builds a new key cache with new parameters.
+
+ This implementation doesn't block the calls and executions of other
+ functions from the key cache interface. However it assumes that the
+ calls of resize_simple_key_cache itself are serialized.
+
+ The function starts the operation only when all other threads
+ performing operations with the key cache let her to proceed
+ (when cnt_for_resize=0).
+*/
+
+static
+int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
+{
+ int blocks= 0;
+ DBUG_ENTER("resize_simple_key_cache");
+
+ if (!keycache->key_cache_inited)
+ DBUG_RETURN(blocks);
+
+ /*
+ Note that the cache_lock mutex and the resize_queue are left untouched.
+ We do not lose the cache_lock and will release it only at the end of
+ this function.
+ */
+ if (prepare_resize_simple_key_cache(keycache, 1, 0))
+ goto finish;
+
+ /* The following will work even if use_mem is 0 */
+ blocks= init_simple_key_cache(keycache, key_cache_block_size, use_mem,
+ division_limit, age_threshold);
+
+finish:
+ finish_resize_simple_key_cache(keycache, 1, 0);
+
DBUG_RETURN(blocks);
}
@@ -670,7 +887,7 @@ finish:
/*
Increment counter blocking resize key cache operation
*/
-static inline void inc_counter_for_resize_op(KEY_CACHE *keycache)
+static inline void inc_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
keycache->cnt_for_resize_op++;
}
@@ -680,35 +897,47 @@ static inline void inc_counter_for_resiz
Decrement counter blocking resize key cache operation;
Signal the operation to proceed when counter becomes equal zero
*/
-static inline void dec_counter_for_resize_op(KEY_CACHE *keycache)
+static inline void dec_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
if (!--keycache->cnt_for_resize_op)
release_whole_queue(&keycache->waiting_for_resize_cnt);
}
+
/*
- Change the key cache parameters
+ Change key cache parameters of a simple key cache
SYNOPSIS
- change_key_cache_param()
- keycache pointer to a key cache data structure
- division_limit new division limit (if not zero)
- age_threshold new age threshold (if not zero)
+ change_simple_key_cache_param()
+ keycache pointer to the control block of a simple key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the change_key_cache_param interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
+ cache where new values of the division limit and the age threshold used
+ for midpoint insertion strategy are to be set. The parameters
+ division_limit and age_threshold provide these new values.
RETURN VALUE
none
NOTES.
- Presently the function resets the key cache parameters
- concerning midpoint insertion strategy - division_limit and
- age_threshold.
+ Presently the function resets the key cache parameters concerning
+ midpoint insertion strategy - division_limit and age_threshold.
+ This function changes some parameters of a given key cache without
+ reformatting it. The function does not touch the contents the key
+ cache blocks.
*/
-void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
- uint age_threshold)
+static
+void change_simple_key_cache_param(SIMPLE_KEY_CACHE_CB *keycache, uint division_limit,
+ uint age_threshold)
{
- DBUG_ENTER("change_key_cache_param");
-
+ DBUG_ENTER("change_simple_key_cache_param");
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (division_limit)
keycache->min_warm_blocks= (keycache->disk_blocks *
@@ -722,20 +951,31 @@ void change_key_cache_param(KEY_CACHE *k
/*
- Remove key_cache from memory
+ Destroy a simple key cache
SYNOPSIS
- end_key_cache()
- keycache key cache handle
- cleanup Complete free (Free also mutex for key cache)
+ end_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ cleanup <=> complete free (free also mutex for key cache)
+
+ DESCRIPTION
+ This function is the implementation of the end_key_cache interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
+ cache to be destroyed.
+ The function frees the memory allocated for the key cache blocks and
+ auxiliary structures. If the value of the parameter cleanup is TRUE
+ then even the key cache mutex is freed.
RETURN VALUE
none
*/
-void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
+static
+void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup)
{
- DBUG_ENTER("end_key_cache");
+ DBUG_ENTER("end_simple_key_cache");
DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
if (!keycache->key_cache_inited)
@@ -1026,7 +1266,7 @@ static inline void link_changed(BLOCK_LI
void
*/
-static void link_to_file_list(KEY_CACHE *keycache,
+static void link_to_file_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int file,
my_bool unlink_block)
{
@@ -1067,7 +1307,7 @@ static void link_to_file_list(KEY_CACHE
void
*/
-static void link_to_changed_list(KEY_CACHE *keycache,
+static void link_to_changed_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
@@ -1122,8 +1362,8 @@ static void link_to_changed_list(KEY_CAC
not linked in the LRU ring.
*/
-static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
- my_bool at_end)
+static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block,
+ my_bool hot, my_bool at_end)
{
BLOCK_LINK *ins;
BLOCK_LINK **pins;
@@ -1243,7 +1483,7 @@ static void link_block(KEY_CACHE *keycac
See NOTES for link_block
*/
-static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
+static void unlink_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE));
DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/
@@ -1301,7 +1541,8 @@ static void unlink_block(KEY_CACHE *keyc
RETURN
void
*/
-static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
+static void reg_requests(SIMPLE_KEY_CACHE_CB *keycache,
+ BLOCK_LINK *block, int count)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
DBUG_ASSERT(block->hash_link);
@@ -1344,7 +1585,7 @@ static void reg_requests(KEY_CACHE *keyc
not linked in the LRU ring.
*/
-static void unreg_request(KEY_CACHE *keycache,
+static void unreg_request(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int at_end)
{
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
@@ -1433,7 +1674,7 @@ static void remove_reader(BLOCK_LINK *bl
signals on its termination
*/
-static void wait_for_readers(KEY_CACHE *keycache,
+static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
#ifdef THREAD
@@ -1482,7 +1723,7 @@ static inline void link_hash(HASH_LINK *
Remove a hash link from the hash table
*/
-static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
+static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
{
KEYCACHE_DBUG_PRINT("unlink_hash", ("fd: %u pos_ %lu #requests=%u",
(uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests));
@@ -1538,7 +1779,7 @@ static void unlink_hash(KEY_CACHE *keyca
Get the hash link for a page
*/
-static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
+static HASH_LINK *get_hash_link(SIMPLE_KEY_CACHE_CB *keycache,
int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
@@ -1659,7 +1900,7 @@ restart:
waits until first of this operations links any block back.
*/
-static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
+static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache,
File file, my_off_t filepos,
int init_hits_left,
int wrmode, int *page_st)
@@ -2419,7 +2660,7 @@ restart:
portion is less than read_length, but not less than min_length.
*/
-static void read_block(KEY_CACHE *keycache,
+static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, uint read_length,
uint min_length, my_bool primary)
{
@@ -2507,43 +2748,60 @@ static void read_block(KEY_CACHE *keycac
/*
- Read a block of data from a cached file into a buffer;
+ Read a block of data from a simple key cache into a buffer
SYNOPSIS
- key_cache_read()
- keycache pointer to a key cache data structure
- file handler for the file for the block of data to be read
- filepos position of the block of data in the file
- level determines the weight of the data
- buff buffer to where the data must be placed
- length length of the buffer
- block_length length of the block in the key cache buffer
- return_buffer return pointer to the key cache buffer with the data
+ simple_key_cache_read()
+ keycache pointer to the control block of a simple key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ level determines the weight of the data
+ buff buffer to where the data must be placed
+ length length of the buffer
+ block_length length of the read data from a key cache block
+ return_buffer return pointer to the key cache buffer with the data
+ DESCRIPTION
+ This function is the implementation of the key_cache_read interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache.
+ In a general case the function reads a block of data from the key cache
+ into the buffer buff of the size specified by the parameter length. The
+ beginning of the block of data to be read is specified by the parameters
+ file and filepos. The length of the read data is the same as the length
+ of the buffer. The data is read into the buffer in key_cache_block_size
+ increments. If the next portion of the data is not found in any key cache
+ block, first it is read from file into the key cache.
+ If the parameter return_buffer is not ignored and its value is TRUE, and
+ the data to be read of the specified size block_length can be read from one
+ key cache buffer, then the function returns a pointer to the data in the
+ key cache buffer.
+ The function takse into account parameters block_length and return buffer
+ only in a single-threaded environment.
+ The parameter 'level' is used only by the midpoint insertion strategy
+ when the data or its portion cannot be found in the key cache.
+
RETURN VALUE
- Returns address from where the data is placed if sucessful, 0 - otherwise.
+ Returns address from where the data is placed if successful, 0 - otherwise.
- NOTES.
- The function ensures that a block of data of size length from file
- positioned at filepos is in the buffers for some key cache blocks.
- Then the function either copies the data into the buffer buff, or,
- if return_buffer is TRUE, it just returns the pointer to the key cache
- buffer with the data.
+ NOTES
Filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key_cache_block_size;
*/
-uchar *key_cache_read(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
my_bool locked_and_incremented= FALSE;
int error=0;
uchar *start= buff;
- DBUG_ENTER("key_cache_read");
+ DBUG_ENTER("simple_key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
@@ -2738,28 +2996,47 @@ end:
/*
- Insert a block of file data from a buffer into key cache
+ Insert a block of file data from a buffer into a simple key cache
SYNOPSIS
- key_cache_insert()
- keycache pointer to a key cache data structure
+ simple_key_cache_insert()
+ keycache pointer to the control block of a simple key cache
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
buff buffer to read data from
length length of the data in the buffer
- NOTES
- This is used by MyISAM to move all blocks from a index file to the key
- cache
-
+ DESCRIPTION
+ This function is the implementation of the key_cache_insert interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache.
+ The function writes a block of file data from a buffer into the key cache.
+ The buffer is specified with the parameters buff and length - the pointer
+ to the beginning of the buffer and its size respectively. It's assumed
+ the buffer contains the data from 'file' allocated from the position
+ filepos. The data is copied from the buffer in key_cache_block_size
+ increments.
+ The parameter level is used to set one characteristic for the key buffers
+ loaded with the data from buff. The characteristic is used only by the
+ midpoint insertion strategy.
+
RETURN VALUE
0 if a success, 1 - otherwise.
+
+ NOTES
+ The function is used by MyISAM to move all blocks from a index file to
+ the key cache. It can be performed in parallel with reading the file data
+ from the key buffers by other threads.
+
*/
-int key_cache_insert(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length)
+static
+int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
{
int error= 0;
DBUG_ENTER("key_cache_insert");
@@ -2979,43 +3256,64 @@ int key_cache_insert(KEY_CACHE *keycache
/*
- Write a buffer into a cached file.
+ Write a buffer into a simple key cache
SYNOPSIS
- key_cache_write()
- keycache pointer to a key cache data structure
- file handler for the file to write data to
- filepos position in the file to write data to
- level determines the weight of the data
- buff buffer with the data
- length length of the buffer
- dont_write if is 0 then all dirty pages involved in writing
- should have been flushed from key cache
+ simple_key_cache_write()
+ keycache pointer to the control block of a simple key cache
+ file handler for the file to write data to
+ file_extra maps of key cache partitions containing
+ dirty pages from file
+ filepos position in the file to write data to
+ level determines the weight of the data
+ buff buffer with the data
+ length length of the buffer
+ dont_write if is 0 then all dirty pages involved in writing
+ should have been flushed from key cache
+ DESCRIPTION
+ This function is the implementation of the key_cache_write interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache.
+ In a general case the function copies data from a buffer into the key
+ cache. The buffer is specified with the parameters buff and length -
+ the pointer to the beginning of the buffer and its size respectively.
+ It's assumed the buffer contains the data to be written into 'file'
+ starting from the position filepos. The data is copied from the buffer
+ in key_cache_block_size increments.
+ If the value of the parameter dont_write is FALSE then the function
+ also writes the data into file.
+ The parameter level is used to set one characteristic for the key buffers
+ filled with the data from buff. The characteristic is employed only by
+ the midpoint insertion strategy.
+ The parameter file_extra currently makes sense only for simple key caches
+ that are elements of a partitioned key cache. It provides a pointer to the
+ shared bitmap of the partitions that may contains dirty pages for the file.
+ This bitmap is used to optimize the function
+ flush_partitioned_key_cache_blocks.
+
RETURN VALUE
0 if a success, 1 - otherwise.
- NOTES.
- The function copies the data of size length from buff into buffers
- for key cache blocks that are assigned to contain the portion of
- the file starting with position filepos.
- It ensures that this data is flushed to the file if dont_write is FALSE.
- Filepos must be a multiple of 'block_length', but it doesn't
- have to be a multiple of key_cache_block_size;
-
- dont_write is always TRUE in the server (info->lock_type is never F_UNLCK).
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
*/
-int key_cache_write(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+static
+int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, void *file_extra __attribute__((unused)),
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
my_bool locked_and_incremented= FALSE;
int error=0;
- DBUG_ENTER("key_cache_write");
+ DBUG_ENTER("simple_key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu length: %u block_length: %u"
" key_block_length: %u",
@@ -3330,7 +3628,7 @@ end:
Block must have a request registered on it.
*/
-static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block)
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
KEYCACHE_THREAD_TRACE("free block");
KEYCACHE_DBUG_PRINT("free_block",
@@ -3470,7 +3768,7 @@ static int cmp_sec_link(BLOCK_LINK **a,
free used blocks if requested
*/
-static int flush_cached_blocks(KEY_CACHE *keycache,
+static int flush_cached_blocks(SIMPLE_KEY_CACHE_CB *keycache,
File file, BLOCK_LINK **cache,
BLOCK_LINK **end,
enum flush_type type)
@@ -3514,9 +3812,9 @@ static int flush_cached_blocks(KEY_CACHE
(BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE));
block->status|= BLOCK_IN_FLUSHWRITE;
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- error= my_pwrite(file, block->buffer+block->offset,
+ error= my_pwrite(file, block->buffer + block->offset,
block->length - block->offset,
- block->hash_link->diskpos+ block->offset,
+ block->hash_link->diskpos + block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock);
keycache->global_cache_write++;
@@ -3576,7 +3874,7 @@ static int flush_cached_blocks(KEY_CACHE
/*
- Flush all key blocks for a file to disk, but don't do any mutex locks.
+ Flush all key blocks for a file to disk, but don't do any mutex locks
SYNOPSIS
flush_key_blocks_int()
@@ -3598,7 +3896,7 @@ static int flush_cached_blocks(KEY_CACHE
1 error
*/
-static int flush_key_blocks_int(KEY_CACHE *keycache,
+static int flush_key_blocks_int(SIMPLE_KEY_CACHE_CB *keycache,
File file, enum flush_type type)
{
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
@@ -4040,22 +4338,46 @@ err:
/*
- Flush all blocks for a file to disk
+ Flush all blocks for a file from key buffers of a simple key cache
SYNOPSIS
- flush_key_blocks()
- keycache pointer to a key cache data structure
- file handler for the file to flush to
- flush_type type of the flush
+ flush_simple_key_blocks()
+ keycache pointer to the control block of a simple key cache
+ file handler for the file to flush to
+ file_extra maps of key cache partitions containing
+ dirty pages from file (not used)
+ flush_type type of the flush operation
+ DESCRIPTION
+ This function is the implementation of the flush_key_blocks interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type S_KEY_CACHE_CB for a simple key
+ cache.
+ In a general case the function flushes the data from all dirty key
+ buffers related to the file 'file' into this file. The function does
+ exactly this if the value of the parameter type is FLUSH_KEEP. If the
+ value of this parameter is FLUSH_RELEASE, the function additionally
+ releases the key buffers containing data from 'file' for new usage.
+ If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
+ just releases the key buffers containing data from 'file'.
+ The parameter file_extra currently is not used by this function.
+
RETURN
0 ok
1 error
+
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
*/
-int flush_key_blocks(KEY_CACHE *keycache,
- File file, enum flush_type type)
+static
+int flush_simple_key_cache_blocks(SIMPLE_KEY_CACHE_CB *keycache,
+ File file,
+ void *file_extra __attribute__((unused)),
+ enum flush_type type)
{
int res= 0;
DBUG_ENTER("flush_key_blocks");
@@ -4109,7 +4431,7 @@ int flush_key_blocks(KEY_CACHE *keycache
!= 0 Error
*/
-static int flush_all_key_blocks(KEY_CACHE *keycache)
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache)
{
BLOCK_LINK *block;
uint total_found;
@@ -4212,37 +4534,43 @@ static int flush_all_key_blocks(KEY_CACH
/*
- Reset the counters of a key cache.
+ Reset the counters of a simple key cache
SYNOPSIS
- reset_key_cache_counters()
- name the name of a key cache
- key_cache pointer to the key kache to be reset
+ reset_simple_key_cache_counters()
+ name the name of a key cache
+ keycache pointer to the control block of a simple key cache
DESCRIPTION
- This procedure is used by process_key_caches() to reset the counters of all
- currently used key caches, both the default one and the named ones.
+ This function is the implementation of the reset_key_cache_counters
+ interface function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type S_KEY_CACHE_CB for a simple key cache.
+ This function resets the values of all statistical counters for the key
+ cache to 0.
+ The parameter name is currently not used.
RETURN
0 on success (always because it can't fail)
*/
-int reset_key_cache_counters(const char *name __attribute__((unused)),
- KEY_CACHE *key_cache)
+static
+int reset_simple_key_cache_counters(const char *name __attribute__((unused)),
+ SIMPLE_KEY_CACHE_CB *keycache)
{
- DBUG_ENTER("reset_key_cache_counters");
- if (!key_cache->key_cache_inited)
+ DBUG_ENTER("reset_simple_key_cache_counters");
+ if (!keycache->key_cache_inited)
{
DBUG_PRINT("info", ("Key cache %s not initialized.", name));
DBUG_RETURN(0);
}
DBUG_PRINT("info", ("Resetting counters for key cache %s.", name));
- key_cache->global_blocks_changed= 0; /* Key_blocks_not_flushed */
- key_cache->global_cache_r_requests= 0; /* Key_read_requests */
- key_cache->global_cache_read= 0; /* Key_reads */
- key_cache->global_cache_w_requests= 0; /* Key_write_requests */
- key_cache->global_cache_write= 0; /* Key_writes */
+ keycache->global_blocks_changed= 0; /* Key_blocks_not_flushed */
+ keycache->global_cache_r_requests= 0; /* Key_read_requests */
+ keycache->global_cache_read= 0; /* Key_reads */
+ keycache->global_cache_w_requests= 0; /* Key_write_requests */
+ keycache->global_cache_write= 0; /* Key_writes */
DBUG_RETURN(0);
}
@@ -4251,9 +4579,10 @@ int reset_key_cache_counters(const char
/*
Test if disk-cache is ok
*/
-static void test_key_cache(KEY_CACHE *keycache __attribute__((unused)),
- const char *where __attribute__((unused)),
- my_bool lock __attribute__((unused)))
+static
+void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache __attribute__((unused)),
+ const char *where __attribute__((unused)),
+ my_bool lock __attribute__((unused)))
{
/* TODO */
}
@@ -4265,7 +4594,7 @@ static void test_key_cache(KEY_CACHE *ke
#define MAX_QUEUE_LEN 100
-static void keycache_dump(KEY_CACHE *keycache)
+static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache)
{
FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
struct st_my_thread_var *last;
@@ -4505,7 +4834,7 @@ static int fail_hlink(HASH_LINK *hlink)
return 0; /* Let the assert fail. */
}
-static int cache_empty(KEY_CACHE *keycache)
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache)
{
int errcnt= 0;
int idx;
@@ -4543,3 +4872,1702 @@ static int cache_empty(KEY_CACHE *keycac
}
#endif
+
+/*
+ Get statistics for a simple key cache
+
+ SYNOPSIS
+ get_simple_key_cache_statistics()
+ keycache pointer to the control block of a simple key cache
+ partition_no partition number (not used)
+ key_cache_stats OUT pointer to the structure for the returned statistics
+
+ DESCRIPTION
+ This function is the implementation of the get_key_cache_statistics
+ interface function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the statistical data for the key cache.
+ The parameter partition_no is not used by this function.
+
+ RETURN
+ none
+*/
+
+static
+void get_simple_key_cache_statistics(SIMPLE_KEY_CACHE_CB *keycache,
+ uint partition_no __attribute__((unused)),
+ KEY_CACHE_STATISTICS *keycache_stats)
+{
+ DBUG_ENTER("simple_get_key_cache_statistics");
+
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ keycache_stats->blocks_used= keycache->blocks_used;
+ keycache_stats->blocks_unused= keycache->blocks_unused;
+ keycache_stats->blocks_changed= keycache->global_blocks_changed;
+ keycache_stats->read_requests= keycache->global_cache_r_requests;
+ keycache_stats->reads= keycache->global_cache_read;
+ keycache_stats->write_requests= keycache->global_cache_w_requests;
+ keycache_stats->writes= keycache->global_cache_write;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Offsets of the statistical values in the control block for a simple key cache
+ The first NO_LONG_KEY_CACHE_STAT_VARIABLES=3 are of the ulong type while the
+ remaining are of the ulonglong type.
+ */
+static size_t simple_key_cache_stat_var_offsets[]=
+{
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_used),
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_unused),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_blocks_changed),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_w_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_write),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_r_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_read)
+};
+
+
+/*
+ Get the value of a statistical variable for a simple key cache
+
+ SYNOPSIS
+ get_simple_key_cache_stat_value()
+ keycache pointer to the control block of a simple key cache
+ var_no the ordered number of a statistical variable
+
+ DESCRIPTION
+ This function is the implementation of the get_simple_key_cache_stat_value
+ interface function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the value of the statistical variable var_no
+ for this key cache. The variables are numbered starting from 0 to 6.
+
+ RETURN
+ The value of the specified statistical variable
+
+*/
+
+static
+ulonglong get_simple_key_cache_stat_value(SIMPLE_KEY_CACHE_CB *keycache,
+ uint var_no)
+{
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
+ ulonglong res= 0;
+ DBUG_ENTER("get_simple_key_cache_stat_value");
+
+ if (var_no < 3)
+ res= (ulonglong) (*(long *) ((char *) keycache + var_ofs));
+ else
+ res= *(ulonglong *) ((char *) keycache + var_ofs);
+
+ DBUG_RETURN(res);
+}
+
+
+/*
+ The array of pointer to the key cache interface functions used for simple
+ key caches. Any simple key cache objects including those incorporated into
+ partitioned keys caches exploit this array.
+
+ The current implementation of these functions allows to call them from
+ the MySQL server code directly. We don't do it though.
+*/
+
+static KEY_CACHE_FUNCS simple_key_cache_funcs =
+{
+ (INIT_KEY_CACHE) init_simple_key_cache,
+ (RESIZE_KEY_CACHE) resize_simple_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_simple_key_cache_param,
+ (KEY_CACHE_READ) simple_key_cache_read,
+ (KEY_CACHE_INSERT) simple_key_cache_insert,
+ (KEY_CACHE_WRITE) simple_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_simple_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_simple_key_cache_counters,
+ (END_KEY_CACHE) end_simple_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_simple_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_simple_key_cache_stat_value
+};
+
+
+/******************************************************************************
+ Partitioned Key Cache Module
+
+ The module contains implementations of all key cache interface functions
+ employed by partitioned key caches.
+
+ A partitioned key cache is a collection of structures for simple key caches
+ called key cache partitions. Any page from a file can be placed into a buffer
+ of only one partition. The number of the partition is calculated from
+ the file number and the position of the page in the file, and it's always the
+ same for the page. The function that maps pages into partitions takes care
+ of even distribution of pages among partitions.
+
+ Partition key cache mitigate one of the major problem of simple key cache:
+ thread contention for key cache lock (mutex). Every call of a key cache
+ interface function must acquire this lock. So threads compete for this lock
+ even in the case when they have acquired shared locks for the file and
+ pages they want read from are in the key cache buffers.
+ When working with a partitioned key cache any key cache interface function
+ that needs only one page has to acquire the key cache lock only for the
+ partition the page is ascribed to. This makes the chances for threads not
+ compete for the same key cache lock better. Unfortunately if we use a
+ partitioned key cache with N partitions for B-tree indexes we can't say
+ that the chances becomes N times less. The fact is that any index lookup
+ operation requires reading from the root page that, for any index, is always
+ ascribed to the same partition. To resolve this problem we should have
+ employed more sophisticated mechanisms of working with root pages.
+
+ Currently the number of partitions in a partitioned key cache is limited
+ by 64. We could increase this limit. Simultaneously we would have to increase
+ accordingly the size of the bitmap dirty_part_map from the MYISAM_SHARE
+ structure.
+
+******************************************************************************/
+
+/* Control block for a partitioned key cache */
+
+typedef struct st_partitioned_key_cache_cb
+{
+ my_bool key_cache_inited; /*<=> control block is allocated */
+ SIMPLE_KEY_CACHE_CB **partition_array; /* the key cache partitions */
+ size_t key_cache_mem_size; /* specified size of the cache memory */
+ uint key_cache_block_size; /* size of the page buffer of a cache block */
+ uint partitions; /* number of partitions in the key cache */
+} PARTITIONED_KEY_CACHE_CB;
+
+static
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup);
+
+static int
+reset_partitioned_key_cache_counters(const char *name,
+ PARTITIONED_KEY_CACHE_CB *keycache);
+
+/*
+ Determine the partition to which the index block to read is ascribed
+
+ SYNOPSIS
+ get_key_cache_partition()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+
+ DESCRIPTION
+ The function determines the number of the partition in whose buffer the
+ block from 'file' at the position filepos has to be placed for reading.
+ The function returns the control block of the simple key cache for this
+ partition to the caller.
+
+ RETURN VALUE
+ The pointer to the control block of the partition to which the specified
+ file block is ascribed.
+*/
+
+static
+SIMPLE_KEY_CACHE_CB *
+get_key_cache_partition(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos)
+{
+ uint i= KEYCACHE_BASE_EXPR(file, filepos) % keycache->partitions;
+ return keycache->partition_array[i];
+}
+
+
+/*
+ Determine the partition to which the index block to write is ascribed
+
+ SYNOPSIS
+ get_key_cache_partition()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ dirty_part_map pointer to the bitmap of dirty partitions for the file
+
+ DESCRIPTION
+ The function determines the number of the partition in whose buffer the
+ block from 'file' at the position filepos has to be placed for writing and
+ marks the partition as dirty in the dirty_part_map bitmap.
+ The function returns the control block of the simple key cache for this
+ partition to the caller.
+
+ RETURN VALUE
+ The pointer to the control block of the partition to which the specified
+ file block is ascribed.
+*/
+
+static SIMPLE_KEY_CACHE_CB
+*get_key_cache_partition_for_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos,
+ ulonglong* dirty_part_map)
+{
+ uint i= KEYCACHE_BASE_EXPR( file, filepos) % keycache->partitions;
+ *dirty_part_map|= 1<<i;
+ return keycache->partition_array[i];
+}
+
+
+/*
+ Initialize a partitioned key cache
+
+ SYNOPSIS
+ init_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for all key cache partitions
+ division_limit division limit (may be zero)
+ age_threshold age threshold (may be zero)
+
+ DESCRIPTION
+ This function is the implementation of the init_key_cache interface function
+ that is employed by partitioned key caches.
+ The function builds and initializes an array of simple key caches, and then
+ initializes the control block structure of the type PARTITIONED_KEY_CACHE_CB
+ that is used for a partitioned key cache. The parameter keycache is
+ supposed to point to this structure. The number of partitions in the
+ partitioned key cache to be built must be passed through the field
+ 'partitions' of this structure. The parameter key_cache_block_size specifies
+ the size of the blocks in the the simple key caches to be built.
+ The parameters division_limit and age_threshold determine the initial
+ values of those characteristics of the simple key caches that are used for
+ midpoint insertion strategy. The parameter use_mem specifies the total
+ amount of memory to be allocated for the key cache blocks in all simple key
+ caches and for all auxiliary structures.
+
+ RETURN VALUE
+ total number of blocks in key cache partitions, if successful,
+ <= 0 - otherwise.
+
+ NOTES
+ If keycache->key_cache_inited != 0 then we assume that the memory for
+ the array of partitions has been already allocated.
+
+ It's assumed that no two threads call this function simultaneously
+ referring to the same key cache handle.
+*/
+
+static
+int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
+{
+ int i;
+ size_t mem_per_cache;
+ size_t mem_decr;
+ int cnt;
+ SIMPLE_KEY_CACHE_CB *partition;
+ SIMPLE_KEY_CACHE_CB **partition_ptr;
+ uint partitions= keycache->partitions;
+ int blocks= 0;
+ DBUG_ENTER("partitioned_init_key_cache");
+
+ keycache->key_cache_block_size = key_cache_block_size;
+
+ if (keycache->key_cache_inited)
+ partition_ptr= keycache->partition_array;
+ else
+ {
+ if(!(partition_ptr=
+ (SIMPLE_KEY_CACHE_CB **) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB *) *
+ partitions, MYF(MY_WME))))
+ DBUG_RETURN(-1);
+ bzero(partition_ptr, sizeof(SIMPLE_KEY_CACHE_CB *) * partitions);
+ keycache->partition_array= partition_ptr;
+ }
+
+ mem_decr= mem_per_cache / 5;
+ mem_per_cache = use_mem / partitions;
+
+ for (i= 0; i < (int) partitions; i++)
+ {
+ my_bool key_cache_inited= keycache->key_cache_inited;
+ if (key_cache_inited)
+ partition= *partition_ptr;
+ else
+ {
+ if (!(partition=
+ (SIMPLE_KEY_CACHE_CB *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(MY_WME))))
+ continue;
+ partition->key_cache_inited= 0;
+ }
+
+ cnt= init_simple_key_cache(partition, key_cache_block_size, mem_per_cache,
+ division_limit, age_threshold);
+ if (cnt <= 0)
+ {
+ end_simple_key_cache(partition, 1);
+ if (!key_cache_inited)
+ {
+ my_free(partition, MYF(0));
+ partition= 0;
+ }
+ if (i == 0 && cnt < 0 || i > 0)
+ {
+ /*
+ Here we have two cases:
+ 1. i == 0 and cnt < 0
+ cnt < 0 => mem_per_cache is not big enough to allocate minimal
+ number of key blocks in the key cache of the partition.
+ Decrease the the number of the partitions by 1 and start again.
+ 2. i > 0
+ There is not enough memory for one of the succeeding partitions.
+ Just skip this partition decreasing the number of partitions in
+ the key cache by one.
+ Do not change the value of mem_per_cache in both cases.
+ */
+ if (key_cache_inited)
+ {
+ my_free(partition, MYF(0));
+ partition= 0;
+ if(key_cache_inited)
+ memmove(partition_ptr, partition_ptr+1,
+ sizeof(partition_ptr)*(partitions-i-1));
+ }
+ if (!--partitions)
+ break;
+ }
+ else
+ {
+ /*
+ We come here when i == 0 && cnt == 0.
+ cnt == 0 => the memory allocator fails to allocate a block of
+ memory of the size mem_per_cache. Decrease the value of
+ mem_per_cache without changing the current number of partitions
+ and start again. Make sure that such a decrease may happen not
+ more than 5 times in total.
+ */
+ if (use_mem <= mem_decr)
+ break;
+ use_mem-= mem_decr;
+ }
+ i--;
+ mem_per_cache= use_mem/partitions;
+ continue;
+ }
+ else
+ {
+ blocks+= cnt;
+ *partition_ptr++= partition;
+ }
+ }
+
+ keycache->partitions= partitions= partition_ptr-keycache->partition_array;
+ keycache->key_cache_mem_size= mem_per_cache * partitions;
+ for (i= 0; i < (int) partitions; i++)
+ keycache->partition_array[i]->hash_factor= partitions;
+
+ keycache->key_cache_inited= 1;
+
+ if (!partitions)
+ blocks= -1;
+
+ DBUG_RETURN(blocks);
+}
+
+
+/*
+ Resize a partitioned key cache
+
+ SYNOPSIS
+ resize_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for the new key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the resize_key_cache interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be resized.
+ The parameter key_cache_block_size specifies the new size of the blocks in
+ the simple key caches that comprise the partitioned key cache.
+ The parameters division_limit and age_threshold determine the new initial
+ values of those characteristics of the simple key cache that are used for
+ midpoint insertion strategy. The parameter use-mem specifies the total
+ amount of memory to be allocated for the key cache blocks in all new
+ simple key caches and for all auxiliary structures.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES.
+ The function first calls prepare_resize_simple_key_cache for each simple
+ key cache effectively flushing all dirty pages from it and destroying
+ the key cache. Then init_partitioned_key_cache is called. This call builds
+ a new array of simple key caches containing the same number of elements
+ as the old one. After this the function calls the function
+ finish_resize_simple_key_cache for each simple key cache from this array.
+
+ This implementation doesn't block the calls and executions of other
+ functions from the key cache interface. However it assumes that the
+ calls of resize_partitioned_key_cache itself are serialized.
+*/
+
+static
+int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ my_bool cleanup= use_mem == 0;
+ int blocks= -1;
+ int err= 0;
+ DBUG_ENTER("partitioned_resize_key_cache");
+ if (cleanup)
+ {
+ end_partitioned_key_cache(keycache, 0);
+ DBUG_RETURN(-1);
+ }
+ for (i= 0; i < partitions; i++)
+ {
+ err|= prepare_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
+ }
+ if (!err)
+ blocks= init_partitioned_key_cache(keycache, key_cache_block_size,
+ use_mem, division_limit, age_threshold);
+ if (blocks > 0)
+ {
+ for (i= 0; i < partitions; i++)
+ {
+ finish_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
+ }
+ }
+ DBUG_RETURN(blocks);
+}
+
+
+/*
+ Change key cache parameters of a partitioned key cache
+
+ SYNOPSIS
+ partitioned_change_key_cache_param()
+ keycache pointer to the control block of a partitioned key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the change_key_cache_param interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the simple
+ key cache where new values of the division limit and the age threshold used
+ for midpoint insertion strategy are to be set. The parameters
+ division_limit and age_threshold provide these new values.
+
+ RETURN VALUE
+ none
+
+ NOTES
+ The function just calls change_simple_key_cache_param for each element from
+ the array of simple caches that comprise the partitioned key cache.
+*/
+
+static
+void change_partitioned_key_cache_param(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint division_limit,
+ uint age_threshold)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("partitioned_change_key_cache_param");
+ for (i= 0; i < partitions; i++)
+ {
+ change_simple_key_cache_param(keycache->partition_array[i], division_limit,
+ age_threshold);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Destroy a partitioned key cache
+
+ SYNOPSIS
+ end_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
+ cleanup <=> complete free (free also control block structures
+ for all simple key caches)
+
+ DESCRIPTION
+ This function is the implementation of the end_key_cache interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be destroyed.
+ The function frees the memory allocated for the cache blocks and
+ auxiliary structures used by simple key caches that comprise the
+ partitioned key cache. If the value of the parameter cleanup is TRUE
+ then even the memory used for control blocks of the simple key caches
+ and the array of pointers to them are freed.
+
+ RETURN VALUE
+ none
+*/
+
+static
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("partitioned_end_key_cache");
+ DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
+
+ for (i= 0; i < partitions; i++)
+ {
+ end_simple_key_cache(keycache->partition_array[i], cleanup);
+ }
+ if (cleanup)
+ {
+ for (i= 0; i < partitions; i++)
+ my_free((uchar*) keycache->partition_array[i], MYF(0));
+ my_free((uchar*) keycache->partition_array, MYF(0));
+ keycache->key_cache_inited= 0;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Read a block of data from a partitioned key cache into a buffer
+
+ SYNOPSIS
+
+ partitioned_key_cache_read()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ level determines the weight of the data
+ buff buffer to where the data must be placed
+ length length of the buffer
+ block_length length of the read data from a key cache block
+ return_buffer return pointer to the key cache buffer with the data
+
+ DESCRIPTION
+ This function is the implementation of the key_cache_read interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ In a general case the function reads a block of data from the key cache
+ into the buffer buff of the size specified by the parameter length. The
+ beginning of the block of data to be read is specified by the parameters
+ file and filepos. The length of the read data is the same as the length
+ of the buffer. The data is read into the buffer in key_cache_block_size
+ increments. To read each portion the function first finds out in what
+ partition of the key cache this portion(page) is to be saved, and calls
+ simple_key_cache_read with the pointer to the corresponding simple key as
+ its first parameter.
+ If the parameter return_buffer is not ignored and its value is TRUE, and
+ the data to be read of the specified size block_length can be read from one
+ key cache buffer, then the function returns a pointer to the data in the
+ key cache buffer.
+ The function takes into account parameters block_length and return buffer
+ only in a single-threaded environment.
+ The parameter 'level' is used only by the midpoint insertion strategy
+ when the data or its portion cannot be found in the key cache.
+
+ RETURN VALUE
+ Returns address from where the data is placed if successful, 0 - otherwise.
+*/
+
+static
+uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
+{
+ uint r_length;
+ uint offset= (uint) (filepos % keycache->key_cache_block_size);
+ uchar *start= buff;
+ DBUG_ENTER("partitioned_key_cache_read");
+ DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
+ (uint) file, (ulong) filepos, length));
+
+#ifndef THREAD
+ if (block_length > keycache->key_cache_block_size || offset)
+ return_buffer=0;
+#endif
+
+ /* Read data in key_cache_block_size increments */
+ do
+ {
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
+ uchar *ret_buff= 0;
+ r_length= length;
+ set_if_smaller(r_length, keycache->key_cache_block_size - offset);
+ ret_buff= simple_key_cache_read((void *) partition,
+ file, filepos, level,
+ buff, r_length,
+ block_length, return_buffer);
+ if (ret_buff == 0)
+ DBUG_RETURN(0);
+#ifndef THREAD
+ /* This is only true if we were able to read everything in one block */
+ if (return_buffer)
+ DBUG_RETURN(ret_buff);
+#endif
+ filepos+= r_length;
+ buff+= r_length;
+ offset= 0;
+ } while ((length-= r_length));
+
+ DBUG_RETURN(start);
+}
+
+
+/*
+ Insert a block of file data from a buffer into a partitioned key cache
+
+ SYNOPSIS
+ partitioned_key_cache_insert()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file to insert data from
+ filepos position of the block of data in the file to insert
+ level determines the weight of the data
+ buff buffer to read data from
+ length length of the data in the buffer
+
+ DESCRIPTION
+ This function is the implementation of the key_cache_insert interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ The function writes a block of file data from a buffer into the key cache.
+ The buffer is specified with the parameters buff and length - the pointer
+ to the beginning of the buffer and its size respectively. It's assumed
+ that the buffer contains the data from 'file' allocated from the position
+ filepos. The data is copied from the buffer in key_cache_block_size
+ increments. For every portion of data the function finds out in what simple
+ key cache from the array of partitions the data must be stored, and after
+ this calls simple_key_cache_insert to copy the data into a key buffer of
+ this simple key cache.
+ The parameter level is used to set one characteristic for the key buffers
+ loaded with the data from buff. The characteristic is used only by the
+ midpoint insertion strategy.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ The function is used by MyISAM to move all blocks from a index file to
+ the key cache. It can be performed in parallel with reading the file data
+ from the key buffers by other threads.
+*/
+
+static
+int partitioned_key_cache_insert(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
+{
+ uint w_length;
+ uint offset= (uint) (filepos % keycache->key_cache_block_size);
+ DBUG_ENTER("partitioned_key_cache_insert");
+ DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
+ (uint) file,(ulong) filepos, length));
+
+
+ /* Write data in key_cache_block_size increments */
+ do
+ {
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
+ w_length= length;
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset);
+ if (simple_key_cache_insert((void *) partition,
+ file, filepos, level,
+ buff, w_length))
+ DBUG_RETURN(1);
+
+ filepos+= w_length;
+ buff+= w_length;
+ offset = 0;
+ } while ((length-= w_length));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Write data from a buffer into a partitioned key cache
+
+ SYNOPSIS
+
+ partitioned_key_cache_write()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file to write data to
+ filepos position in the file to write data to
+ level determines the weight of the data
+ buff buffer with the data
+ length length of the buffer
+ dont_write if is 0 then all dirty pages involved in writing
+ should have been flushed from key cache
+ file_extra maps of key cache partitions containing
+ dirty pages from file
+
+ DESCRIPTION
+ This function is the implementation of the key_cache_write interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ In a general case the function copies data from a buffer into the key
+ cache. The buffer is specified with the parameters buff and length -
+ the pointer to the beginning of the buffer and its size respectively.
+ It's assumed the buffer contains the data to be written into 'file'
+ starting from the position filepos. The data is copied from the buffer
+ in key_cache_block_size increments. For every portion of data the
+ function finds out in what simple key cache from the array of partitions
+ the data must be stored, and after this calls simple_key_cache_write to
+ copy the data into a key buffer of this simple key cache.
+ If the value of the parameter dont_write is FALSE then the function
+ also writes the data into file.
+ The parameter level is used to set one characteristic for the key buffers
+ filled with the data from buff. The characteristic is employed only by
+ the midpoint insertion strategy.
+ The parameter file_expra provides a pointer to the shared bitmap of
+ the partitions that may contains dirty pages for the file. This bitmap
+ is used to optimize the function flush_partitioned_key_cache_blocks.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
+*/
+
+static
+int partitioned_key_cache_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
+{
+ uint w_length;
+ ulonglong *part_map= (ulonglong *) file_extra;
+ uint offset= (uint) (filepos % keycache->key_cache_block_size);
+ DBUG_ENTER("partitioned_key_cache_write");
+ DBUG_PRINT("enter",
+ ("fd: %u pos: %lu length: %u block_length: %u"
+ " key_block_length: %u",
+ (uint) file, (ulong) filepos, length, block_length,
+ keycache ? keycache->key_cache_block_size : 0));
+
+
+ /* Write data in key_cache_block_size increments */
+ do
+ {
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
+ file,
+ filepos,
+ part_map);
+ w_length = length;
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset );
+ if (simple_key_cache_write(partition,
+ file, 0, filepos, level,
+ buff, w_length, block_length,
+ dont_write))
+ DBUG_RETURN(1);
+
+ filepos+= w_length;
+ buff+= w_length;
+ offset= 0;
+ } while ((length-= w_length));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Flush all blocks for a file from key buffers of a partitioned key cache
+
+ SYNOPSIS
+
+ flush_partitioned_key_cache_blocks()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file to flush to
+ file_extra maps of key cache partitions containing
+ dirty pages from file (not used)
+ flush_type type of the flush operation
+
+ DESCRIPTION
+ This function is the implementation of the flush_key_blocks interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ In a general case the function flushes the data from all dirty key
+ buffers related to the file 'file' into this file. The function does
+ exactly this if the value of the parameter type is FLUSH_KEEP. If the
+ value of this parameter is FLUSH_RELEASE, the function additionally
+ releases the key buffers containing data from 'file' for new usage.
+ If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
+ just releases the key buffers containing data from 'file'.
+ The function performs the operation by calling the function
+ flush_simple_key_cache_blocks for the elements of the array of the
+ simple key caches that comprise the partitioned key_cache. If the value
+ of the parameter type is FLUSH_KEEP s_flush_key_blocks is called only
+ for the partitions with possibly dirty pages marked in the bitmap
+ pointed to by the parameter file_extra.
+
+ RETURN
+ 0 ok
+ 1 error
+
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
+*/
+
+static
+int flush_partitioned_key_cache_blocks(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ enum flush_type type)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ int err= 0;
+ ulonglong *dirty_part_map= (ulonglong *) file_extra;
+ DBUG_ENTER("partitioned_flush_key_blocks");
+ DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
+
+ for (i= 0; i < partitions; i++)
+ {
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ if ((type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) &&
+ !((*dirty_part_map) & ((ulonglong) 1 << i)))
+ continue;
+ err|= test(flush_simple_key_cache_blocks(partition, file, 0, type));
+ }
+ *dirty_part_map= 0;
+
+ DBUG_RETURN(err);
+}
+
+
+/*
+ Reset the counters of a partitioned key cache
+
+ SYNOPSIS
+ reset_partitioned_key_cache_counters()
+ name the name of a key cache
+ keycache pointer to the control block of a partitioned key cache
+
+ DESCRIPTION
+ This function is the implementation of the reset_key_cache_counters
+ interface function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a partitioned
+ key cache.
+ This function resets the values of the statistical counters of the simple
+ key caches comprising partitioned key cache to 0. It does it by calling
+ reset_simple_key_cache_counters for each key cache partition.
+ The parameter name is currently not used.
+
+ RETURN
+ 0 on success (always because it can't fail)
+*/
+
+static int
+reset_partitioned_key_cache_counters(const char *name __attribute__((unused)),
+ PARTITIONED_KEY_CACHE_CB *keycache)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("partitioned_reset_key_cache_counters");
+
+ for (i = 0; i < partitions; i++)
+ {
+ reset_simple_key_cache_counters(name, keycache->partition_array[i]);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Get statistics for a partition key cache
+
+ SYNOPSIS
+ get_partitioned_key_cache_statistics()
+ keycache pointer to the control block of a partitioned key cache
+ partition_no partition number to get statistics for
+ key_cache_stats OUT pointer to the structure for the returned statistics
+
+ DESCRIPTION
+ This function is the implementation of the get_key_cache_statistics
+ interface function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for
+ a partitioned key cache.
+ If the value of the parameter partition_no is equal to 0 then aggregated
+ statistics for all partitions is returned in the fields of the
+ structure key_cache_stat of the type KEY_CACHE_STATISTICS . Otherwise
+ the function returns data for the partition number partition_no of the
+ key cache in the structure key_cache_stat. (Here partitions are numbered
+ starting from 1.)
+
+ RETURN
+ none
+*/
+
+static
+void
+get_partitioned_key_cache_statistics(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint partition_no,
+ KEY_CACHE_STATISTICS *keycache_stats)
+{
+ uint i;
+ SIMPLE_KEY_CACHE_CB *partition;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("get_partitioned_key_cache_statistics");
+
+ if (partition_no != 0)
+ {
+ partition= keycache->partition_array[partition_no-1];
+ get_simple_key_cache_statistics((void *) partition, 0, keycache_stats);
+ DBUG_VOID_RETURN;
+ }
+ bzero(keycache_stats, sizeof(KEY_CACHE_STATISTICS));
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ for (i = 0; i < partitions; i++)
+ {
+ partition= keycache->partition_array[i];
+ keycache_stats->blocks_used+= partition->blocks_used;
+ keycache_stats->blocks_unused+= partition->blocks_unused;
+ keycache_stats->blocks_changed+= partition->global_blocks_changed;
+ keycache_stats->read_requests+= partition->global_cache_r_requests;
+ keycache_stats->reads+= partition->global_cache_read;
+ keycache_stats->write_requests+= partition->global_cache_w_requests;
+ keycache_stats->writes+= partition->global_cache_write;
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Get the value of a statistical variable for a partitioned key cache
+
+ SYNOPSIS
+ get_partitioned_key_cache_stat_value()
+ keycache pointer to the control block of a partitioned key cache
+ var_no the ordered number of a statistical variable
+
+ DESCRIPTION
+ This function is the implementation of the get_key_cache_stat_value
+ interface function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ This function returns the value of the statistical variable var_no
+ for this key cache. The variables are numbered starting from 0 to 6.
+ The returned value is calculated as the sum of the values of the
+ statistical variable with number var_no for all simple key caches that
+ comprise the partitioned key cache.
+
+ RETURN
+ The value of the specified statistical variable
+*/
+
+static
+ulonglong
+get_partitioned_key_cache_stat_value(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint var_no)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
+ ulonglong res= 0;
+ DBUG_ENTER("get_partitioned_key_cache_stat_value");
+
+ if (var_no < NUM_LONG_KEY_CACHE_STAT_VARIABLES)
+ {
+ for (i = 0; i < partitions; i++)
+ {
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ res+= (ulonglong) (*(long *) ((char *) partition + var_ofs));
+ }
+ }
+ else
+ {
+ for (i = 0; i < partitions; i++)
+ {
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ res+= *(ulonglong *) ((char *) partition + var_ofs);
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+/*
+ The array of pointers to the key cache interface functions used by
+ partitioned key caches. Any partitioned key cache object caches exploits
+ this array.
+
+ The current implementation of these functions does not allow to call
+ them from the MySQL server code directly. The key cache interface
+ wrappers must be used for this purpose.
+*/
+
+static KEY_CACHE_FUNCS partitioned_key_cache_funcs =
+{
+ (INIT_KEY_CACHE) init_partitioned_key_cache,
+ (RESIZE_KEY_CACHE) resize_partitioned_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_partitioned_key_cache_param,
+ (KEY_CACHE_READ) partitioned_key_cache_read,
+ (KEY_CACHE_INSERT) partitioned_key_cache_insert,
+ (KEY_CACHE_WRITE) partitioned_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_partitioned_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_partitioned_key_cache_counters,
+ (END_KEY_CACHE) end_partitioned_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_partitioned_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_partitioned_key_cache_stat_value
+};
+
+
+/******************************************************************************
+ Key Cache Interface Module
+
+ The module contains wrappers for all key cache interface functions.
+
+ Currently there are key caches of two types: simple key caches and
+ partitioned key caches. Each type (class) has its own implementation of the
+ basic key cache operations used the MyISAM storage engine. The pointers
+ to the implementation functions are stored in two static structures of the
+ type KEY_CACHE_FUNC: simple_key_cache_funcs - for simple key caches, and
+ partitioned_key_cache_funcs - for partitioned key caches. When a key cache
+ object is created the constructor procedure init_key_cache places a pointer
+ to the corresponding table into one of its fields. The procedure also
+ initializes a control block for the key cache oject and saves the pointer
+ to this block in another field of the key cache object.
+ When a key cache wrapper function is invoked for a key cache object to
+ perform a basic key cache operation it looks into the interface table
+ associated with the key cache oject and calls the corresponding
+ implementation of the operation. It passes the saved key cache control
+ block to this implementation. If, for some reasons, the control block
+ has not been fully initialized yet, the wrapper function either does not
+ do anything or, in the case when it perform a read/write operation, the
+ function do it directly through the system i/o functions.
+
+ As we can see the model with which the key cache interface is supported
+ as quite conventional for interfaces in general.
+
+******************************************************************************/
+
+
+/*
+ Initialize a key cache
+
+ SYNOPSIS
+ init_key_cache()
+ keycache pointer to the key cache to be initialized
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for cache buffers/structures
+ division_limit division limit (may be zero)
+ age_threshold age threshold (may be zero)
+ partitions number of partitions in the key cache
+
+ DESCRIPTION
+ The function creates a control block structure for a key cache and
+ places the pointer to this block in the structure keycache.
+ If the value of the parameter 'partitions' is 0 then a simple key cache
+ is created. Otherwise a partitioned key cache with the specified number
+ of partitions is created.
+ The parameter key_cache_block_size specifies the size of the blocks in
+ the key cache to be created. The parameters division_limit and
+ age_threshold determine the initial values of those characteristics of
+ the key cache that are used for midpoint insertion strategy. The parameter
+ use_mem specifies the total amount of memory to be allocated for the
+ key cache buffers and for all auxiliary structures.
+
+ RETURN VALUE
+ total number of blocks in key cache partitions, if successful,
+ <= 0 - otherwise.
+
+ NOTES
+ if keycache->key_cache_inited != 0 we assume that the memory
+ for the control block of the key cache has been already allocated.
+
+ It's assumed that no two threads call this function simultaneously
+ referring to the same key cache handle.
+*/
+
+int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold, uint partitions)
+{
+ void *keycache_cb;
+ int blocks;
+ if (keycache->key_cache_inited)
+ keycache_cb= keycache->keycache_cb;
+ else
+ {
+ if (partitions == 0)
+ {
+ if (!(keycache_cb= (void *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(0))))
+ return 0;
+ ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ keycache->key_cache_type= SIMPLE_KEY_CACHE;
+ keycache->interface_funcs= &simple_key_cache_funcs;
+ }
+ else
+ {
+ if (!(keycache_cb= (void *) my_malloc(sizeof(PARTITIONED_KEY_CACHE_CB),
+ MYF(0))))
+ return 0;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ keycache->key_cache_type= PARTITIONED_KEY_CACHE;
+ keycache->interface_funcs= &partitioned_key_cache_funcs;
+ }
+ keycache->keycache_cb= keycache_cb;
+ keycache->key_cache_inited= 1;
+ }
+
+ if (partitions != 0)
+ {
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions= partitions;
+ }
+ keycache->can_be_used= 0;
+ blocks= keycache->interface_funcs->init(keycache_cb, key_cache_block_size,
+ use_mem, division_limit,
+ age_threshold);
+ keycache->partitions= partitions ?
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions :
+ 0;
+ DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
+ if (blocks > 0)
+ keycache->can_be_used= 1;
+ return blocks;
+}
+
+
+/*
+ Resize a key cache
+
+ SYNOPSIS
+ resize_key_cache()
+ keycache pointer to the key cache to be resized
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for the new key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ The function operates over the key cache key cache.
+ The parameter key_cache_block_size specifies the new size of the block
+ buffers in the key cache. The parameters division_limit and age_threshold
+ determine the new initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for the key cache
+ buffers and for all auxiliary structures.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES
+ The function does not block the calls and executions of other functions
+ from the key cache interface. However it assumes that the calls of
+ resize_key_cache itself are serialized.
+
+ Currently the function is called when the values of the variables
+ key_buffer_size and/or key_cache_block_size are being reset for
+ the key cache keycache.
+*/
+
+int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold)
+{
+ int blocks= -1;
+ if (keycache->key_cache_inited)
+ {
+ if ((uint) keycache->param_partitions != keycache->partitions && use_mem)
+ blocks= repartition_key_cache(keycache,
+ key_cache_block_size, use_mem,
+ division_limit, age_threshold,
+ (uint) keycache->param_partitions);
+ else
+ {
+ blocks= keycache->interface_funcs->resize(keycache->keycache_cb,
+ key_cache_block_size,
+ use_mem, division_limit,
+ age_threshold);
+
+ if (keycache->partitions)
+ keycache->partitions=
+ ((PARTITIONED_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
+ }
+
+ keycache->can_be_used= (blocks >= 0);
+ }
+ return blocks;
+}
+
+
+/*
+ Change key cache parameters of a key cache
+
+ SYNOPSIS
+ change_key_cache_param()
+ keycache pointer to the key cache to change parameters for
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ The function sets new values of the division limit and the age threshold
+ used when the key cache keycach employs midpoint insertion strategy.
+ The parameters division_limit and age_threshold provide these new values.
+
+ RETURN VALUE
+ none
+
+ NOTES
+ Currently the function is called when the values of the variables
+ key_cache_division_limit and/or key_cache_age_threshold are being reset
+ for the key cache keycache.
+*/
+
+void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
+ uint age_threshold)
+{
+ if (keycache->key_cache_inited)
+ {
+
+ keycache->interface_funcs->change_param(keycache->keycache_cb,
+ division_limit,
+ age_threshold);
+ }
+}
+
+
+/*
+ Destroy a key cache
+
+ SYNOPSIS
+ end_key_cache()
+ keycache pointer to the key cache to be destroyed
+ cleanup <=> complete free
+
+ DESCRIPTION
+ The function frees the memory allocated for the cache blocks and
+ auxiliary structures used by the key cache keycache. If the value
+ of the parameter cleanup is TRUE then all resources used by the key
+ cache are to be freed.
+
+ RETURN VALUE
+ none
+*/
+
+void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
+{
+ if (keycache->key_cache_inited)
+ {
+ keycache->interface_funcs->end(keycache->keycache_cb, cleanup);
+ if (cleanup)
+ {
+ if (keycache->keycache_cb)
+ {
+ my_free((uchar *) keycache->keycache_cb, MYF(0));
+ keycache->keycache_cb= 0;
+ }
+ keycache->key_cache_inited= 0;
+ }
+ keycache->can_be_used= 0;
+ }
+}
+
+
+/*
+ Read a block of data from a key cache into a buffer
+
+ SYNOPSIS
+
+ key_cache_read()
+ keycache pointer to the key cache to read data from
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ level determines the weight of the data
+ buff buffer to where the data must be placed
+ length length of the buffer
+ block_length length of the data read from a key cache block
+ return_buffer return pointer to the key cache buffer with the data
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ In a general case the function reads a block of data from the key cache
+ into the buffer buff of the size specified by the parameter length. The
+ beginning of the block of data to be read is specified by the parameters
+ file and filepos. The length of the read data is the same as the length
+ of the buffer.
+ If the parameter return_buffer is not ignored and its value is TRUE, and
+ the data to be read of the specified size block_length can be read from one
+ key cache buffer, then the function returns a pointer to the data in the
+ key cache buffer.
+ The parameter 'level' is used only by the midpoint insertion strategy
+ when the data or its portion cannot be found in the key cache.
+ The function reads data into the buffer directly from file if the control
+ block of the key cache has not been initialized yet.
+
+ RETURN VALUE
+ Returns address from where the data is placed if successful, 0 - otherwise.
+
+ NOTES.
+ Filepos must be a multiple of 'block_length', but it doesn't
+ have to be a multiple of key_cache_block_size;
+*/
+
+uchar *key_cache_read(KEY_CACHE *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int return_buffer)
+{
+ if (keycache->key_cache_inited && keycache->can_be_used)
+ return keycache->interface_funcs->read(keycache->keycache_cb,
+ file, filepos, level,
+ buff, length,
+ block_length, return_buffer);
+
+ /* We can't use mutex here as the key cache may not be initialized */
+ keycache->global_cache_r_requests++;
+ keycache->global_cache_read++;
+
+ if (my_pread(file, (uchar*) buff, length, filepos, MYF(MY_NABP)))
+ return (uchar *) 0;
+
+ return buff;
+}
+
+
+/*
+ Insert a block of file data from a buffer into a key cache
+
+ SYNOPSIS
+ key_cache_insert()
+ keycache pointer to the key cache to insert data into
+ file handler for the file to insert data from
+ filepos position of the block of data in the file to insert
+ level determines the weight of the data
+ buff buffer to read data from
+ length length of the data in the buffer
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ The function writes a block of file data from a buffer into the key cache.
+ The buffer is specified with the parameters buff and length - the pointer
+ to the beginning of the buffer and its size respectively. It's assumed
+ that the buffer contains the data from 'file' allocated from the position
+ filepos.
+ The parameter level is used to set one characteristic for the key buffers
+ loaded with the data from buff. The characteristic is used only by the
+ midpoint insertion strategy.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ The function is used by MyISAM to move all blocks from a index file to
+ the key cache.
+ It is assumed that it may be performed in parallel with reading the file
+ data from the key buffers by other threads.
+*/
+
+int key_cache_insert(KEY_CACHE *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
+{
+ if (keycache->key_cache_inited && keycache->can_be_used)
+ return keycache->interface_funcs->insert(keycache->keycache_cb,
+ file, filepos, level,
+ buff, length);
+ return 0;
+}
+
+
+/*
+ Write data from a buffer into a key cache
+
+ SYNOPSIS
+
+ key_cache_write()
+ keycache pointer to the key cache to write data to
+ file handler for the file to write data to
+ filepos position in the file to write data to
+ level determines the weight of the data
+ buff buffer with the data
+ length length of the buffer
+ dont_write if is 0 then all dirty pages involved in writing
+ should have been flushed from key cache
+ file_extra pointer to optional file attributes
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ In a general case the function writes data from a buffer into the key
+ cache. The buffer is specified with the parameters buff and length -
+ the pointer to the beginning of the buffer and its size respectively.
+ It's assumed the buffer contains the data to be written into 'file'
+ starting from the position filepos.
+ If the value of the parameter dont_write is FALSE then the function
+ also writes the data into file.
+ The parameter level is used to set one characteristic for the key buffers
+ filled with the data from buff. The characteristic is employed only by
+ the midpoint insertion strategy.
+ The parameter file_expra may point to additional file attributes used
+ for optimization or other purposes.
+ The function writes data from the buffer directly into file if the control
+ block of the key cache has not been initialized yet.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ This implementation may exploit the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
+*/
+
+int key_cache_write(KEY_CACHE *keycache,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int force_write)
+{
+ if (keycache->key_cache_inited && keycache->can_be_used)
+ return keycache->interface_funcs->write(keycache->keycache_cb,
+ file, file_extra,
+ filepos, level,
+ buff, length,
+ block_length, force_write);
+
+ /* We can't use mutex here as the key cache may not be initialized */
+ keycache->global_cache_w_requests++;
+ keycache->global_cache_write++;
+ if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL)))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+ Flush all blocks for a file from key buffers of a key cache
+
+ SYNOPSIS
+
+ flush_key_blocks()
+ keycache pointer to the key cache whose blocks are to be flushed
+ file handler for the file to flush to
+ file_extra maps of key cache (used for partitioned key caches)
+ flush_type type of the flush operation
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ In a general case the function flushes the data from all dirty key
+ buffers related to the file 'file' into this file. The function does
+ exactly this if the value of the parameter type is FLUSH_KEEP. If the
+ value of this parameter is FLUSH_RELEASE, the function additionally
+ releases the key buffers containing data from 'file' for new usage.
+ If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
+ just releases the key buffers containing data from 'file'.
+ If the value of the parameter type is FLUSH_KEEP the function may use
+ the value of the parameter file_extra pointing to possibly dirty
+ partitions to optimize the operation for partitioned key caches.
+
+ RETURN
+ 0 ok
+ 1 error
+
+ NOTES
+ Any implementation of the function may exploit the fact that the function
+ is called only when a thread has got an exclusive lock for the key file.
+*/
+
+int flush_key_blocks(KEY_CACHE *keycache,
+ int file, void *file_extra,
+ enum flush_type type)
+{
+ if (keycache->key_cache_inited)
+ return keycache->interface_funcs->flush(keycache->keycache_cb,
+ file, file_extra, type);
+ return 0;
+}
+
+
+/*
+ Reset the counters of a key cache
+
+ SYNOPSIS
+ reset_key_cache_counters()
+ name the name of a key cache (unused)
+ keycache pointer to the key cache for which to reset counters
+
+ DESCRIPTION
+ This function resets the values of the statistical counters for the key
+ cache keycache.
+ The parameter name is currently not used.
+
+ RETURN
+ 0 on success (always because it can't fail)
+
+ NOTES
+ This procedure is used by process_key_caches() to reset the counters of all
+ currently used key caches, both the default one and the named ones.
+*/
+
+int reset_key_cache_counters(const char *name __attribute__((unused)),
+ KEY_CACHE *keycache)
+{
+ if (keycache->key_cache_inited)
+ {
+
+ return keycache->interface_funcs->reset_counters(name,
+ keycache->keycache_cb);
+ }
+ return 0;
+}
+
+
+/*
+ Get statistics for a key cache
+
+ SYNOPSIS
+ get_key_cache_statistics()
+ keycache pointer to the key cache to get statistics for
+ partition_no partition number to get statistics for
+ key_cache_stats OUT pointer to the structure for the returned statistics
+
+ DESCRIPTION
+ If the value of the parameter partition_no is equal to 0 then statistics
+ for the whole key cache keycache (aggregated statistics) is returned in the
+ fields of the structure key_cache_stat of the type KEY_CACHE_STATISTICS.
+ Otherwise the value of the parameter partition_no makes sense only for
+ a partitioned key cache. In this case the function returns statistics
+ for the partition with the specified number partition_no.
+
+ RETURN
+ none
+*/
+
+void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats)
+{
+ if (keycache->key_cache_inited)
+ {
+ keycache->interface_funcs->get_stats(keycache->keycache_cb,
+ partition_no, key_cache_stats);
+ }
+}
+
+
+/*
+ Get the value of a statistical variable for a key cache
+
+ SYNOPSIS
+ get_key_cache_stat_value()
+ keycache pointer to the key cache to get statistics for
+ var_no the ordered number of a statistical variable
+
+ DESCRIPTION
+ This function returns the value of the statistical variable var_no for
+ the key cache keycache. The variables are numbered starting from 0 to 6.
+
+ RETURN
+ The value of the specified statistical variable.
+
+ NOTES
+ Currently for any key cache the function can return values for the
+ following 7 statistical variables:
+
+ Name Number
+
+ blocks_used 0
+ blocks_unused 1
+ blocks_changed 2
+ read_requests 3
+ reads 4
+ write_requests 5
+ writes 6
+*/
+
+ulonglong get_key_cache_stat_value(KEY_CACHE *keycache, uint var_no)
+{
+ if (keycache->key_cache_inited)
+ {
+ return keycache->interface_funcs->get_stat_val(keycache->keycache_cb,
+ var_no);
+ }
+ else
+ return 0;
+}
+
+
+/*
+ Repartition a key cache
+
+ SYNOPSIS
+ repartition_key_cache()
+ keycache pointer to the key cache to be repartitioned
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for the new key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+ partitions new number of partitions in the key cache
+
+ DESCRIPTION
+ The function operates over the key cache keycache.
+ The parameter partitions specifies the number of partitions in the key
+ cache after repartitioning. If the value of this parameter is 0 then
+ a simple key cache must be created instead of the old one.
+ The parameter key_cache_block_size specifies the new size of the block
+ buffers in the key cache. The parameters division_limit and age_threshold
+ determine the new initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for the new key
+ cache buffers and for all auxiliary structures.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES
+ The function does not block the calls and executions of other functions
+ from the key cache interface. However it assumes that the calls of
+ resize_key_cache itself are serialized.
+
+ Currently the function is called when the value of the variable
+ key_cache_partitions is being reset for the key cache keycache.
+*/
+
+int repartition_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold, uint partitions)
+{
+ uint blocks= -1;
+ if (keycache->key_cache_inited)
+ {
+ keycache->interface_funcs->resize(keycache->keycache_cb,
+ key_cache_block_size, 0,
+ division_limit, age_threshold);
+ end_key_cache(keycache, 1);
+ blocks= init_key_cache(keycache, key_cache_block_size, use_mem,
+ division_limit, age_threshold, partitions);
+ }
+ return blocks;
+}
+
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-04-01 09:04:26 +0000
+++ b/sql/handler.cc 2010-04-03 20:19:35 +0000
@@ -3826,11 +3826,13 @@ int ha_init_key_cache(const char *name,
uint tmp_block_size= (uint) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold;
+ uint partitions= key_cache->param_partitions;
pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(!init_key_cache(key_cache,
tmp_block_size,
tmp_buff_size,
- division_limit, age_threshold));
+ division_limit, age_threshold,
+ partitions));
}
DBUG_RETURN(0);
}
@@ -3860,10 +3862,12 @@ int ha_resize_key_cache(KEY_CACHE *key_c
/**
- Change parameters for key cache (like size)
+ Change parameters for key cache (like division_limit)
*/
int ha_change_key_cache_param(KEY_CACHE *key_cache)
{
+ DBUG_ENTER("ha_change_key_cache_param");
+
if (key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
@@ -3872,9 +3876,35 @@ int ha_change_key_cache_param(KEY_CACHE
pthread_mutex_unlock(&LOCK_global_system_variables);
change_key_cache_param(key_cache, division_limit, age_threshold);
}
- return 0;
+ DBUG_RETURN(0);
}
+
+/**
+ Repartition key cache
+*/
+int ha_repartition_key_cache(KEY_CACHE *key_cache)
+{
+ DBUG_ENTER("ha_repartition_key_cache");
+
+ if (key_cache->key_cache_inited)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
+ long tmp_block_size= (long) key_cache->param_block_size;
+ uint division_limit= key_cache->param_division_limit;
+ uint age_threshold= key_cache->param_age_threshold;
+ uint partitions= key_cache->param_partitions;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ DBUG_RETURN(!repartition_key_cache(key_cache, tmp_block_size,
+ tmp_buff_size,
+ division_limit, age_threshold,
+ partitions));
+ }
+ DBUG_RETURN(0);
+}
+
+
/**
Free memory allocated by a key cache.
*/
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2010-03-25 13:33:39 +0000
+++ b/sql/handler.h 2010-03-29 21:16:12 +0000
@@ -2201,6 +2201,7 @@ int ha_table_exists_in_engine(THD* thd,
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
int ha_resize_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache_param(KEY_CACHE *key_cache);
+int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
int ha_end_key_cache(KEY_CACHE *key_cache);
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-04-02 09:20:09 +0000
+++ b/sql/mysqld.cc 2010-04-03 20:19:35 +0000
@@ -5831,6 +5831,7 @@ enum options_mysqld
OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
+ OPT_KEY_CACHE_PARTITIONS,
OPT_LONG_QUERY_TIME,
OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
@@ -6928,6 +6929,12 @@ log and this option does nothing anymore
(uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
1, 100, 0, 1, 0},
+ {"key_cache_partitions", OPT_KEY_CACHE_PARTITIONS,
+ "The number of partitions in key cache",
+ (uchar**) &dflt_key_cache_var.param_partitions,
+ (uchar**) 0,
+ 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, DEFAULT_KEY_CACHE_PARTITIONS,
+ 0, MAX_KEY_CACHE_PARTITIONS, 0, 1, 0},
{"log-slow-filter", OPT_LOG_SLOW_FILTER,
"Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [admin, filesort, filesort_on_disk, full_join, full_scan, query_cache, query_cache_miss, tmp_table, tmp_table_on_disk]. Sets log-slow-admin-command to ON",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, QPLAN_ALWAYS_SET, 0, 0},
@@ -8910,6 +8917,7 @@ mysql_getopt_value(const char *keyname,
case OPT_KEY_CACHE_BLOCK_SIZE:
case OPT_KEY_CACHE_DIVISION_LIMIT:
case OPT_KEY_CACHE_AGE_THRESHOLD:
+ case OPT_KEY_CACHE_PARTITIONS:
{
KEY_CACHE *key_cache;
if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
@@ -8927,6 +8935,8 @@ mysql_getopt_value(const char *keyname,
return (uchar**) &key_cache->param_division_limit;
case OPT_KEY_CACHE_AGE_THRESHOLD:
return (uchar**) &key_cache->param_age_threshold;
+ case OPT_KEY_CACHE_PARTITIONS:
+ return (uchar**) &key_cache->param_partitions;
}
}
}
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-04-01 09:04:26 +0000
+++ b/sql/set_var.cc 2010-04-03 20:19:35 +0000
@@ -320,15 +320,18 @@ static sys_var_thd_ulong sys_interactive
static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size",
&SV::join_buff_size);
static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size");
-static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size",
- offsetof(KEY_CACHE,
- param_block_size));
-static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit",
- offsetof(KEY_CACHE,
- param_division_limit));
-static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold",
- offsetof(KEY_CACHE,
- param_age_threshold));
+static sys_var_key_cache_long sys_key_cache_block_size(&vars,
+ "key_cache_block_size",
+ offsetof(KEY_CACHE,param_block_size));
+static sys_var_key_cache_long sys_key_cache_division_limit(&vars,
+ "key_cache_division_limit",
+ offsetof(KEY_CACHE, param_division_limit));
+static sys_var_key_cache_long sys_key_cache_age_threshold(&vars,
+ "key_cache_age_threshold",
+ offsetof(KEY_CACHE, param_age_threshold));
+static sys_var_key_cache_long sys_key_cache_partitions(&vars,
+ "key_cache_partitions",
+ offsetof(KEY_CACHE, param_partitions));
static sys_var_const sys_language(&vars, "language",
OPT_GLOBAL, SHOW_CHAR,
(uchar*) language);
@@ -2548,7 +2551,21 @@ bool sys_var_key_cache_long::update(THD
pthread_mutex_unlock(&LOCK_global_system_variables);
- error= (bool) (ha_resize_key_cache(key_cache));
+ switch (offset) {
+
+ case offsetof(KEY_CACHE, param_block_size):
+ error= (bool) (ha_resize_key_cache(key_cache));
+ break;
+
+ case offsetof(KEY_CACHE, param_division_limit):
+ case offsetof(KEY_CACHE, param_age_threshold):
+ error= (bool) (ha_change_key_cache_param(key_cache));
+ break;
+
+ case offsetof(KEY_CACHE, param_partitions):
+ error= (bool) (ha_repartition_key_cache(key_cache));
+ break;
+ }
pthread_mutex_lock(&LOCK_global_system_variables);
key_cache->in_init= 0;
@@ -4156,6 +4173,7 @@ static KEY_CACHE *create_key_cache(const
key_cache->param_block_size= dflt_key_cache_var.param_block_size;
key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold;
+ key_cache->param_partitions= dflt_key_cache_var.param_partitions;
}
}
DBUG_RETURN(key_cache);
=== modified file 'sql/set_var.h'
--- a/sql/set_var.h 2009-12-03 11:19:05 +0000
+++ b/sql/set_var.h 2010-02-16 16:41:11 +0000
@@ -1427,6 +1427,7 @@ public:
my_free((uchar*) name, MYF(0));
}
friend bool process_key_caches(process_key_cache_t func);
+ friend int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond);
friend void delete_elements(I_List<NAMED_LIST> *list,
void (*free_element)(const char*, uchar*));
};
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-04-02 09:20:09 +0000
+++ b/sql/sql_show.cc 2010-04-06 02:08:10 +0000
@@ -2249,6 +2249,32 @@ void remove_status_vars(SHOW_VAR *list)
}
+
+static void update_key_cache_stat_var(KEY_CACHE *key_cache, size_t ofs)
+{
+ uint var_no;
+ switch (ofs) {
+ case offsetof(KEY_CACHE, blocks_used):
+ case offsetof(KEY_CACHE, blocks_unused):
+ case offsetof(KEY_CACHE, global_blocks_changed):
+ var_no= (ofs-offsetof(KEY_CACHE, blocks_used))/sizeof(ulong);
+ *(ulong *)((char *) key_cache + ofs)=
+ (ulong) get_key_cache_stat_value(key_cache, var_no);
+ break;
+ case offsetof(KEY_CACHE, global_cache_r_requests):
+ case offsetof(KEY_CACHE, global_cache_read):
+ case offsetof(KEY_CACHE, global_cache_w_requests):
+ case offsetof(KEY_CACHE, global_cache_write):
+ var_no= NUM_LONG_KEY_CACHE_STAT_VARIABLES +
+ (ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
+ sizeof(ulonglong);
+ *(ulonglong *)((char *) key_cache + ofs)=
+ get_key_cache_stat_value(key_cache, var_no);
+ break;
+ }
+}
+
+
static bool show_status_array(THD *thd, const char *wild,
SHOW_VAR *variables,
enum enum_var_type value_type,
@@ -2381,10 +2407,12 @@ static bool show_status_array(THD *thd,
break;
}
case SHOW_KEY_CACHE_LONG:
+ update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_KEY_CACHE_LONGLONG:
+ update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
@@ -6640,6 +6668,90 @@ int fill_schema_files(THD *thd, TABLE_LI
}
+static
+int store_key_cache_table_record(THD *thd, TABLE *table,
+ const char *name, uint name_length,
+ KEY_CACHE *key_cache,
+ uint partitions, uint partition_no)
+{
+ KEY_CACHE_STATISTICS keycache_stats;
+ uint err;
+ DBUG_ENTER("store_key_cache_table_record");
+
+ get_key_cache_statistics(key_cache, partition_no, &keycache_stats);
+
+ if (!key_cache->key_cache_inited || keycache_stats.mem_size == 0)
+ DBUG_RETURN(0);
+
+ restore_record(table, s->default_values);
+ table->field[0]->store(name, name_length, system_charset_info);
+ if (partitions == 0)
+ table->field[1]->set_null();
+ else
+ {
+ table->field[1]->set_notnull();
+ table->field[1]->store((long) partitions, TRUE);
+ }
+
+ if (partition_no == 0)
+ table->field[2]->set_null();
+ else
+ {
+ table->field[2]->set_notnull();
+ table->field[2]->store((long) partition_no, TRUE);
+ }
+ table->field[3]->store(keycache_stats.mem_size, TRUE);
+ table->field[4]->store(keycache_stats.block_size, TRUE);
+ table->field[5]->store(keycache_stats.blocks_used, TRUE);
+ table->field[6]->store(keycache_stats.blocks_unused, TRUE);
+ table->field[7]->store(keycache_stats.blocks_changed, TRUE);
+ table->field[8]->store(keycache_stats.read_requests, TRUE);
+ table->field[9]->store(keycache_stats.reads, TRUE);
+ table->field[10]->store(keycache_stats.write_requests, TRUE);
+ table->field[11]->store(keycache_stats.writes, TRUE);
+
+ err= schema_table_store_record(thd, table);
+ DBUG_RETURN(err);
+}
+
+
+int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ TABLE *table= tables->table;
+ I_List_iterator<NAMED_LIST> it(key_caches);
+ NAMED_LIST *element;
+ DBUG_ENTER("fill_key_cache_tables");
+
+ while ((element= it++))
+ {
+ KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
+
+ if (!key_cache->key_cache_inited)
+ continue;
+
+ uint partitions= key_cache->partitions;
+ DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
+
+ if (partitions)
+ {
+ for (uint i= 0; i < partitions; i++)
+ {
+ if (store_key_cache_table_record(thd, table,
+ element->name, element->name_length,
+ key_cache, partitions, i+1))
+ DBUG_RETURN(1);
+ }
+ }
+
+ if (store_key_cache_table_record(thd, table,
+ element->name, element->name_length,
+ key_cache, partitions, 0))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
ST_FIELD_INFO schema_fields_info[]=
{
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
@@ -7219,6 +7331,35 @@ ST_FIELD_INFO referential_constraints_fi
};
+ST_FIELD_INFO keycache_fields_info[]=
+{
+ {"KEY_CACHE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
+ {"PARTITIONS", 3, MYSQL_TYPE_LONG, 0,
+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED) , 0, SKIP_OPEN_TABLE},
+ {"PARTITION_NUMBER", 3, MYSQL_TYPE_LONG, 0,
+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
+ {"FULL_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
+ {"BLOCK_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE },
+ {"USED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_blocks_used", SKIP_OPEN_TABLE},
+ {"UNUSED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_blocks_unused", SKIP_OPEN_TABLE},
+ {"DIRTY_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_blocks_not_flushed", SKIP_OPEN_TABLE},
+ {"READ_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_read_requests", SKIP_OPEN_TABLE},
+ {"READS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_reads", SKIP_OPEN_TABLE},
+ {"WRITE_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_write_requests", SKIP_OPEN_TABLE},
+ {"WRITES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_writes", SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+};
+
+
/*
Description of ST_FIELD_INFO in table.h
@@ -7258,6 +7399,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_variables, make_old_format, 0, 0, -1, 0, 0},
{"INDEX_STATISTICS", index_stats_fields_info, create_schema_table,
fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0},
+ {"KEY_CACHES", keycache_fields_info, create_schema_table,
+ fill_key_cache_tables, make_old_format, 0, -1,-1, 0, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
OPEN_TABLE_ONLY},
=== modified file 'sql/sql_test.cc'
--- a/sql/sql_test.cc 2010-03-04 08:03:07 +0000
+++ b/sql/sql_test.cc 2010-03-29 21:16:12 +0000
@@ -445,7 +445,8 @@ static int print_key_cache_status(const
Buffer_size: %10lu\n\
Block_size: %10lu\n\
Division_limit: %10lu\n\
-Age_limit: %10lu\n\
+Age_threshold: %10lu\n\
+Partitions: %10lu\n\
blocks used: %10lu\n\
not flushed: %10lu\n\
w_requests: %10s\n\
@@ -455,6 +456,7 @@ reads: %10s\n\n",
name,
(ulong) key_cache->param_buff_size, key_cache->param_block_size,
key_cache->param_division_limit, key_cache->param_age_threshold,
+ key_cache->param_partitions,
key_cache->blocks_used,key_cache->global_blocks_changed,
llstr(key_cache->global_cache_w_requests,llbuff1),
llstr(key_cache->global_cache_write,llbuff2),
=== modified file 'sql/table.h'
--- a/sql/table.h 2010-02-12 08:47:31 +0000
+++ b/sql/table.h 2010-02-16 16:41:11 +0000
@@ -953,6 +953,7 @@ enum enum_schema_tables
SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES,
SCH_INDEX_STATS,
+ SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARTITIONS,
=== modified file 'storage/myisam/mi_check.c'
--- a/storage/myisam/mi_check.c 2010-01-14 16:51:00 +0000
+++ b/storage/myisam/mi_check.c 2010-02-16 16:41:11 +0000
@@ -332,7 +332,8 @@ int chk_size(HA_CHECK *param, register M
/* The following is needed if called externally (not from myisamchk) */
flush_key_blocks(info->s->key_cache,
- info->s->kfile, FLUSH_FORCE_WRITE);
+ info->s->kfile, &info->s->dirty_part_map,
+ FLUSH_FORCE_WRITE);
size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size)
@@ -1474,6 +1475,7 @@ static int mi_drop_all_indexes(HA_CHECK
*/
DBUG_PRINT("repair", ("all disabled are empty: create missing"));
error= flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
FLUSH_FORCE_WRITE);
goto end;
}
@@ -1488,6 +1490,7 @@ static int mi_drop_all_indexes(HA_CHECK
/* Remove all key blocks of this index file from key cache. */
if ((error= flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
FLUSH_IGNORE_CHANGED)))
goto end; /* purecov: inspected */
@@ -1549,7 +1552,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,
- (size_t) param->use_buffers, 0, 0));
+ (size_t) param->use_buffers, 0, 0, 0));
if (init_io_cache(¶m->read_cache,info->dfile,
(uint) param->read_buffer_length,
@@ -1762,7 +1765,8 @@ err:
VOID(end_io_cache(¶m->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache));
- got_error|=flush_blocks(param, share->key_cache, share->kfile);
+ got_error|=flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
if (!got_error && param->testflag & T_UNPACK)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
@@ -1908,9 +1912,10 @@ void lock_memory(HA_CHECK *param __attri
/* Flush all changed blocks to disk */
-int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file)
+int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
+ ulonglong *dirty_part_map)
{
- if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
+ if (flush_key_blocks(key_cache, file, dirty_part_map, FLUSH_RELEASE))
{
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1);
@@ -1977,7 +1982,8 @@ int mi_sort_index(HA_CHECK *param, regis
}
/* Flush key cache for this file if we are calling this outside myisamchk */
- flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */
@@ -2535,7 +2541,8 @@ int mi_repair_by_sort(HA_CHECK *param, r
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param, share->key_cache, share->kfile);
+ got_error|= flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@@ -3059,7 +3066,8 @@ int mi_repair_parallel(HA_CHECK *param,
memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param, share->key_cache, share->kfile);
+ got_error|= flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
/*
Destroy the write cache. The master thread did already detach from
the share by remove_io_thread() or it was not yet started (if the
=== modified file 'storage/myisam/mi_close.c'
--- a/storage/myisam/mi_close.c 2010-02-10 19:06:24 +0000
+++ b/storage/myisam/mi_close.c 2010-02-16 16:41:11 +0000
@@ -64,6 +64,7 @@ int mi_close(register MI_INFO *info)
if (share->kfile >= 0) abort(););
if (share->kfile >= 0 &&
flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
((share->temporary || share->deleting) ?
FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE)))
=== modified file 'storage/myisam/mi_delete_all.c'
--- a/storage/myisam/mi_delete_all.c 2008-04-28 16:24:05 +0000
+++ b/storage/myisam/mi_delete_all.c 2010-02-16 16:41:11 +0000
@@ -52,7 +52,8 @@ int mi_delete_all_rows(MI_INFO *info)
If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache
*/
- flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_IGNORE_CHANGED);
#ifdef HAVE_MMAP
if (share->file_map)
_mi_unmap_file(info);
=== modified file 'storage/myisam/mi_extra.c'
--- a/storage/myisam/mi_extra.c 2010-02-10 19:06:24 +0000
+++ b/storage/myisam/mi_extra.c 2010-02-16 16:41:11 +0000
@@ -268,6 +268,7 @@ int mi_extra(MI_INFO *info, enum ha_extr
pthread_mutex_lock(&share->intern_lock);
/* Flush pages that we don't need anymore */
if (flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
(function == HA_EXTRA_PREPARE_FOR_DROP ?
FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)))
{
@@ -326,7 +327,8 @@ int mi_extra(MI_INFO *info, enum ha_extr
break;
case HA_EXTRA_FLUSH:
if (!share->temporary)
- flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP);
+ flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_KEEP);
#ifdef HAVE_PWRITE
_mi_decrement_open_count(info);
#endif
=== modified file 'storage/myisam/mi_keycache.c'
--- a/storage/myisam/mi_keycache.c 2008-03-29 15:56:33 +0000
+++ b/storage/myisam/mi_keycache.c 2010-02-16 16:41:11 +0000
@@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info
in the old key cache.
*/
- if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_RELEASE))
{
error= my_errno;
mi_print_error(info->s, HA_ERR_CRASHED);
@@ -90,7 +91,8 @@ int mi_assign_to_key_cache(MI_INFO *info
(This can never fail as there is never any not written data in the
new key cache)
*/
- (void) flush_key_blocks(key_cache, share->kfile, FLUSH_RELEASE);
+ (void) flush_key_blocks(key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_RELEASE);
/*
ensure that setting the key cache and changing the multi_key_cache
@@ -102,6 +104,7 @@ int mi_assign_to_key_cache(MI_INFO *info
This should be seen at the lastes for the next call to an myisam function.
*/
share->key_cache= key_cache;
+ share->dirty_part_map= 0;
/* store the key cache in the global hash structure for future opens */
if (multi_key_cache_set((uchar*) share->unique_file_name,
=== modified file 'storage/myisam/mi_locking.c'
--- a/storage/myisam/mi_locking.c 2009-10-06 06:57:22 +0000
+++ b/storage/myisam/mi_locking.c 2010-02-16 16:41:11 +0000
@@ -68,7 +68,9 @@ int mi_lock_database(MI_INFO *info, int
--share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->key_cache,
- share->kfile,FLUSH_KEEP))
+ share->kfile,
+ &share->dirty_part_map,
+ FLUSH_KEEP))
{
error=my_errno;
mi_print_error(info->s, HA_ERR_CRASHED);
@@ -513,7 +515,8 @@ int _mi_test_if_changed(register MI_INFO
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process)
- VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
+ VOID(flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map, FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;
=== modified file 'storage/myisam/mi_page.c'
--- a/storage/myisam/mi_page.c 2009-05-06 12:03:24 +0000
+++ b/storage/myisam/mi_page.c 2010-02-16 16:41:11 +0000
@@ -94,10 +94,11 @@ int _mi_write_keypage(register MI_INFO *
}
#endif
DBUG_RETURN((key_cache_write(info->s->key_cache,
- info->s->kfile,page, level, (uchar*) buff,length,
- (uint) keyinfo->block_length,
- (int) ((info->lock_type != F_UNLCK) ||
- info->s->delay_key_write))));
+ info->s->kfile, &info->s->dirty_part_map,
+ page, level, (uchar*) buff, length,
+ (uint) keyinfo->block_length,
+ (int) ((info->lock_type != F_UNLCK) ||
+ info->s->delay_key_write))));
} /* mi_write_keypage */
@@ -116,7 +117,8 @@ int _mi_dispose(register MI_INFO *info,
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->key_cache,
- info->s->kfile, pos , level, buff,
+ info->s->kfile, &info->s->dirty_part_map,
+ pos , level, buff,
sizeof(buff),
(uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK)));
=== modified file 'storage/myisam/mi_panic.c'
--- a/storage/myisam/mi_panic.c 2006-12-31 00:32:21 +0000
+++ b/storage/myisam/mi_panic.c 2010-02-16 16:41:11 +0000
@@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
- if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(info->s->key_cache, info->s->kfile,
+ &info->s->dirty_part_map, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
=== modified file 'storage/myisam/mi_preload.c'
--- a/storage/myisam/mi_preload.c 2009-09-09 15:13:13 +0000
+++ b/storage/myisam/mi_preload.c 2010-02-16 16:41:11 +0000
@@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong
}
}
else
- block_length= share->key_cache->key_cache_block_size;
+ block_length= share->key_cache->param_block_size;
length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length);
@@ -73,7 +73,8 @@ int mi_preload(MI_INFO *info, ulonglong
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
- if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_RELEASE))
goto err;
do
=== modified file 'storage/myisam/mi_test1.c'
--- a/storage/myisam/mi_test1.c 2008-04-28 16:24:05 +0000
+++ b/storage/myisam/mi_test1.c 2010-02-16 16:41:11 +0000
@@ -49,7 +49,8 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
if (key_cacheing)
- init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0);
+ init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0,
+ DEFAULT_KEY_CACHE_PARTITIONS);
get_options(argc,argv);
exit(run_test("test1"));
=== modified file 'storage/myisam/mi_test2.c'
--- a/storage/myisam/mi_test2.c 2008-04-28 16:24:05 +0000
+++ b/storage/myisam/mi_test2.c 2010-02-16 16:41:11 +0000
@@ -215,7 +215,8 @@ int main(int argc, char *argv[])
if (!silent)
printf("- Writing key:s\n");
if (key_cacheing)
- init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
+ init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0,
+ DEFAULT_KEY_CACHE_PARTITIONS);
if (do_locking)
mi_lock_database(file,F_WRLCK);
if (write_cacheing)
=== modified file 'storage/myisam/mi_test3.c'
--- a/storage/myisam/mi_test3.c 2010-01-06 21:27:53 +0000
+++ b/storage/myisam/mi_test3.c 2010-02-16 16:41:11 +0000
@@ -177,7 +177,8 @@ void start_test(int id)
exit(1);
}
if (key_cacheing && rnd(2) == 0)
- init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0);
+ init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0,
+ DEFAULT_KEY_CACHE_PARTITIONS);
printf("Process %d, pid: %ld\n", id, (long) getpid());
fflush(stdout);
=== modified file 'storage/myisam/myisam_ftdump.c'
--- a/storage/myisam/myisam_ftdump.c 2009-11-30 13:36:06 +0000
+++ b/storage/myisam/myisam_ftdump.c 2010-02-16 16:41:11 +0000
@@ -83,7 +83,7 @@ int main(int argc,char *argv[])
usage();
}
- init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0);
+ init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0, 0);
if (!(info=mi_open(argv[0], O_RDONLY,
HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))
=== modified file 'storage/myisam/myisamchk.c'
--- a/storage/myisam/myisamchk.c 2009-12-03 11:34:11 +0000
+++ b/storage/myisam/myisamchk.c 2010-02-16 16:41:11 +0000
@@ -1102,7 +1102,7 @@ static int myisamchk(HA_CHECK *param, ch
{
if (param->testflag & (T_EXTEND | T_MEDIUM))
VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size,
- (size_t) param->use_buffers, 0, 0));
+ (size_t) param->use_buffers, 0, 0, 0));
VOID(init_io_cache(¶m->read_cache,datafile,
(uint) param->read_buffer_length,
READ_CACHE,
@@ -1116,7 +1116,8 @@ static int myisamchk(HA_CHECK *param, ch
HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM)))
error|=chk_data_link(param, info, test(param->testflag & T_EXTEND));
- error|=flush_blocks(param, share->key_cache, share->kfile);
+ error|=flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
VOID(end_io_cache(¶m->read_cache));
}
if (!error)
@@ -1526,7 +1527,7 @@ static int mi_sort_records(HA_CHECK *par
DBUG_RETURN(0); /* Nothing to do */
init_key_cache(dflt_key_cache, opt_key_cache_block_size,
- (size_t) param->use_buffers, 0, 0);
+ (size_t) param->use_buffers, 0, 0, 0);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
@@ -1641,8 +1642,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0;
share->state.sortkey=sort_key;
- DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) |
- got_error);
+ DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map) | got_error);
} /* sort_records */
=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h 2010-03-04 08:03:07 +0000
+++ b/storage/myisam/myisamdef.h 2010-03-29 21:16:12 +0000
@@ -174,6 +174,8 @@ typedef struct st_mi_isam_share
*index_file_name;
uchar *file_map; /* mem-map of file if possible */
KEY_CACHE *key_cache; /* ref to the current key cache */
+ /* To mark the key cache partitions containing dirty pages for this file */
+ ulonglong dirty_part_map;
MI_DECODE_TREE *decode_trees;
uint16 *decode_tables;
/* Function to use for a row checksum. */
@@ -732,7 +734,8 @@ void mi_check_print_info _VARARGS((HA_CH
#ifdef THREAD
pthread_handler_t thr_find_all_keys(void *arg);
#endif
-int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file);
+int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
+ ulonglong *dirty_part_map);
#ifdef __cplusplus
}
#endif
=== modified file 'storage/myisam/myisamlog.c'
--- a/storage/myisam/myisamlog.c 2009-11-29 23:08:56 +0000
+++ b/storage/myisam/myisamlog.c 2010-02-16 16:41:11 +0000
@@ -333,7 +333,7 @@ static int examine_log(char * file_name,
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL);
VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
- 0, 0));
+ 0, 0, 0));
files_open=0; access_time=0;
while (access_time++ != number_of_commands &&
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2750)
by Igor Babaev 06 Apr '10
by Igor Babaev 06 Apr '10
06 Apr '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100405202809-beg2cwhelygpbl6i
2750 Igor Babaev 2010-04-05
Post review fixes.
modified:
include/keycache.h
mysql-test/suite/funcs_1/r/is_columns_is.result
mysql-test/suite/funcs_1/r/is_tables_is.result
mysys/mf_keycache.c
sql/sql_show.cc
=== modified file 'include/keycache.h'
--- a/include/keycache.h 2010-04-01 21:42:40 +0000
+++ b/include/keycache.h 2010-04-06 02:08:10 +0000
@@ -52,7 +52,7 @@ typedef struct st_key_cache_statistics
ulonglong writes; /* number of actual writes from buffers into files */
} KEY_CACHE_STATISTICS;
-#define NO_LONG_KEY_CACHE_STAT_VARIABLES 3
+#define NUM_LONG_KEY_CACHE_STAT_VARIABLES 3
/* The type of a key cache object */
typedef enum key_cache_type
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_is.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-04-02 10:03:39 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-04-06 02:08:10 +0000
@@ -230,6 +230,18 @@ NULL information_schema INNODB_TRX trx_s
NULL information_schema INNODB_TRX trx_state 2 NO varchar 13 39 NULL NULL utf8 utf8_general_ci varchar(13) select
NULL information_schema INNODB_TRX trx_wait_started 5 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select
NULL information_schema INNODB_TRX trx_weight 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES KEY_CACHE_NAME 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
+NULL information_schema KEY_CACHES PARTITIONS 2 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
+NULL information_schema KEY_CACHES PARTITION_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
+NULL information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
@@ -743,6 +755,18 @@ NULL information_schema INNODB_TRX trx_w
NULL information_schema INNODB_TRX trx_weight bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema INNODB_TRX trx_mysql_thread_id bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema INNODB_TRX trx_query varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema KEY_CACHES KEY_CACHE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema KEY_CACHES PARTITIONS int NULL NULL NULL NULL int(3) unsigned
+NULL information_schema KEY_CACHES PARTITION_NUMBER int NULL NULL NULL NULL int(3) unsigned
+NULL information_schema KEY_CACHES FULL_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES BLOCK_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES USED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES UNUSED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES DIRTY_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES READ_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES READS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES WRITE_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES WRITES bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
=== modified file 'mysql-test/suite/funcs_1/r/is_tables_is.result'
--- a/mysql-test/suite/funcs_1/r/is_tables_is.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/suite/funcs_1/r/is_tables_is.result 2010-04-06 02:08:10 +0000
@@ -590,6 +590,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME KEY_CACHES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -1688,6 +1711,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME KEY_CACHES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2010-04-03 20:19:35 +0000
+++ b/mysys/mf_keycache.c 2010-04-06 02:08:10 +0000
@@ -5158,6 +5158,7 @@ int init_partitioned_key_cache(PARTITION
{
int i;
size_t mem_per_cache;
+ size_t mem_decr;
int cnt;
SIMPLE_KEY_CACHE_CB *partition;
SIMPLE_KEY_CACHE_CB **partition_ptr;
@@ -5175,9 +5176,11 @@ int init_partitioned_key_cache(PARTITION
(SIMPLE_KEY_CACHE_CB **) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB *) *
partitions, MYF(MY_WME))))
DBUG_RETURN(-1);
+ bzero(partition_ptr, sizeof(SIMPLE_KEY_CACHE_CB *) * partitions);
keycache->partition_array= partition_ptr;
}
+ mem_decr= mem_per_cache / 5;
mem_per_cache = use_mem / partitions;
for (i= 0; i < (int) partitions; i++)
@@ -5194,30 +5197,64 @@ int init_partitioned_key_cache(PARTITION
partition->key_cache_inited= 0;
}
- if ((cnt= init_simple_key_cache(partition,
- key_cache_block_size, mem_per_cache,
- division_limit, age_threshold)) <= 0)
+ cnt= init_simple_key_cache(partition, key_cache_block_size, mem_per_cache,
+ division_limit, age_threshold);
+ if (cnt <= 0)
{
end_simple_key_cache(partition, 1);
- my_free(partition, MYF(0));
- partition= 0;
- if (key_cache_inited)
+ if (!key_cache_inited)
{
- memmove(partition_ptr, partition_ptr+1,
- sizeof(partition_ptr)*(partitions-i-1));
+ my_free(partition, MYF(0));
+ partition= 0;
}
- if (!--partitions)
- break;
- if (i == 0)
+ if (i == 0 && cnt < 0 || i > 0)
{
- i--;
- mem_per_cache = use_mem / partitions;
- continue;
+ /*
+ Here we have two cases:
+ 1. i == 0 and cnt < 0
+ cnt < 0 => mem_per_cache is not big enough to allocate minimal
+ number of key blocks in the key cache of the partition.
+ Decrease the the number of the partitions by 1 and start again.
+ 2. i > 0
+ There is not enough memory for one of the succeeding partitions.
+ Just skip this partition decreasing the number of partitions in
+ the key cache by one.
+ Do not change the value of mem_per_cache in both cases.
+ */
+ if (key_cache_inited)
+ {
+ my_free(partition, MYF(0));
+ partition= 0;
+ if(key_cache_inited)
+ memmove(partition_ptr, partition_ptr+1,
+ sizeof(partition_ptr)*(partitions-i-1));
+ }
+ if (!--partitions)
+ break;
+ }
+ else
+ {
+ /*
+ We come here when i == 0 && cnt == 0.
+ cnt == 0 => the memory allocator fails to allocate a block of
+ memory of the size mem_per_cache. Decrease the value of
+ mem_per_cache without changing the current number of partitions
+ and start again. Make sure that such a decrease may happen not
+ more than 5 times in total.
+ */
+ if (use_mem <= mem_decr)
+ break;
+ use_mem-= mem_decr;
}
+ i--;
+ mem_per_cache= use_mem/partitions;
+ continue;
+ }
+ else
+ {
+ blocks+= cnt;
+ *partition_ptr++= partition;
}
-
- blocks+= cnt;
- *partition_ptr++= partition;
}
keycache->partitions= partitions= partition_ptr-keycache->partition_array;
@@ -5859,7 +5896,7 @@ get_partitioned_key_cache_stat_value(PAR
ulonglong res= 0;
DBUG_ENTER("get_partitioned_key_cache_stat_value");
- if (var_no < NO_LONG_KEY_CACHE_STAT_VARIABLES)
+ if (var_no < NUM_LONG_KEY_CACHE_STAT_VARIABLES)
{
for (i = 0; i < partitions; i++)
{
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-04-03 20:19:35 +0000
+++ b/sql/sql_show.cc 2010-04-06 02:08:10 +0000
@@ -2265,7 +2265,7 @@ static void update_key_cache_stat_var(KE
case offsetof(KEY_CACHE, global_cache_read):
case offsetof(KEY_CACHE, global_cache_w_requests):
case offsetof(KEY_CACHE, global_cache_write):
- var_no= NO_LONG_KEY_CACHE_STAT_VARIABLES +
+ var_no= NUM_LONG_KEY_CACHE_STAT_VARIABLES +
(ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
sizeof(ulonglong);
*(ulonglong *)((char *) key_cache + ofs)=
1
0

[Maria-developers] Rev 2773: MWL#43 CREATE TABLE options in file:///home/bell/maria/bzr/work-maria-5.2-createoptions5/
by sanja@askmonty.org 06 Apr '10
by sanja@askmonty.org 06 Apr '10
06 Apr '10
At file:///home/bell/maria/bzr/work-maria-5.2-createoptions5/
------------------------------------------------------------
revno: 2773
revision-id: sanja(a)askmonty.org-20100406000609-jl8415st523eq5jj
parent: sergii(a)pisem.net-20100405095031-bgjy005pcftkp6g1
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-createoptions5
timestamp: Tue 2010-04-06 03:06:09 +0300
message:
MWL#43 CREATE TABLE options
=== modified file 'Docs/sp-imp-spec.txt'
--- a/Docs/sp-imp-spec.txt 2004-03-23 11:04:40 +0000
+++ b/Docs/sp-imp-spec.txt 2010-04-06 00:06:09 +0000
@@ -1075,7 +1075,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_NOERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -1097,4 +1097,4 @@
) comment='Stored Procedures';
--
-
\ No newline at end of file
+
=== modified file 'include/my_base.h'
--- a/include/my_base.h 2010-02-10 19:06:24 +0000
+++ b/include/my_base.h 2010-04-06 00:06:09 +0000
@@ -314,6 +314,8 @@
#define HA_OPTION_RELIES_ON_SQL_LAYER 512
#define HA_OPTION_NULL_FIELDS 1024
#define HA_OPTION_PAGE_CHECKSUM 2048
+/* .frm has extra create options in linked-list format */
+#define HA_OPTION_TEXT_CREATE_OPTIONS (1L << 14)
#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */
#define HA_OPTION_READ_ONLY_DATA (1L << 16) /* Set by isamchk */
#define HA_OPTION_NO_CHECKSUM (1L << 17)
=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt 2010-04-02 18:51:02 +0000
+++ b/libmysqld/CMakeLists.txt 2010-04-06 00:06:09 +0000
@@ -139,7 +139,8 @@
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
- ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/create_options.cc
${GEN_SOURCES}
${LIB_SOURCES})
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2010-03-29 15:13:53 +0000
+++ b/libmysqld/Makefile.am 2010-04-06 00:06:09 +0000
@@ -75,7 +75,7 @@
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
debug_sync.cc \
- sql_tablespace.cc \
+ sql_tablespace.cc create_options.cc \
rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc event_parse_data.cc opt_table_elimination.cc
=== added file 'mysql-test/r/create_options.result'
--- a/mysql-test/r/create_options.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/create_options.result 2010-04-06 00:06:09 +0000
@@ -0,0 +1,182 @@
+drop table if exists t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'
+Warning 1650 Unknown option 'dff'
+Warning 1650 Unknown option 'tkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v1'
+drop table t1;
+#reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'
+Warning 1650 Unknown option 'dff'
+Warning 1650 Unknown option 'tkey1'
+Warning 1650 Unknown option 'tkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1'
+#add option
+alter table t1 tkey4=4v1;
+Warnings:
+Warning 1650 Unknown option 'tkey4'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1' `tkey4`='4v1'
+#remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+Warnings:
+Warning 1650 Unknown option 'tkey3'
+Warning 1650 Unknown option 'tkey4'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1' `tkey4`='4v1'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unknown option 'fkey1'
+Warning 1650 Unknown option 'kkey1'
+Warning 1650 Unknown option 'TKEY1'
+Warning 1650 Unknown option 'tkey2'
+Warning 1650 Unknown option 'tkey3'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v1',
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+Warnings:
+Warning 1650 Unknown option 'FKEY1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `FKEY1`='v1',
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning 1650 Unknown option 'fkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new column no options
+alter table t1 add column b int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning 1650 Unknown option 'kkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+Warnings:
+Warning 1650 Unknown option 'fkey1'
+Warning 1650 Unknown option 'fkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#drop column
+alter table t1 drop b;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#add column with options after delete
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning 1650 Unknown option 'fkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ `b` int(11) DEFAULT NULL `fkey2`='v1',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#add key
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning 1650 Unknown option 'kkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ `b` int(11) DEFAULT NULL `fkey2`='v1',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`),
+ KEY `bkey` (`b`) `kkey2`='v2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+drop table t1;
+create table t1 (a int) tkey1=100;
+Warnings:
+Warning 1650 Unknown option 'tkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=100
+drop table t1;
+#error on unknown option
+SET SQL_MODE='';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+ERROR HY000: Unknown option 'fkey'
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/r/events_bugs.result'
--- a/mysql-test/r/events_bugs.result 2009-03-11 20:30:56 +0000
+++ b/mysql-test/r/events_bugs.result 2010-04-06 00:06:09 +0000
@@ -729,9 +729,8 @@
create event e1 on schedule every 1 day do select 1;
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_NOERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
name
=== modified file 'mysql-test/r/information_schema.result'
--- a/mysql-test/r/information_schema.result 2010-03-15 11:51:23 +0000
+++ b/mysql-test/r/information_schema.result 2010-04-06 00:06:09 +0000
@@ -615,7 +615,7 @@
proc definer char(77)
proc created timestamp
proc modified timestamp
-proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
proc comment char(64)
proc character_set_client char(32)
proc collation_connection char(32)
=== modified file 'mysql-test/r/plugin_load.result'
--- a/mysql-test/r/plugin_load.result 2008-01-26 00:05:15 +0000
+++ b/mysql-test/r/plugin_load.result 2010-04-06 00:06:09 +0000
@@ -1,3 +1,57 @@
SELECT @@global.example_enum_var = 'e2';
@@global.example_enum_var = 'e2'
1
+#legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `complex`='c,f,f,f'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000 `STR`='dskj' `one_or_two`='one' `YESNO`=0
+drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+#illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+Warnings:
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS'
+#alter table
+alter table t1 ULL=10000000;
+Warnings:
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS' `ULL`='10000000'
+alter table t1 change a a int complex='c,c,c';
+Warnings:
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `complex`='c,c,c'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS' `ULL`='10000000'
+drop table t1;
+#illegal value error
+SET SQL_MODE='';
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+ERROR HY000: Incorrect value '10000000000000000000' for option 'ULL'
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result 2009-12-23 13:44:03 +0000
+++ b/mysql-test/r/sp.result 2010-04-06 00:06:09 +0000
@@ -6940,9 +6940,8 @@
call p();
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_NOERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
name
=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result 2010-03-29 15:13:53 +0000
+++ b/mysql-test/r/system_mysql_db.result 2010-04-06 00:06:09 +0000
@@ -202,7 +202,7 @@
`definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
- `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
@@ -227,7 +227,7 @@
`ends` datetime DEFAULT NULL,
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
- `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`originator` int(10) unsigned NOT NULL,
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-03-29 15:13:53 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-04-06 00:06:09 +0000
@@ -49,7 +49,7 @@
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned select,insert,update,references
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql event sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select,insert,update,references
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references
@@ -124,7 +124,7 @@
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql proc sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI select,insert,update,references
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references
@@ -330,7 +330,7 @@
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -405,7 +405,7 @@
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result 2009-05-19 16:43:50 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result 2010-04-06 00:06:09 +0000
@@ -49,7 +49,7 @@
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE')
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64)
@@ -124,7 +124,7 @@
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER')
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64)
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL
@@ -327,7 +327,7 @@
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +402,7 @@
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== added file 'mysql-test/t/create_options.test'
--- a/mysql-test/t/create_options.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/create_options.test 2010-04-06 00:06:09 +0000
@@ -0,0 +1,68 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+show create table t1;
+drop table t1;
+
+--echo #reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+show create table t1;
+
+-- echo #add option
+alter table t1 tkey4=4v1;
+show create table t1;
+
+--echo #remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+show create table t1;
+
+drop table t1;
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+show create table t1;
+
+--echo #change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+show create table t1;
+--echo #change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+show create table t1;
+--echo #new column no options
+alter table t1 add column b int;
+show create table t1;
+--echo #new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+show create table t1;
+--echo #new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+show create table t1;
+--echo #new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+--echo #drop column
+alter table t1 drop b;
+show create table t1;
+--echo #add column with options after delete
+alter table t1 add column b int fkey2=v1;
+show create table t1;
+--echo #add key
+alter table t1 add key bkey (b) kkey2=v2;
+show create table t1;
+drop table t1;
+
+#numeric (unquoted) value
+create table t1 (a int) tkey1=100;
+show create table t1;
+drop table t1;
+
+--echo #error on unknown option
+SET SQL_MODE='';
+--error ER_UNKNOWN_OPTION
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/t/events_bugs.test'
--- a/mysql-test/t/events_bugs.test 2009-03-11 20:30:56 +0000
+++ b/mysql-test/t/events_bugs.test 2010-04-06 00:06:09 +0000
@@ -1204,7 +1204,6 @@
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
drop event e1;
=== modified file 'mysql-test/t/plugin_load.test'
--- a/mysql-test/t/plugin_load.test 2009-10-08 08:39:15 +0000
+++ b/mysql-test/t/plugin_load.test 2010-04-06 00:06:09 +0000
@@ -2,3 +2,30 @@
--source include/have_example_plugin.inc
SELECT @@global.example_enum_var = 'e2';
+
+--echo #legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+drop table t1;
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+
+--echo #illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+show create table t1;
+
+--echo #alter table
+alter table t1 ULL=10000000;
+show create table t1;
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+drop table t1;
+
+
+--echo #illegal value error
+SET SQL_MODE='';
+--error ER_BAD_OPTION_VALUE
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/t/sp.test'
--- a/mysql-test/t/sp.test 2009-12-23 13:44:03 +0000
+++ b/mysql-test/t/sp.test 2010-04-06 00:06:09 +0000
@@ -8210,7 +8210,6 @@
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
drop procedure p;
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql 2010-03-29 15:13:53 +0000
+++ b/scripts/mysql_system_tables.sql 2010-04-06 00:06:09 +0000
@@ -60,7 +60,7 @@
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
-CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
+CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'CREATE_OPTIONS_NOERR', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
@@ -80,7 +80,7 @@
EXECUTE stmt;
DROP PREPARE stmt;
-CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
+CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
=== modified file 'scripts/mysql_system_tables_fix.sql'
--- a/scripts/mysql_system_tables_fix.sql 2010-03-29 15:13:53 +0000
+++ b/scripts/mysql_system_tables_fix.sql 2010-04-06 00:06:09 +0000
@@ -368,7 +368,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_NOERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -482,14 +482,14 @@
ALTER TABLE event DROP PRIMARY KEY;
ALTER TABLE event ADD PRIMARY KEY(db, name);
# Add sql_mode column just in case.
-ALTER TABLE event ADD sql_mode set ('NOT_USED') AFTER on_completion;
+ALTER TABLE event ADD sql_mode set ('CREATE_OPTIONS_NOERR') AFTER on_completion;
# Update list of sql_mode values.
ALTER TABLE event MODIFY sql_mode
set('REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_NOERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2010-03-29 15:13:53 +0000
+++ b/sql/CMakeLists.txt 2010-04-06 00:06:09 +0000
@@ -77,6 +77,7 @@
rpl_rli.cc rpl_mi.cc sql_servers.cc
sql_connect.cc scheduler.cc
sql_profile.cc event_parse_data.cc opt_table_elimination.cc
+ create_options.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2010-03-29 15:13:53 +0000
+++ b/sql/Makefile.am 2010-04-06 00:06:09 +0000
@@ -78,7 +78,8 @@
sql_plugin.h authors.h event_parse_data.h \
event_data_objects.h event_scheduler.h \
sql_partition.h partition_info.h partition_element.h \
- contributors.h sql_servers.h
+ contributors.h sql_servers.h \
+ create_options.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -124,7 +125,7 @@
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \
sql_servers.cc event_parse_data.cc \
- opt_table_elimination.cc
+ opt_table_elimination.cc create_options.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c client_plugin.c
=== added file 'sql/create_options.cc'
--- a/sql/create_options.cc 1970-01-01 00:00:00 +0000
+++ b/sql/create_options.cc 2010-04-06 00:06:09 +0000
@@ -0,0 +1,679 @@
+/* Copyright (C) 2010 Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Engine defined options of tables/fields/keys in CREATE/ALTER TABLE.
+*/
+
+#include "mysql_priv.h"
+#include <my_getopt.h>
+
+/* bits of first byte (type byte of frm imege) */
+#define FRM_TYPE_MASK 0x03
+#define FRM_QUATED_VALUE 0x80
+
+/**
+ Links this item to the given list end
+
+ @param start The list beginning or NULL
+ @param end The list last element or does not matter
+*/
+
+void engine_option_value::link(engine_option_value **start,
+ engine_option_value **end)
+{
+ DBUG_ENTER("engine_option_value::link");
+ DBUG_PRINT("enter", ("name: '%s' (%u) value: '%s' (%u)",
+ name.str, (uint) name.length,
+ value.str, (uint) value.length));
+ engine_option_value *opt;
+ /* check duplicates to avoid writing them to frm*/
+ for(opt= *start;
+ opt && (opt->deleted ||
+ my_strnncoll(system_charset_info,
+ (uchar *)name.str, name.length,
+ (uchar*)opt->name.str, opt->name.length));
+ opt= opt->next) {};
+ if (opt)
+ {
+ /* remove previous value */
+ opt->value.str= NULL;
+ opt->parsed= TRUE;
+ opt->deleted= TRUE;
+ }
+ /*
+ Add this option to the end of the list
+
+ @note: We add even if it is opt->value.str == NULL because it can be
+ ALTER TABLE to remove the option.
+ */
+ if (*start)
+ {
+ (*end)->next= this;
+ *end= this;
+ }
+ else
+ {
+ *start= *end= this;
+ }
+ DBUG_VOID_RETURN;
+}
+
+static bool report_wrong_value(THD *thd, const char *name, const char *val,
+ my_bool suppress_warning)
+{
+ if (!(thd->variables.sql_mode & MODE_CREATE_OPTIONS_NOERR))
+ {
+ my_error(ER_BAD_OPTION_VALUE, MYF(0), val, name);
+ return 1;
+ }
+
+ /*
+ We suppress errors to avoid double messages about the same value. It has
+ no sense to supress errors as they lead to execution abortion.
+ */
+ if (!suppress_warning)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_OPTION_VALUE,
+ ER(ER_BAD_OPTION_VALUE), val, name);
+ return 0;
+}
+
+static bool report_unknown_option(THD *thd, engine_option_value *val,
+ my_bool suppress_warning)
+{
+ DBUG_ENTER("report_unknown_option");
+ if (val->parsed)
+ {
+ DBUG_PRINT("info", ("parsed => exiting"));
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!(thd->variables.sql_mode & MODE_CREATE_OPTIONS_NOERR))
+ {
+ my_error(ER_UNKNOWN_OPTION, MYF(0), val->name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ We suppress errors to avoid double messages about the same value. It has
+ no sense to supress errors as they lead to execution abortion.
+ */
+ if (!suppress_warning)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_OPTION,
+ ER(ER_UNKNOWN_OPTION),
+ val->name.str);
+ DBUG_RETURN(FALSE);
+}
+
+static bool set_one_value(ha_create_table_option *opt,
+ THD *thd, LEX_STRING *value, void *base,
+ my_bool suppress_warning,
+ MEM_ROOT *root)
+{
+ DBUG_ENTER("set_one_value");
+ DBUG_PRINT("enter", ("opt: 0x%lx type: %u name '%s' value: '%s'",
+ (ulong) opt,
+ opt->type, opt->name,
+ (value->str ? value->str : "<DEFAULT>")));
+ switch (opt->type)
+ {
+ case HA_OPTION_TYPE_ULL:
+ {
+ ulonglong *val= (ulonglong*)((char*)base + opt->offset);
+ *val= opt->def_value;
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ my_option optp= { opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
+ REQUIRED_ARG, opt->def_value, opt->min_value, opt->max_value,
+ 0, opt->block_size, 0};
+
+ ulonglong orig_val= strtoull(value->str, NULL, 10);
+ my_bool unused;
+ *val= orig_val;
+ *val= getopt_ull_limit_value(*val, &optp, &unused);
+ if (*val == orig_val)
+ DBUG_RETURN(0);
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ case HA_OPTION_TYPE_STRING:
+ {
+ char **val= (char **)((char *)base + opt->offset);
+ *val= 0;
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (!(*val= strmake_root(root, value->str, value->length)))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+ }
+ case HA_OPTION_TYPE_ENUM:
+ {
+ uint *val= (uint *)((char *)base + opt->offset), num;
+ *val= opt->def_value;
+
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ const char *start= opt->values, *end;
+
+ num= 0;
+ while (*start)
+ {
+ for (end=start;
+ *end && *end != ',';
+ end+= my_mbcharlen(system_charset_info, *end)) /* no-op */;
+ if (!my_strnncoll(system_charset_info,
+ (uchar*)start, end-start,
+ (uchar*)value->str, value->length))
+ {
+ *val= num;
+ DBUG_RETURN(0);
+ }
+ if (*end) *end++;
+ start= end;
+ num++;
+ }
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ case HA_OPTION_TYPE_BOOL:
+ {
+ bool *val= (bool *)((char *)base + opt->offset);
+ *val= opt->def_value;
+
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (!my_strnncoll(system_charset_info,
+ (const uchar*)"NO", 2,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"OFF", 3,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"N", 1,
+ (uchar *)value->str, value->length))
+ {
+ *val= FALSE;
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!my_strnncoll(system_charset_info,
+ (const uchar*)"YES", 3,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"ON", 2,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"N", 1,
+ (uchar *)value->str, value->length))
+ {
+ *val= TRUE;
+ DBUG_RETURN(FALSE);
+ }
+
+ /* numeric value */
+ if (value->str[0] < '0' || value->str[0] > '9')
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+
+ if (strtoull(value->str, NULL, 10))
+ *val= 1;
+ else
+ *val= 0;
+
+ DBUG_RETURN(FALSE);
+ }
+ }
+ DBUG_ASSERT(0);
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ DBUG_RETURN(1);
+}
+
+static const size_t ha_option_type_sizeof[]=
+{ sizeof(ulonglong), sizeof(char *), sizeof(uint), sizeof(bool)};
+
+/**
+ Creates option structure and parses list of options in it
+
+ @param thd thread handler
+ @param option_struct where to store pointer on the option struct
+ @param option_list list of options given by user
+ @param rules list of option description by engine
+ @param suppress_warning second parse so we do not need warnings
+ @param root MEM_ROOT where allocate memory
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool parse_option_list(THD* thd, void **option_struct,
+ engine_option_value *option_list,
+ ha_create_table_option *rules,
+ my_bool suppress_warning,
+ MEM_ROOT *root)
+{
+ ha_create_table_option *opt;
+ size_t option_struct_size= 0;
+ engine_option_value *val= option_list;
+ DBUG_ENTER("parse_option_list");
+ DBUG_PRINT("enter",
+ ("struct: 0x%lx list: 0x%lx rules: 0x%lx suppres %u root 0x%lx",
+ (ulong) *option_struct, (ulong)option_list, (ulong)rules,
+ (uint) suppress_warning, (ulong) root));
+
+ if (rules)
+ {
+ LEX_STRING default_val= {NULL, 0};
+ for (opt= rules; opt->name; opt++)
+ set_if_bigger(option_struct_size, opt->offset +
+ ha_option_type_sizeof[opt->type]);
+
+ *option_struct= alloc_root(root, option_struct_size);
+
+ /* set all values to default */
+ for (opt= rules; opt->name; opt++)
+ set_one_value(opt, thd, &default_val, *option_struct,
+ suppress_warning, root);
+ }
+
+ for (; val; val= val->next)
+ {
+ //if (!val->value.str) continue; // skip deleted
+ for (opt= rules; opt && opt->name; opt++)
+ {
+ if (my_strnncoll(system_charset_info,
+ (uchar*)opt->name, opt->name_length,
+ (uchar*)val->name.str, val->name.length))
+ continue;
+
+ if (set_one_value(opt, thd, &val->value,
+ *option_struct, suppress_warning, root))
+ DBUG_RETURN(TRUE);
+ val->parsed= true;
+ break;
+ }
+ if (report_unknown_option(thd, val, suppress_warning))
+ DBUG_RETURN(TRUE);
+ val->parsed= true;
+ }
+
+ DBUG_RETURN(FALSE);;
+}
+
+
+/**
+ Parses all table/fields/keys options
+
+ @param thd thread handler
+ @param file handler of the table
+ @parem share descriptor of the table
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+ TABLE_SHARE *share)
+{
+ MEM_ROOT *root= &share->mem_root;
+ DBUG_ENTER("parse_engine_table_options");
+
+ if (parse_option_list(thd, &share->option_struct, share->option_list,
+ ht->table_opt_rules, TRUE, root))
+ DBUG_RETURN(TRUE);
+
+ for (Field **field= share->field; *field; field++)
+ {
+ if (parse_option_list(thd, &(*field)->option_struct, (*field)->option_list,
+ ht->field_opt_rules, TRUE, root))
+ DBUG_RETURN(TRUE);
+ }
+
+ for (uint index= 0; index < share->keys; index ++)
+ {
+ if (parse_option_list(thd, &share->key_info[index].option_struct,
+ share->key_info[index].option_list,
+ ht->key_opt_rules, TRUE, root))
+ DBUG_RETURN(TRUE);
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Returns representation length of key and value in the frm file
+*/
+
+uint engine_option_value::frm_length()
+{
+ /*
+ 2 bytes - value length
+ 1 byte - key length
+ */
+ return 2 + 1 + name.length + value.length;
+}
+
+
+/**
+ Returns length of representation of option list in the frm file
+
+ @param opt list of options;
+ @param overhead length of additional information per option
+
+ @returns length of image in frm
+*/
+
+static uint option_list_frm_length(engine_option_value *opt, uint overhead)
+{
+ uint res= 0;
+
+ for (; opt; opt= opt->next)
+ if (opt->value.str)
+ res+= opt->frm_length() + overhead;
+
+ return res;
+}
+
+
+/**
+ Calculates length of options image in the .frm
+
+ @param table_option_list list of table options
+ @param create_fields field descriptors list
+ @param keys number of keys
+ @param key_info array of key descriptors
+
+ @returns length of image in frm
+*/
+
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ uint res, index;
+ DBUG_ENTER("engine_table_options_frm_length");
+
+ /* 1 byte - record type */
+ res= option_list_frm_length(table_option_list, 1);
+
+ while ((field= it++))
+ {
+ /*
+ 1 byte - record type
+ 2 bytes - field number
+ */
+ res+= option_list_frm_length(field->option_list, 1 + 2);
+ }
+
+ for (index= 0; index < keys; index++, key_info++)
+ {
+
+ /*
+ 1 byte - record type
+ 2 bytes - key number
+ */
+ res+= option_list_frm_length(key_info->option_list, 1 + 2);
+ }
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Writes image of the key and value to the frm image buffer
+
+ @param buff pointer to the buffer free space beginning
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_option_value::frm_image(uchar *buff)
+{
+ buff[0]= name.length;
+ buff++;
+ memcpy(buff, name.str, name.length);
+ buff+= name.length;
+ int2store(buff, value.length);
+ buff+= 2;
+ memcpy(buff, (const uchar *) value.str, value.length);
+ buff+= value.length;
+ return buff;
+}
+
+/**
+ Writes image of the key and value to the frm image buffer
+
+ @param buff pointer to the buffer free space beginning
+ @param opt list of options;
+ @param type option type (CREATE_OPTION_*)
+ @param index for keys and fields index of them
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+static uchar *option_list_frm_image(uchar *buff,
+ engine_option_value *opt,
+ CREATE_OPTION_TYPES type,
+ uint index)
+{
+ for (; opt; opt= opt->next)
+ {
+ /* skip deleted options */
+ if (opt->value.str)
+ {
+ *(buff++)= (type | (opt->quoted_value ? FRM_QUATED_VALUE : 0));
+ if (type != CREATE_OPTION_TABLE)
+ {
+ int2store(buff, index);
+ buff+= 2;
+ }
+ buff= opt->frm_image(buff);
+ }
+ }
+
+ return buff;
+}
+
+
+/**
+ Writes options image in the .frm buffer
+
+ @param buff pointer to the buffer
+ @param table_option_list list of table options
+ @param create_fields field descriptors list
+ @param keys number of keys
+ @param key_info array of key descriptors
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ uint index;
+ DBUG_ENTER("engine_table_options_frm_image");
+
+ buff= option_list_frm_image(buff, table_option_list, CREATE_OPTION_TABLE, 0);
+
+ for (index= 0; (field= it++); index++)
+ buff= option_list_frm_image(buff, field->option_list,
+ CREATE_OPTION_FIELD, index);
+
+ for (index= 0; index < keys; index++, key_info++)
+ buff= option_list_frm_image(buff, key_info->option_list,
+ CREATE_OPTION_KEY, index);
+ DBUG_RETURN(buff);
+}
+
+/**
+ Reads name and value from buffer, then link it in the list
+
+ @param buff the buffer to read from
+ @param start The list beginning or NULL
+ @param end The list last element or does not matter
+ @param root MEM_ROOT for allocating
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+uchar *engine_option_value::frm_read(const uchar *buff,
+ engine_option_value **start,
+ engine_option_value **end,
+ MEM_ROOT *root)
+{
+ name.length= buff[0];
+ buff++;
+ if (!(name.str= strmake_root(root, (const char*)buff,
+ name.length)))
+ return NULL;
+ buff+= name.length;
+ value.length= uint2korr(buff);
+ buff+= 2;
+ if (!(value.str= strmake_root(root, (const char*)buff,
+ value.length)))
+ return NULL;
+ buff+= value.length;
+ link(start, end);
+ return (uchar *)buff;
+}
+
+
+/**
+ Reads options from this buffer
+
+ @param buff the buffer to read from
+ @param length buffer length
+ @param share table descriptor
+ @param root MEM_ROOT for allocating
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool engine_table_options_frm_read(const uchar *buff,
+ uint length,
+ TABLE_SHARE *share)
+{
+ const uchar *buff_end= buff + length;
+ engine_option_value *tbl_end, **fld_end, **key_end;
+ MEM_ROOT *root= &share->mem_root;
+ DBUG_ENTER("engine_table_options_frm_read");
+
+ /* temporary list end pointers to construct lists */
+ tbl_end= NULL;
+ if (!(fld_end= (engine_option_value **)
+ alloc_root(root, sizeof(engine_option_value *) * share->fields)) ||
+ !(key_end= (engine_option_value **)
+ alloc_root(root, sizeof(engine_option_value *) * share->keys)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ while (buff < buff_end)
+ {
+ engine_option_value *option;
+ CREATE_OPTION_TYPES type;
+ uint index= 0;
+
+ if (!(option= new (root) engine_option_value()))
+ DBUG_RETURN(TRUE);
+
+ DBUG_ASSERT(buff + 4 <= buff_end);
+
+ type= (CREATE_OPTION_TYPES)(FRM_TYPE_MASK & buff[0]);
+ option->set_quoted_value(FRM_QUATED_VALUE & buff[0]);
+ buff++;
+ switch (type) {
+ case CREATE_OPTION_FIELD:
+ index= uint2korr(buff);
+ buff+= 2;
+ DBUG_ASSERT(index < share->fields);
+ if (!(buff= option->frm_read(buff,
+ &share->field[index]->option_list,
+ fld_end + index,
+ root)))
+ DBUG_RETURN(TRUE);
+ break;
+ case CREATE_OPTION_KEY:
+ index= uint2korr(buff);
+ buff+= 2;
+ DBUG_ASSERT(index < share->keys);
+ if (!(buff= option->frm_read(buff,
+ &share->key_info[index].option_list,
+ key_end + index,
+ root)))
+ DBUG_RETURN(TRUE);
+ break;
+ case CREATE_OPTION_TABLE:
+ if (!(buff= option->frm_read(buff,
+ &share->option_list,
+ &tbl_end,
+ root)))
+ DBUG_RETURN(TRUE);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ DBUG_PRINT("info", ("type: %u index: %u key: '%s' value: '%s'",
+ (uint) type, (uint) index,
+ option->name.str, option->value.str));
+ }
+ DBUG_RETURN(FALSE);
+}
+
+/**
+ Adds (merges) chages to source
+*/
+
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+ engine_option_value *changes,
+ MEM_ROOT *root)
+{
+ engine_option_value *end, *opt;
+ DBUG_ENTER("merge_engine_table_options");
+
+ /* find last element */
+ if (source)
+ for (end= source; end->next; end= end->next){};
+
+ for (opt= changes; opt; opt= opt->next)
+ {
+ new (root) engine_option_value(opt->name,
+ opt->value.str, opt->value.length,
+ &source, &end);
+ }
+ DBUG_RETURN(source);
+}
=== added file 'sql/create_options.h'
--- a/sql/create_options.h 1970-01-01 00:00:00 +0000
+++ b/sql/create_options.h 2010-04-06 00:06:09 +0000
@@ -0,0 +1,139 @@
+/* Copyright (C) 2010 Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Engine defined options of tables/fields/keys in CREATE/ALTER TABLE.
+*/
+
+#ifndef SQL_CREATE_OPTIONS_INCLUDED
+#define SQL_CREATE_OPTIONS_INCLUDED
+
+class Item;
+#include "handler.h"
+
+/* types of cretate options records on disk, also it is length of extra data */
+typedef enum enum_create_options_type {
+ CREATE_OPTION_TABLE= 0,
+ CREATE_OPTION_KEY= 1,
+ CREATE_OPTION_FIELD= 2
+} CREATE_OPTION_TYPES;
+
+class engine_option_value: public Sql_alloc
+{
+ public:
+ LEX_STRING name;
+ LEX_STRING value;
+ engine_option_value *next;
+ bool parsed;
+ bool deleted;
+ bool quoted_value;
+ engine_option_value() :
+ next(NULL), parsed(false)
+ {}
+ engine_option_value(const char *name_arg, size_t name_len_arg,
+ const char *value_arg, size_t value_len_arg,
+ engine_option_value **start, engine_option_value **end) :
+ next(NULL), parsed(false), deleted(false), quoted_value(true)
+ {
+ name.str= const_cast<char*>(name_arg);
+ name.length= name_len_arg;
+ value.str= const_cast<char*>(value_arg);
+ value.length= value_len_arg;
+ link(start, end);
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ const char *value_arg, size_t value_len_arg,
+ engine_option_value **start, engine_option_value **end) :
+ name(name_arg), next(NULL), parsed(false), deleted(false),
+ quoted_value(true)
+ {
+ value.str= const_cast<char*>(value_arg);
+ value.length= value_len_arg;
+ link(start, end);
+ }
+ engine_option_value(const char *name_arg, size_t name_len_arg,
+ ulonglong value_arg,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root) :
+ next(NULL), parsed(false), deleted(false), quoted_value(false)
+ {
+ name.str= const_cast<char*>(name_arg);
+ name.length= name_len_arg;
+ if ((value.str= (char *)alloc_root(root, 22)))
+ {
+ value.length= longlong2str(value_arg, value.str, 10) - value.str;
+ link(start, end);
+ }
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ ulonglong value_arg,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root) :
+ name(name_arg), next(NULL), parsed(false), deleted(false),
+ quoted_value(false)
+ {
+ if ((value.str= (char *)alloc_root(root, 22)))
+ {
+ value.length= longlong2str(value_arg, value.str, 10) - value.str;
+ link(start, end);
+ }
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ ha_choice value_arg,
+ engine_option_value **start, engine_option_value **end) :
+ name(name_arg), next(NULL), parsed(false), deleted(false),
+ quoted_value(false)
+ {
+ value.length= 1;
+ switch (value_arg) {
+ case HA_CHOICE_UNDEF:
+ value.str= NULL;
+ value.length= 0;
+ break;
+ case HA_CHOICE_NO:
+ value.str= (char*)"0";
+ break;
+ case HA_CHOICE_YES:
+ value.str= (char*)"1";
+ break;
+ }
+ }
+ void set_quoted_value(bool quoted) {quoted_value= quoted;}
+ void link(engine_option_value **start, engine_option_value **end);
+ uint frm_length();
+ uchar *frm_image(uchar *buff);
+ uchar *frm_read(const uchar *buff,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root);
+};
+
+class handler;
+class THD;
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+ TABLE_SHARE *share);
+my_bool parse_option_list(THD* thd, void **option_struct,
+ engine_option_value *option_list,
+ ha_create_table_option *rules,
+ my_bool suppress_warning,
+ MEM_ROOT *root);
+my_bool engine_table_options_frm_read(const uchar *buff,
+ uint length,
+ TABLE_SHARE *share);
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+ engine_option_value *changes,
+ MEM_ROOT *root);
+#endif
=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc 2010-03-15 11:51:23 +0000
+++ b/sql/event_db_repository.cc 2010-04-06 00:06:09 +0000
@@ -105,7 +105,8 @@
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY',"
+ "'NO_UNSIGNED_SUBTRACTION',"
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2010-03-17 02:32:31 +0000
+++ b/sql/field.cc 2010-04-06 00:06:09 +0000
@@ -1306,14 +1306,13 @@
Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg)
- :ptr(ptr_arg), null_ptr(null_ptr_arg),
- table(0), orig_table(0), table_name(0),
- field_name(field_name_arg),
- 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),
- vcol_info(0), stored_in_db(TRUE)
+ :ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0),
+ table_name(0), field_name(field_name_arg), option_list(0),
+ option_struct(0), 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), vcol_info(0),
+ stored_in_db(TRUE)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -9567,7 +9566,8 @@
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,
- Virtual_column_info *fld_vcol_info)
+ Virtual_column_info *fld_vcol_info,
+ engine_option_value *create_opt)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9578,6 +9578,7 @@
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
+ option_list= create_opt;
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
@@ -10217,6 +10218,8 @@
decimals= old_field->decimals();
vcol_info= old_field->vcol_info;
stored_in_db= old_field->stored_in_db;
+ option_list= old_field->option_list;
+ option_struct= old_field->option_struct;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -10291,6 +10294,19 @@
/**
+ Makes a clone of this object for ALTER/CREATE TABLE
+
+ @param mem_root MEM_ROOT where to clone the field
+*/
+
+Create_field *Create_field::clone(MEM_ROOT *mem_root) const
+{
+ Create_field *res= new (mem_root) Create_field(*this);
+ return res;
+}
+
+
+/**
maximum possible display length for blob.
@return
=== modified file 'sql/field.h'
--- a/sql/field.h 2010-03-15 11:51:23 +0000
+++ b/sql/field.h 2010-04-06 00:06:09 +0000
@@ -137,6 +137,9 @@
struct st_table *table; // Pointer for table
struct st_table *orig_table; // Pointer to original table
const char **table_name, *field_name;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -2145,6 +2148,9 @@
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
+ engine_option_value *option_list;
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
@@ -2162,11 +2168,11 @@
*/
bool stored_in_db;
- Create_field() :after(0) {}
+ Create_field() :after(0), option_list(NULL), option_struct(NULL)
+ {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
- Create_field *clone(MEM_ROOT *mem_root) const
- { return new (mem_root) Create_field(*this); }
+ Create_field *clone(MEM_ROOT *mem_root) const;
void create_length_to_internal_length(void);
/* Init for a tmp table field. To be extended if need be. */
@@ -2178,8 +2184,8 @@
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,
- Virtual_column_info *vcol_info);
+ uint uint_geom_type, Virtual_column_info *vcol_info,
+ engine_option_value *option_list);
bool field_flags_are_binary()
{
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-04-01 14:34:51 +0000
+++ b/sql/ha_partition.cc 2010-04-06 00:06:09 +0000
@@ -1218,7 +1218,9 @@
DBUG_ENTER("prepare_new_partition");
if ((error= set_up_table_before_create(tbl, part_name, create_info,
- 0, p_elem)))
+ 0, p_elem)) ||
+ parse_engine_table_options(ha_thd(), file->ht,
+ file->table_share))
goto error_create;
if ((error= file->ha_create(part_name, tbl, create_info)))
{
@@ -1869,6 +1871,8 @@
{
if ((error= set_up_table_before_create(table_arg, from_buff,
create_info, i, NULL)) ||
+ parse_engine_table_options(ha_thd(), (*file)->ht,
+ (*file)->table_share) ||
((error= (*file)->ha_create(from_buff, table_arg, create_info))))
goto create_error;
}
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-04-01 09:04:26 +0000
+++ b/sql/handler.cc 2010-04-06 00:06:09 +0000
@@ -3719,7 +3719,12 @@
name= get_canonical_filename(table.file, share.path.str, name_buff);
+ if (parse_engine_table_options(thd, table.file->ht, &share))
+ goto err;
+
error= table.file->ha_create(name, &table, create_info);
+
+
VOID(closefrm(&table, 0));
if (error)
{
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2010-03-25 13:33:39 +0000
+++ b/sql/handler.h 2010-04-06 00:06:09 +0000
@@ -16,6 +16,9 @@
/* Definitions for parameters to do with handler-routines */
+#ifndef SQL_HANDLER_INCLUDED
+#define SQL_HANDLER_INCLUDED
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -23,6 +26,7 @@
#include <my_handler.h>
#include <ft_global.h>
#include <keycache.h>
+#include "create_options.h"
#ifndef NO_HASH
#define NO_HASH /* Not yet implemented */
@@ -516,6 +520,7 @@
struct st_table;
typedef struct st_table TABLE;
typedef struct st_table_share TABLE_SHARE;
+class engine_option;
struct st_foreign_key_info;
typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
@@ -549,6 +554,65 @@
enum log_status status;
};
+enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */
+ HA_OPTION_TYPE_STRING, /* char * */
+ HA_OPTION_TYPE_ENUM, /* uint */
+ HA_OPTION_TYPE_BOOL}; /* bool */
+
+#define HA_xOPTION_ULL(name, struc, field, def, min, max, blk_siz) \
+ { HA_OPTION_TYPE_ULL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, min, max, blk_siz, 0 }
+#define HA_xOPTION_STRING(name, struc, field) \
+ { HA_OPTION_TYPE_STRING, name, sizeof(name)-1, \
+ offsetof(struc, field), 0, 0, 0, 0, 0 }
+#define HA_xOPTION_ENUM(name, struc, field, values, def) \
+ { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, \
+ sizeof(values)-1, 0, values }
+#define HA_xOPTION_BOOL(name, struc, field, def) \
+ { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, 1, 0, 0 }
+#define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define HA_TOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_table_option_struct, field, def, min, max, blk_siz)
+#define HA_TOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_table_option_struct, field)
+#define HA_TOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def)
+#define HA_TOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_table_option_struct, field, def)
+#define HA_TOPTION_END HA_xOPTION_END
+
+#define HA_FOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_field_option_struct, field, def, min, max, blk_siz)
+#define HA_FOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_field_option_struct, field)
+#define HA_FOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def)
+#define HA_FOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_field_option_struct, field, def)
+#define HA_FOPTION_END HA_xOPTION_END
+
+#define HA_KOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_key_option_struct, field, def, min, max, blk_siz)
+#define HA_KOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_key_option_struct, field)
+#define HA_KOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_BOOL(name, field, values, def) \
+ HA_xOPTION_BOOL(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_END HA_xOPTION_END
+
+typedef struct st_ha_create_table_option {
+ enum ha_option_type type;
+ const char *name;
+ size_t name_length;
+ ptrdiff_t offset;
+ ulonglong def_value;
+ ulonglong min_value, max_value, block_size;
+ const char *values;
+} ha_create_table_option;
enum handler_iterator_type
{
@@ -721,7 +785,11 @@
int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
const char *name);
uint32 license; /* Flag for Engine License */
- void *data; /* Location for engines to keep personal structures */
+ /* CREATE OPTIONS rules for parameter parsing */
+ ha_create_table_option *table_opt_rules,
+ *field_opt_rules,
+ *key_opt_rules;
+
};
@@ -950,6 +1018,14 @@
bool varchar; /* 1 if table has a VARCHAR */
enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
enum ha_choice page_checksum; /* If we have page_checksums */
+ engine_option_value *option_list; /* list of table create options */
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
+ /* following 4 fields assigned only for check_if_incompatible_data() */
+ void *old_option_struct;
+ void **old_new_fileds_option_struct[2];
+ void **old_new_keys_option_struct[2];
+ uint fields, keys;
} HA_CREATE_INFO;
@@ -2254,3 +2330,5 @@
#define ha_binlog_wait(a) do {} while (0)
#define ha_binlog_end(a) do {} while (0)
#endif
+
+#endif
=== modified file 'sql/log_event.h'
--- a/sql/log_event.h 2010-03-15 11:51:23 +0000
+++ b/sql/log_event.h 2010-04-06 00:06:09 +0000
@@ -1371,7 +1371,7 @@
MODE_PIPES_AS_CONCAT==0x2
MODE_ANSI_QUOTES==0x4
MODE_IGNORE_SPACE==0x8
- MODE_NOT_USED==0x10
+ MODE_CREATE_OPTIONS_NOERR==0x10
MODE_ONLY_FULL_GROUP_BY==0x20
MODE_NO_UNSIGNED_SUBTRACTION==0x40
MODE_NO_DIR_IN_CREATE==0x80
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2010-03-29 15:13:53 +0000
+++ b/sql/mysql_priv.h 2010-04-06 00:06:09 +0000
@@ -54,7 +54,6 @@
#include "sql_plugin.h"
#include "scheduler.h"
#include "log_slow.h"
-
class Parser_state;
/**
@@ -520,7 +519,7 @@
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
-#define MODE_NOT_USED 16
+#define MODE_CREATE_OPTIONS_NOERR 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define MODE_NO_DIR_IN_CREATE 128
@@ -783,6 +782,7 @@
ulonglong *engine_data);
#include "sql_string.h"
#include "sql_list.h"
+#include "create_options.h"
#include "sql_map.h"
#include "my_decimal.h"
#include "handler.h"
@@ -1508,7 +1508,8 @@
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info);
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
@@ -2625,4 +2626,14 @@
#endif /* MYSQL_CLIENT */
+/* Define to force use of my_malloc() if the allocated memory block is big */
+
+#ifndef HAVE_ALLOCA
+#define my_safe_alloca(size, min_length) my_alloca(size)
+#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
+#else
+#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
+#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
+#endif
+
#endif /* MYSQL_PRIV_H */
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-04-02 09:20:09 +0000
+++ b/sql/mysqld.cc 2010-04-06 00:06:09 +0000
@@ -244,7 +244,7 @@
static const char *sql_mode_names[]=
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "CREATE_OPTIONS_NOERR", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"NO_DIR_IN_CREATE",
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
@@ -264,7 +264,7 @@
/*PIPES_AS_CONCAT*/ 15,
/*ANSI_QUOTES*/ 11,
/*IGNORE_SPACE*/ 12,
- /*?*/ 1,
+ /*CREATE_OPTIONS_NOERR*/ 20,
/*ONLY_FULL_GROUP_BY*/ 18,
/*NO_UNSIGNED_SUBTRACTION*/ 23,
/*NO_DIR_IN_CREATE*/ 16,
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2010-03-15 11:51:23 +0000
+++ b/sql/share/errmsg.txt 2010-04-06 00:06:09 +0000
@@ -6240,3 +6240,8 @@
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"
+
+ER_UNKNOWN_OPTION
+ eng "Unknown option '%-.64s'"
+ER_BAD_OPTION_VALUE
+ eng "Incorrect value '%-.64s' for option '%-.64s'"
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp.cc 2010-04-06 00:06:09 +0000
@@ -147,7 +147,8 @@
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY',"
+ "'NO_UNSIGNED_SUBTRACTION',"
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-04-01 09:04:26 +0000
+++ b/sql/sp_head.cc 2010-04-06 00:06:09 +0000
@@ -2218,7 +2218,7 @@
lex->charset ? lex->charset :
thd->variables.collation_database,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, NULL))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-04-02 18:51:02 +0000
+++ b/sql/sql_class.cc 2010-04-06 00:06:09 +0000
@@ -106,6 +106,7 @@
key_create_info(rhs.key_create_info),
columns(rhs.columns, mem_root),
name(rhs.name),
+ option_list(rhs.option_list),
generated(rhs.generated)
{
list_copy_and_replace_each_value(columns, mem_root);
@@ -775,6 +776,7 @@
void THD::push_internal_handler(Internal_error_handler *handler)
{
+ DBUG_ENTER("THD::push_internal_handler");
if (m_internal_handler)
{
handler->m_prev_internal_handler= m_internal_handler;
@@ -784,6 +786,7 @@
{
m_internal_handler= handler;
}
+ DBUG_VOID_RETURN;
}
@@ -803,8 +806,10 @@
void THD::pop_internal_handler()
{
+ DBUG_ENTER("THD::pop_internal_handler");
DBUG_ASSERT(m_internal_handler != NULL);
m_internal_handler= m_internal_handler->m_prev_internal_handler;
+ DBUG_VOID_RETURN;
}
extern "C"
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-04-01 09:04:26 +0000
+++ b/sql/sql_class.h 2010-04-06 00:06:09 +0000
@@ -205,13 +205,15 @@
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
+ engine_option_value *option_list;
bool generated;
Key(enum Keytype type_par, const char *name_arg,
KEY_CREATE_INFO *key_info_arg,
- bool generated_arg, List<Key_part_spec> &cols)
+ bool generated_arg, List<Key_part_spec> &cols,
+ engine_option_value *create_opt)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
- name(name_arg), generated(generated_arg)
+ name(name_arg), option_list(create_opt), generated(generated_arg)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -240,7 +242,7 @@
Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
- :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_insert.cc 2010-04-06 00:06:09 +0000
@@ -72,15 +72,6 @@
#endif
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
-/* Define to force use of my_malloc() if the allocated memory block is big */
-
-#ifndef HAVE_ALLOCA
-#define my_safe_alloca(size, min_length) my_alloca(size)
-#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
-#else
-#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
-#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
-#endif
/*
Check that insert/update fields are from the same single table of a view.
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-03-29 15:13:53 +0000
+++ b/sql/sql_lex.h 2010-04-06 00:06:09 +0000
@@ -1749,6 +1749,11 @@
const char *stmt_definition_end;
/**
+ Collects create options for Field and KEY
+ */
+ engine_option_value *option_list, *option_list_last;
+
+ /**
During name resolution search only in the table list given by
Name_resolution_context::first_name_resolution_table and
Name_resolution_context::last_name_resolution_table
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_parse.cc 2010-04-06 00:06:09 +0000
@@ -6086,7 +6086,8 @@
char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info)
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6104,7 +6105,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::PRIMARY, NullS,
&default_key_create_info,
- 0, lex->col_list);
+ 0, lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6114,7 +6115,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
- lex->col_list);
+ lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6172,7 +6173,8 @@
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, vcol_info))
+ interval_list, cs, uint_geom_type, vcol_info,
+ create_options))
DBUG_RETURN(1);
lex->alter_info.create_list.push_back(new_field);
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-04-02 09:20:09 +0000
+++ b/sql/sql_show.cc 2010-04-06 00:06:09 +0000
@@ -981,6 +981,30 @@
DBUG_RETURN(0);
}
+
+/**
+ Goes through all character combinations and ensure that it is number.
+
+ @param name attribute name
+ @param name_length length of name
+
+ @retval # Pointer to conflicting character
+ @retval 0 No conflicting character
+*/
+
+static const char *is_unsigned_number(const char *name, uint name_length)
+{
+ const char *end= name + name_length;
+
+ for (; name < end ; name++)
+ {
+ uchar chr= (uchar) *name;
+ if (chr < '0' || chr > '9')
+ return name;
+ }
+ return 0;
+}
+
/*
Go through all character combinations and ensure that sql_lex.cc can
parse it as an identifier.
@@ -1043,7 +1067,7 @@
/*
The identifier must be quoted as it includes a quote character or
- it's a keyword
+ it's a keyword
*/
VOID(packet->reserve(length*2 + 2));
@@ -1106,7 +1130,6 @@
return '`';
}
-
/* Append directory name (if exists) to CREATE INFO */
static void append_directory(THD *thd, String *packet, const char *dir_type,
@@ -1203,6 +1226,32 @@
return has_default;
}
+
+/**
+ Appends list of options to string
+
+ @param thd thread handler
+ @param packet string to append
+ @param opt list of options
+*/
+
+static void append_create_options(THD *thd, String *packet,
+ engine_option_value *opt)
+{
+ for(; opt; opt= opt->next)
+ {
+ DBUG_ASSERT(opt->value.str);
+ packet->append(' ');
+ append_identifier(thd, packet, opt->name.str, opt->name.length);
+ packet->append('=');
+ if (!opt->quoted_value && opt->value.length < 21 &&
+ is_unsigned_number(opt->value.str, opt->value.length) == NULL)
+ packet->append(opt->value.str, opt->value.length);
+ else
+ append_unescaped(packet, opt->value.str, opt->value.length);
+ }
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1385,6 +1434,8 @@
packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
+ if (field->option_list)
+ append_create_options(thd, packet, field->option_list);
}
key_info= table->key_info;
@@ -1456,6 +1507,8 @@
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
}
+ if (key_info->option_list)
+ append_create_options(thd, packet, key_info->option_list);
}
/*
@@ -1615,6 +1668,10 @@
packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
+ /* create_table_options can be NULL for temporary tables */
+ if (share->option_list)
+ append_create_options(thd, packet,
+ share->option_list);
append_directory(thd, packet, "DATA", create_info.data_file_name);
append_directory(thd, packet, "INDEX", create_info.index_file_name);
}
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-04-01 09:04:26 +0000
+++ b/sql/sql_table.cc 2010-04-06 00:06:09 +0000
@@ -2863,6 +2863,11 @@
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
+ if (parse_option_list(thd, &sql_field->option_struct,
+ sql_field->option_list,
+ create_info->db_type->field_opt_rules, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
/*
For now skip fields that are not physically stored in the database
(virtual fields) and update their offset later
@@ -3061,6 +3066,12 @@
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
key_info->algorithm= key->key_create_info.algorithm;
+ key_info->option_list= key->option_list;
+ if (parse_option_list(thd, &key_info->option_struct,
+ key_info->option_list,
+ create_info->db_type->key_opt_rules, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
if (key->type == Key::FULLTEXT)
{
@@ -3438,6 +3449,12 @@
}
}
+ if (parse_option_list(thd, &create_info->option_struct,
+ create_info->option_list,
+ create_info->db_type->table_opt_rules, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
+
DBUG_RETURN(FALSE);
}
@@ -5679,6 +5696,7 @@
KEY_PART_INFO *key_part;
KEY_PART_INFO *end;
THD *thd= table->in_use;
+ uint i;
/*
Remember if the new definition has new VARCHAR column;
create_info->varchar will be reset in mysql_prepare_create_table.
@@ -5769,6 +5787,43 @@
DBUG_RETURN(0);
}
+ create_info->fields= table->s->fields;
+ create_info->keys= table->s->keys;
+ /*if (!(create_info->old_new_fileds_option_struct[0]=
+ (void**)thd->alloc(sizeof(void*) * 2 * (create_info->fields) +
+ sizeof(void*) * 2 * (create_info->keys))))
+ DBUG_RETURN(1);
+ bzero(create_info->old_new_fileds_option_struct[0],
+ sizeof(void*) * 2 * (create_info->fields) +
+ sizeof(void*) * 2 * (create_info->keys));
+ create_info->old_new_fileds_option_struct[1]=
+ create_info->old_new_fileds_option_struct[0] +
+ sizeof(void*) * (create_info->fields);
+ create_info->old_new_keys_option_struct[0]=
+ create_info->old_new_fileds_option_struct[1] +
+ sizeof(void*) * (create_info->fields);
+ create_info->old_new_keys_option_struct[1]=
+ create_info->old_new_keys_option_struct[0] +
+ sizeof(void*) * (create_info->keys);
+ */
+ if ((create_info->old_new_fileds_option_struct[0]=
+ (void**)thd->alloc(sizeof(void*) * create_info->fields)) == NULL ||
+ (create_info->old_new_fileds_option_struct[1]=
+ (void**)thd->alloc(sizeof(void*) * create_info->fields)) == NULL ||
+ (create_info->old_new_keys_option_struct[0]=
+ (void**)thd->alloc(sizeof(void*) * create_info->keys)) == NULL ||
+ (create_info->old_new_keys_option_struct[1]=
+ (void**)thd->alloc(sizeof(void*) * create_info->keys)) == NULL)
+ DBUG_RETURN(1);
+ bzero(create_info->old_new_fileds_option_struct[0],
+ sizeof(void*) * create_info->fields);
+ bzero(create_info->old_new_fileds_option_struct[1],
+ sizeof(void*) * create_info->fields);
+ bzero(create_info->old_new_keys_option_struct[0],
+ sizeof(void*) * create_info->keys);
+ bzero(create_info->old_new_keys_option_struct[1],
+ sizeof(void*) * create_info->keys);
+
/*
Use transformed info to evaluate possibility of fast ALTER TABLE
but use the preserved field to persist modifications.
@@ -5779,12 +5834,16 @@
/* Go through fields and check if the original ones are compatible
with new table.
*/
- for (f_ptr= table->field, new_field= new_field_it++,
+ for (i= 0, f_ptr= table->field, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++;
(field= *f_ptr);
+ i++,
f_ptr++, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++)
{
+ DBUG_ASSERT(i < create_info->fields);
+ create_info->old_new_fileds_option_struct[0][i]= field->option_struct;
+
/* Make sure we have at least the default charset in use. */
if (!new_field->charset)
new_field->charset= create_info->default_table_charset;
@@ -5811,6 +5870,10 @@
DBUG_RETURN(0);
}
+ /* to allow check_if_incompatible_data compare */
+ create_info->old_new_fileds_option_struct[1][i]=
+ tmp_new_field->option_struct;
+
/* 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) ||
@@ -5854,11 +5917,15 @@
*index_drop_count= 0;
*index_add_count= 0;
*candidate_key_count= 0;
- for (table_key= table->key_info; table_key < table_key_end; table_key++)
+ for (i= 0,table_key= table->key_info;
+ table_key < table_key_end;
+ i++, table_key++)
{
KEY_PART_INFO *table_part;
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
KEY_PART_INFO *new_part;
+ DBUG_ASSERT(i < create_info->keys);
+ create_info->old_new_keys_option_struct[0][i]= table_key->option_struct;
/*
Check if key is a candidate key, i.e. a unique index with no index
@@ -5938,7 +6005,9 @@
for (new_key= *key_info_buffer; new_key < new_key_end; new_key++)
{
/* Search an old key with the same name. */
- for (table_key= table->key_info; table_key < table_key_end; table_key++)
+ for (i= 0, table_key= table->key_info;
+ table_key < table_key_end;
+ i++, table_key++)
{
if (! strcmp(table_key->name, new_key->name))
break;
@@ -5957,9 +6026,16 @@
}
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
}
+ else
+ {
+ DBUG_ASSERT(i < create_info->keys);
+ create_info->old_new_keys_option_struct[1][i]=
+ new_key->option_struct;
+ }
}
/* Check if changes are compatible with current handler without a copy */
+ create_info->old_option_struct= table->s->option_struct;
if (table->file->check_if_incompatible_data(create_info, changes))
{
DBUG_PRINT("info", ("check_if_incompatible_data() -> "
@@ -6132,6 +6208,16 @@
}
restore_record(table, s->default_values); // Empty record for DEFAULT
+ if (create_info->option_list)
+ {
+ create_info->option_list=
+ merge_engine_table_options(table->s->option_list,
+ create_info->option_list,
+ thd->mem_root);
+ }
+ else
+ create_info->option_list= table->s->option_list;
+
/*
First collect all fields from table which isn't in drop_list
*/
@@ -6384,7 +6470,7 @@
key= new Key(key_type, key_name,
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts);
+ key_parts, key_info->option_list);
new_key_list.push_back(key);
}
}
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2010-03-30 12:36:49 +0000
+++ b/sql/sql_view.cc 2010-04-06 00:06:09 +0000
@@ -1185,7 +1185,7 @@
+ MODE_PIPES_AS_CONCAT affect expression parsing
+ MODE_ANSI_QUOTES affect expression parsing
+ MODE_IGNORE_SPACE affect expression parsing
- - MODE_NOT_USED not used :)
+ - MODE_CREATE_OPTIONS_NOERR affect only CREATE/ALTER TABLE parsing
* MODE_ONLY_FULL_GROUP_BY affect execution
* MODE_NO_UNSIGNED_SUBTRACTION affect execution
- MODE_NO_DIR_IN_CREATE affect table creation only
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-04-01 09:04:26 +0000
+++ b/sql/sql_yacc.yy 2010-04-06 00:06:09 +0000
@@ -608,6 +608,7 @@
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change= NullS;
+ lex->option_list= lex->option_list_last= NULL;
return FALSE;
}
@@ -617,7 +618,7 @@
{
Key *key;
key= new Key(type, name, info ? info : &lex->key_create_info, generated,
- lex->col_list);
+ lex->col_list, lex->option_list);
if (key == NULL)
return TRUE;
@@ -3898,7 +3899,11 @@
;
create2a:
- field_list ')' opt_create_table_options
+ field_list ')'
+ {
+ Lex->create_info.option_list= Lex->option_list_last= NULL;
+ }
+ opt_create_table_options
opt_partitioning
create3 {}
| opt_partitioning
@@ -4751,6 +4756,39 @@
Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
Lex->create_info.transactional= $3;
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
;
default_charset:
@@ -4872,25 +4910,33 @@
;
key_def:
- normal_key_type opt_ident key_alg '(' key_list ')' normal_key_options
+ normal_key_type opt_ident key_alg '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $1, $2))
MYSQL_YYABORT;
}
| fulltext opt_key_or_index opt_ident init_key_options
- '(' key_list ')' fulltext_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ fulltext_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| spatial opt_key_or_index opt_ident init_key_options
- '(' key_list ')' spatial_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ spatial_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| opt_constraint constraint_key_type opt_ident key_alg
- '(' key_list ')' normal_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $2, $3 ? $3 : $1))
MYSQL_YYABORT;
@@ -4953,6 +4999,7 @@
lex->comment=null_lex_str;
lex->charset=NULL;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
field_def
{
@@ -4963,7 +5010,7 @@
&lex->comment,
lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
;
@@ -5383,6 +5430,39 @@
Lex->charset=$2;
}
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
;
now_or_signed_literal:
@@ -5672,6 +5752,39 @@
all_key_opt:
KEY_BLOCK_SIZE opt_equal ulong_num
{ Lex->key_create_info.block_size= $3; }
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
;
normal_key_opt:
@@ -6161,6 +6274,7 @@
LEX *lex=Lex;
lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->option_list= lex->option_list_last= NULL;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -6172,6 +6286,7 @@
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
field_def
{
@@ -6183,7 +6298,7 @@
&lex->comment,
$3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
opt_place
@@ -6290,8 +6405,7 @@
}
| create_table_options_space_separated
{
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_OPTIONS;
+ Lex->alter_info.flags|= ALTER_OPTIONS;
}
| FORCE_SYM
{
@@ -13651,6 +13765,7 @@
lex->interval_list.empty();
lex->type= 0;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
type /* $11 */
{ /* $12 */
@@ -13901,6 +14016,7 @@
}
;
+
/**
@} (end of group Parser)
*/
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2010-03-29 15:13:53 +0000
+++ b/sql/structs.h 2010-04-06 00:06:09 +0000
@@ -68,6 +68,7 @@
uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;
+class engine_option_value;
typedef struct st_key {
uint key_length; /* Tot length of key */
@@ -101,6 +102,9 @@
int bdb_return_if_eq;
} handler;
struct st_table *table;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
} KEY;
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2010-03-29 15:13:53 +0000
+++ b/sql/table.cc 2010-04-06 00:06:09 +0000
@@ -667,12 +667,13 @@
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 extra_rec_buf_length, options_len;
uint i,j;
bool use_hash;
char *keynames, *names, *comment_pos, *vcol_screen_pos;
uchar *record;
- uchar *disk_buff, *strpos, *null_flags, *null_pos;
+ uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+ uchar *buff= 0;
ulong pos, record_offset, *rec_per_key, rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -788,7 +789,6 @@
for (i=0 ; i < keys ; i++, keyinfo++)
{
- keyinfo->table= 0; // Updated in open_frm
if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -858,15 +858,14 @@
if ((n_length= uint4korr(head+55)))
{
/* Read extra data segment */
- uchar *buff, *next_chunk, *buff_end;
+ uchar *next_chunk, *buff_end;
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
goto err;
if (my_pread(file, buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
share->connect_string.length= uint2korr(buff);
if (!(share->connect_string.str= strmake_root(&share->mem_root,
@@ -874,8 +873,7 @@
share->connect_string.
length)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
next_chunk+= share->connect_string.length + 2;
buff_end= buff + n_length;
@@ -895,8 +893,7 @@
plugin_data(tmp_plugin, handlerton *)))
{
/* bad file, legacy_db_type did not match the name */
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
/*
tmp_plugin is locked with a local lock.
@@ -925,8 +922,7 @@
error= 8;
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
@@ -940,8 +936,7 @@
/* purecov: begin inspected */
error= 8;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
/* purecov: end */
}
next_chunk+= str_db_type_length + 2;
@@ -957,16 +952,14 @@
memdup_root(&share->mem_root, next_chunk + 4,
partition_info_len + 1)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
#else
if (partition_info_len)
{
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
#endif
next_chunk+= 5 + partition_info_len;
@@ -992,6 +985,16 @@
#endif
next_chunk++;
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ /*
+ store options position, but skip till the time we will
+ know number of fields
+ */
+ options_len= uint4korr(next_chunk);
+ options= next_chunk + 4;
+ next_chunk+= options_len + 4;
+ }
keyinfo= share->key_info;
for (i= 0; i < keys; i++, keyinfo++)
{
@@ -1002,8 +1005,7 @@
{
DBUG_PRINT("error",
("fulltext key uses parser that is not defined in .frm"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
parser_name.str= (char*) next_chunk;
parser_name.length= strlen((char*) next_chunk);
@@ -1013,12 +1015,10 @@
if (! keyinfo->parser)
{
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
}
- my_free(buff, MYF(0));
}
share->key_block_size= uint2korr(head+62);
@@ -1028,21 +1028,21 @@
share->rec_buff_length= rec_buff_length;
if (!(record= (uchar *) alloc_root(&share->mem_root,
rec_buff_length)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->default_values= record;
if (my_pread(file, record, (size_t) share->reclength,
record_offset, MYF(MY_NABP)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file, head,288,MYF(MY_NABP)))
- goto err;
+ goto free_and_err;
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err; // Wrong password
+ goto free_and_err; // Wrong password
}
#endif
@@ -1062,6 +1062,8 @@
share->comment.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*)+
@@ -1070,14 +1072,14 @@
keys+3)*sizeof(char *)+
(n_length+int_length+com_length+
vcol_screen_length)))))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->field= field_ptr;
read_length=(uint) (share->fields * field_pack_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 */
+ goto free_and_err; /* purecov: inspected */
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
@@ -1104,7 +1106,7 @@
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
if (share->fieldnames.count != share->fields)
- goto err;
+ goto free_and_err;
fix_type_pointers(&interval_array, share->intervals, interval_count,
&names);
@@ -1118,7 +1120,7 @@
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
count)))
- goto err;
+ goto free_and_err;
for (count= 0; count < interval->count; count++)
{
char *val= (char*) interval->type_names[count];
@@ -1134,7 +1136,7 @@
/* Allocate handler */
if (!(handler_file= get_new_handler(share, thd->mem_root,
share->db_type())))
- goto err;
+ goto free_and_err;
record= share->default_values-1; /* Fieldstart = 1 */
if (share->null_field_first)
@@ -1196,7 +1198,7 @@
charset= &my_charset_bin;
#else
error= 4; // unsupported field type
- goto err;
+ goto free_and_err;
#endif
}
else
@@ -1207,7 +1209,7 @@
{
error= 5; // Unknown or unavailable charset
errarg= (int) strpos[14];
- goto err;
+ goto free_and_err;
}
}
@@ -1247,7 +1249,7 @@
if ((uint)vcol_screen_pos[0] != 1)
{
error= 4;
- goto err;
+ goto free_and_err;
}
field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
fld_stored_in_db= (bool) (uint) vcol_screen_pos[2];
@@ -1256,7 +1258,7 @@
(char *)memdup_root(&share->mem_root,
vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE,
vcol_expr_length)))
- goto err;
+ goto free_and_err;
vcol_info->expr_str.length= vcol_expr_length;
vcol_screen_pos+= vcol_info_length;
share->vfields++;
@@ -1346,7 +1348,7 @@
if (!reg_field) // Not supported field type
{
error= 4;
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
}
reg_field->field_index= i;
@@ -1385,7 +1387,7 @@
sent (OOM).
*/
error= 8;
- goto err;
+ goto free_and_err;
}
}
if (!reg_field->stored_in_db)
@@ -1462,7 +1464,7 @@
if (!key_part->fieldnr)
{
error= 4; // Wrong file
- goto err;
+ goto free_and_err;
}
field= key_part->field= share->field[key_part->fieldnr-1];
key_part->type= field->key_type();
@@ -1627,6 +1629,15 @@
null_length, 255);
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ DBUG_ASSERT(options_len);
+ if (engine_table_options_frm_read(options, options_len, share) ||
+ parse_engine_table_options(thd, handler_file->ht, share))
+ goto free_and_err;
+ }
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
if (share->found_next_number_field)
{
reg_field= *share->found_next_number_field;
@@ -1685,6 +1696,8 @@
#endif
DBUG_RETURN (0);
+ free_and_err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
err:
share->error= error;
share->open_errno= my_errno;
@@ -2883,6 +2896,7 @@
ulong length;
uchar fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
+ DBUG_ENTER("create_frm");
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2964,7 +2978,7 @@
{
VOID(my_close(file,MYF(0)));
VOID(my_delete(name,MYF(0)));
- return(-1);
+ DBUG_RETURN(-1);
}
}
}
@@ -2975,7 +2989,7 @@
else
my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
}
- return (file);
+ DBUG_RETURN(file);
} /* create_frm */
@@ -2994,6 +3008,7 @@
create_info->comment= share->comment;
create_info->transactional= share->transactional;
create_info->page_checksum= share->page_checksum;
+ create_info->option_list= share->option_list;
DBUG_VOID_RETURN;
}
=== modified file 'sql/table.h'
--- a/sql/table.h 2010-02-12 08:47:31 +0000
+++ b/sql/table.h 2010-04-06 00:06:09 +0000
@@ -340,6 +340,8 @@
#ifdef NOT_YET
struct st_table *open_tables; /* link to open tables */
#endif
+ engine_option_value *option_list; /* text options for table */
+ void *option_struct; /* structure with parsed options */
/* The following is copied to each TABLE on OPEN */
Field **field;
=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc 2010-01-04 17:54:42 +0000
+++ b/sql/unireg.cc 2010-04-06 00:06:09 +0000
@@ -29,6 +29,9 @@
#define FCOMP 17 /* Bytes for a packed field */
+/* max length of options in frm which be allocated on stack */
+#define OPTIONS_ON_STACK 256
+
static uchar * pack_screens(List<Create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
@@ -46,6 +49,18 @@
uint reclength, ulong data_offset,
handler *handler);
+/*
+ We declare engine_table_options_frm_length end
+ engine_table_options_frm_image here because
+ List, Create_field, KEY are not declared in create_options.h
+*/
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
/**
An interceptor to hijack ER_TOO_MANY_FIELDS error from
pack_screens and retry again without UNIREG screens.
@@ -75,6 +90,7 @@
return is_handled;
}
+
/*
Create a frm (table definition) file
@@ -107,6 +123,7 @@
ulong key_buff_length;
File file;
ulong filepos, data_offset;
+ uint options_len;
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
@@ -183,6 +200,16 @@
create_info->extra_size+= key_info[i].parser_name->length + 1;
}
+ options_len= engine_table_options_frm_length(create_info->option_list,
+ create_fields,
+ keys, key_info);
+ DBUG_PRINT("info", ("Options length: %u", options_len));
+ if (options_len)
+ {
+ create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+ create_info->extra_size+= (options_len + 4);
+ }
+
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
{
@@ -294,6 +321,25 @@
if (my_write(file, (uchar*) buff, 6, MYF_RW))
goto err;
}
+
+ if (options_len)
+ {
+ uchar *optbuff= (uchar *)my_safe_alloca(options_len + 4, OPTIONS_ON_STACK);
+ my_bool error;
+ DBUG_PRINT("info", ("Create options length: %u", options_len));
+ if (!optbuff)
+ goto err;
+ int4store(optbuff, options_len);
+ engine_table_options_frm_image(optbuff + 4,
+ create_info->option_list,
+ create_fields,
+ keys, key_info);
+ error= my_write(file, optbuff, options_len + 4, MYF_RW);
+ my_safe_afree(optbuff, options_len + 4, OPTIONS_ON_STACK);
+ if (error)
+ goto err;
+ }
+
for (i= 0; i < keys; i++)
{
if (key_info[i].parser_name)
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-04-01 14:34:51 +0000
+++ b/storage/example/ha_example.cc 2010-04-06 00:06:09 +0000
@@ -113,6 +113,47 @@
/* The mutex used to init the hash; variable for example share methods */
pthread_mutex_t example_mutex;
+
+/**
+ structure for CREATE TABLE options (table options)
+*/
+
+struct example_table_options_struct
+{
+ const char *strparam;
+ ulonglong ullparam;
+ uint enumparam;
+ bool boolparam;
+};
+
+
+/**
+ structure for CREATE TABLE options (table options)
+*/
+
+struct example_field_options_struct
+{
+ const char *compex_param_to_parse_it_in_engine;
+};
+
+#define ha_table_option_struct example_table_options_struct
+ha_create_table_option example_table_option_list[]=
+{
+ HA_TOPTION_ULL("ULL", ullparam, UINT_MAX32, 0, UINT_MAX32, 1),
+ HA_TOPTION_STRING("STR", strparam),
+ HA_TOPTION_ENUM("one_or_two", enumparam, "one,two", 0),
+ HA_TOPTION_BOOL("YESNO", boolparam, 1),
+ HA_TOPTION_END
+};
+
+#define ha_field_option_struct example_field_options_struct
+ha_create_table_option example_field_option_list[]=
+{
+ HA_FOPTION_STRING("COMPLEX", compex_param_to_parse_it_in_engine),
+ HA_FOPTION_END
+};
+
+
/**
@brief
Function we use in the creation of our hash to get key.
@@ -138,6 +179,9 @@
example_hton->state= SHOW_OPTION_YES;
example_hton->create= example_create_handler;
example_hton->flags= HTON_CAN_RECREATE;
+ example_hton->table_opt_rules= example_table_option_list;
+ example_hton->field_opt_rules= example_field_option_list;
+ example_hton->key_opt_rules= NULL;
DBUG_RETURN(0);
}
@@ -774,27 +818,6 @@
/**
@brief
- Renames a table from one name to another via an alter table call.
-
- @details
- If you do not implement this, the default rename_table() is called from
- handler.cc and it will delete all files with the file extensions returned
- by bas_ext().
-
- Called from sql_table.cc by mysql_rename_table().
-
- @see
- mysql_rename_table() in sql_table.cc
-*/
-int ha_example::rename_table(const char * from, const char * to)
-{
- DBUG_ENTER("ha_example::rename_table ");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/**
- @brief
Given a starting key and an ending key, estimate the number of rows that
will exist between the two keys.
@@ -836,15 +859,110 @@
int ha_example::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
+ example_table_options_struct *prm=
+ (example_table_options_struct *)table_arg->s->option_struct;
DBUG_ENTER("ha_example::create");
/*
- This is not implemented but we want someone to be able to see that it
- works.
+ This example shows how to support custom engine specific table and field
+ options.
*/
+ DBUG_ASSERT(prm);
+ DBUG_PRINT("info", ("strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prm->strparam ? prm->strparam : "<NULL>"),
+ prm->ullparam, prm->enumparam, prm->boolparam));
+ for (Field **field= table_arg->s->field; *field; field++)
+ {
+ example_field_options_struct *fprm=
+ (example_field_options_struct *)(*field)->option_struct;
+ DBUG_ASSERT(fprm);
+ DBUG_PRINT("info", ("field: %s complex: '%-.64s'",
+ (*field)->field_name,
+ (fprm->compex_param_to_parse_it_in_engine ?
+ fprm->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+
+ }
+
DBUG_RETURN(0);
}
+/**
+ check_if_incompatible_data() called if ALTER TABLE can't detect otherwise
+ if new and old definition are compatible
+
+ @details If there are no other explicit signs like changed number of
+ fields this function will be called by compare_tables()
+ (sql/sql_tables.cc) to decide should we rewrite whole table or only .frm
+ file.
+
+*/
+
+bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes)
+{
+ example_table_options_struct *prmo, *prmn;
+ uint i;
+ DBUG_ENTER("ha_example::check_if_incompatible_data");
+ DBUG_ASSERT(info->option_struct);
+ DBUG_ASSERT(info->old_option_struct);
+ /*
+ This example shows how custom engine specific table and field
+ options can be accessed from this function to be compared.
+ */
+
+ prmn= (example_table_options_struct *)info->option_struct;
+ DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prmn->strparam ? prmn->strparam : "<NULL>"),
+ prmn->ullparam, prmn->enumparam, prmn->boolparam));
+
+ prmo= (example_table_options_struct *)info->old_option_struct;
+ DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prmo->strparam ? prmo->strparam : "<NULL>"),
+ prmo->ullparam, prmo->enumparam, prmo->boolparam));
+
+ /* check important parameters */
+ if (prmn->ullparam != prmo->ullparam || prmn->boolparam != prmo->boolparam)
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+
+ for (i= 0; i < info->fields; i++)
+ {
+ example_field_options_struct *fprmo, *fprmn;
+ if (info->old_new_fileds_option_struct[1][i])
+ {
+ fprmn=
+ (example_field_options_struct *)
+ info->old_new_fileds_option_struct[1][i];
+ DBUG_PRINT("info", ("old field: %u new complex: '%-.64s'", i,
+ (fprmn->compex_param_to_parse_it_in_engine ?
+ fprmn->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ /*
+ if (!structure_is_the_same(fprmn->compex_param_to_parse_it_in_engine,
+ fprmo->compex_param_to_parse_it_in_engine)
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+ */
+ }
+ else
+ DBUG_PRINT("info", ("old field %i did not changed", i));
+
+ fprmo=
+ (example_field_options_struct *)info->old_new_fileds_option_struct[0][i];
+ DBUG_ASSERT(fprmo);
+ DBUG_PRINT("info", ("old field: %u old complex: '%-.64s'", i,
+ (fprmo->compex_param_to_parse_it_in_engine ?
+ fprmo->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ }
+
+ DBUG_RETURN(COMPATIBLE_DATA_YES);
+}
+
+
+
struct st_mysql_storage_engine example_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
=== modified file 'storage/example/ha_example.h'
--- a/storage/example/ha_example.h 2010-03-28 18:10:00 +0000
+++ b/storage/example/ha_example.h 2010-04-06 00:06:09 +0000
@@ -243,9 +243,10 @@
ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
- int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required
+ bool check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required
=== modified file 'storage/pbxt/src/discover_xt.cc'
--- a/storage/pbxt/src/discover_xt.cc 2010-02-01 06:14:12 +0000
+++ b/storage/pbxt/src/discover_xt.cc 2010-04-06 00:06:09 +0000
@@ -1623,7 +1623,7 @@
#endif
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/,
- NULL /*vcol_info*/))
+ NULL /*vcol_info*/, NULL /* create options */))
#endif
goto error;
1
0

[Maria-developers] bzr commit into file:///home/tsk/mprog/src/5.3-subqueries/ branch (timour:2789)
by timour@askmonty.org 05 Apr '10
by timour@askmonty.org 05 Apr '10
05 Apr '10
#At file:///home/tsk/mprog/src/5.3-subqueries/ based on revid:timour@askmonty.org-20100402142706-klcgi39tjzhvy22z
2789 timour(a)askmonty.org 2010-04-06
Fixed a problem where the temp table of a materialized subquery
was not cleaned up between PS re-executions. The reason was two-fold:
- a merge with mysql-6.0 missed select_union::cleanup() that should
have cleaned up the temp table, and
- the subclass of select_union used by materialization didn't call
the base class cleanup() method.
modified:
mysql-test/r/subselect_mat.result
mysql-test/t/subselect_mat.test
sql/sql_class.cc
sql/sql_class.h
sql/sql_union.cc
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect_mat.result 2010-04-05 21:15:15 +0000
@@ -1246,3 +1246,29 @@ i
4
set session optimizer_switch=@save_optimizer_switch;
drop table t1, t2, t3;
+create table t0 (a int);
+insert into t0 values (0),(1),(2);
+create table t1 (a int);
+insert into t1 values (0),(1),(2);
+explain select a, a in (select a from t1) from t0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 3
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
+select a, a in (select a from t1) from t0;
+a a in (select a from t1)
+0 1
+1 1
+2 1
+prepare s from 'select a, a in (select a from t1) from t0';
+execute s;
+a a in (select a from t1)
+0 1
+1 1
+2 1
+update t1 set a=123;
+execute s;
+a a in (select a from t1)
+0 0
+1 0
+2 0
+drop table t0, t1;
=== modified file 'mysql-test/t/subselect_mat.test'
--- a/mysql-test/t/subselect_mat.test 2010-03-13 20:04:52 +0000
+++ b/mysql-test/t/subselect_mat.test 2010-04-05 21:15:15 +0000
@@ -905,3 +905,19 @@ select * from t1 where t1.i in (select t
set session optimizer_switch=@save_optimizer_switch;
drop table t1, t2, t3;
+#
+# Test that the contentes of the temp table of a materialized subquery is
+# cleanup up between PS reexecutions.
+#
+
+create table t0 (a int);
+insert into t0 values (0),(1),(2);
+create table t1 (a int);
+insert into t1 values (0),(1),(2);
+explain select a, a in (select a from t1) from t0;
+select a, a in (select a from t1) from t0;
+prepare s from 'select a, a in (select a from t1) from t0';
+execute s;
+update t1 set a=123;
+execute s;
+drop table t0, t1;
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-20 12:01:47 +0000
+++ b/sql/sql_class.cc 2010-04-05 21:15:15 +0000
@@ -2942,8 +2942,7 @@ bool select_dumpvar::send_eof()
}
-bool
-select_materialize_with_stats::
+bool select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long)
@@ -2962,14 +2961,29 @@ create_result_table(THD *thd_arg, List<I
if (!stat)
return TRUE;
- cleanup();
-
+ reset();
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
return FALSE;
}
+void select_materialize_with_stats::reset()
+{
+ memset(col_stat, 0, table->s->fields * sizeof(Column_statistics));
+ max_nulls_in_row= 0;
+ count_rows= 0;
+}
+
+
+void select_materialize_with_stats::cleanup()
+{
+ reset();
+ select_union::cleanup();
+}
+
+
+
/**
Override select_union::send_data to analyze each row for NULLs and to
update null_statistics before sending data to the client.
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-20 12:01:47 +0000
+++ b/sql/sql_class.h 2010-04-05 21:15:15 +0000
@@ -2820,7 +2820,7 @@ public:
bool send_data(List<Item> &items);
bool send_eof();
bool flush();
-
+ void cleanup();
virtual bool create_result_table(THD *thd, List<Item> *column_types,
bool is_distinct, ulonglong options,
const char *alias, bool bit_fields_as_long);
@@ -2883,6 +2883,9 @@ protected:
*/
ha_rows count_rows;
+protected:
+ void reset();
+
public:
select_materialize_with_stats() {}
virtual bool create_result_table(THD *thd, List<Item> *column_types,
@@ -2890,12 +2893,7 @@ public:
const char *alias, bool bit_fields_as_long);
bool init_result_table(ulonglong select_options);
bool send_data(List<Item> &items);
- void cleanup()
- {
- memset(col_stat, 0, table->s->fields * sizeof(Column_statistics));
- max_nulls_in_row= 0;
- count_rows= 0;
- }
+ void cleanup();
ha_rows get_null_count_of_col(uint idx)
{
DBUG_ASSERT(idx < table->s->fields);
=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc 2010-03-20 12:01:47 +0000
+++ b/sql/sql_union.cc 2010-04-05 21:15:15 +0000
@@ -136,6 +136,22 @@ select_union::create_result_table(THD *t
}
+/**
+ Reset and empty the temporary table that stores the materialized query result.
+
+ @note The cleanup performed here is exactly the same as for the two temp
+ tables of JOIN - exec_tmp_table_[1 | 2].
+*/
+
+void select_union::cleanup()
+{
+ table->file->extra(HA_EXTRA_RESET_STATE);
+ table->file->ha_delete_all_rows();
+ free_io_cache(table);
+ filesort_free_buffers(table,0);
+}
+
+
/*
initialization procedures before fake_select_lex preparation()
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2749)
by Igor Babaev 05 Apr '10
by Igor Babaev 05 Apr '10
05 Apr '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100403201935-gg9tnu4bxe73i7yk
2749 Igor Babaev 2010-04-05 [merge]
Merge with the latest changes of 5.2.
modified:
mysql-test/r/connect.result
mysql-test/t/connect.test
sql/sql_acl.cc
=== modified file 'mysql-test/r/connect.result'
--- a/mysql-test/r/connect.result 2009-04-25 09:04:38 +0000
+++ b/mysql-test/r/connect.result 2010-04-05 09:50:31 +0000
@@ -225,3 +225,17 @@ Connection on extra port 2 ok
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
+CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
+CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
+connect(localhost,mysqltest_up1,foo,test,13001,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'mysqltest_up1'@'localhost' (using password: YES)
+select user(), current_user();
+user() current_user()
+mysqltest_up1@localhost mysqltest_up1@%
+connect(localhost,mysqltest_up2,newpw,test,13001,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'mysqltest_up2'@'localhost' (using password: YES)
+select user(), current_user();
+user() current_user()
+mysqltest_up2@localhost mysqltest_up2@%
+DROP USER mysqltest_up1@'%';
+DROP USER mysqltest_up2@'%';
=== modified file 'mysql-test/t/connect.test'
--- a/mysql-test/t/connect.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/connect.test 2010-04-05 09:50:31 +0000
@@ -328,6 +328,34 @@ if ($error)
--disconnect extracon2
--connection default
+#
+# A couple of plugin tests - for builtin plugins only
+#
+CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
+CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
+
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect(pcon1,localhost,mysqltest_up1,foo,,$MASTER_EXTRA_PORT,);
+
+connect(pcon2,localhost,mysqltest_up1,bar,,$MASTER_EXTRA_PORT,);
+connection pcon2;
+select user(), current_user();
+disconnect pcon2;
+
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect(pcon3,localhost,mysqltest_up2,newpw,,$MASTER_EXTRA_PORT,);
+
+connect(pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_EXTRA_PORT,);
+connection pcon4;
+select user(), current_user();
+disconnect pcon4;
+
+connection default;
+DROP USER mysqltest_up1@'%';
+DROP USER mysqltest_up2@'%';
+
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-04-02 20:08:40 +0000
+++ b/sql/sql_acl.cc 2010-04-05 09:50:31 +0000
@@ -319,6 +319,35 @@ set_user_salt(ACL_USER *acl_user, const
acl_user->salt_len= 0;
}
+/**
+ Fix ACL::plugin pointer to point to a hard-coded string, if appropriate
+
+ Make sure that if ACL_USER's plugin is a built-in, then it points
+ to a hard coded string, not to an allocated copy. Run-time, for
+ authentication, we want to be able to detect built-ins by comparing
+ pointers, not strings.
+
+ Additionally - update the salt if the plugin is built-in.
+
+ @retval 0 the pointers were fixed
+ @retval 1 this ACL_USER uses a not built-in plugin
+*/
+static bool fix_user_plugin_ptr(ACL_USER *user)
+{
+ if (my_strcasecmp(system_charset_info, user->plugin.str,
+ native_password_plugin_name.str) == 0)
+ user->plugin= native_password_plugin_name;
+ else
+ if (my_strcasecmp(system_charset_info, user->plugin.str,
+ old_password_plugin_name.str) == 0)
+ user->plugin= old_password_plugin_name;
+ else
+ return true;
+
+ set_user_salt(user, user->auth_string.str, user->auth_string.length);
+ return false;
+}
+
/*
This after_update function is used when user.password is less than
SCRAMBLE_LENGTH bytes.
@@ -662,6 +691,8 @@ static my_bool acl_load(THD *thd, TABLE_
char *tmpstr= get_field(&mem, table->field[next_field++]);
if (tmpstr)
{
+ user.plugin.str= tmpstr;
+ user.plugin.length= strlen(user.plugin.str);
if (user.auth_string.length)
{
sql_print_warning("'user' entry '%s@%s' has both a password "
@@ -670,22 +701,12 @@ static my_bool acl_load(THD *thd, TABLE_
user.user ? user.user : "",
user.host.hostname ? user.host.hostname : "");
}
- if (my_strcasecmp(system_charset_info, tmpstr,
- native_password_plugin_name.str) == 0)
- user.plugin= native_password_plugin_name;
- else
- if (my_strcasecmp(system_charset_info, tmpstr,
- old_password_plugin_name.str) == 0)
- user.plugin= old_password_plugin_name;
- else
- {
- user.plugin.str= tmpstr;
- user.plugin.length= strlen(tmpstr);
- }
user.auth_string.str= get_field(&mem, table->field[next_field++]);
if (!user.auth_string.str)
user.auth_string.str= const_cast<char*>("");
user.auth_string.length= strlen(user.auth_string.str);
+
+ fix_user_plugin_ptr(&user);
}
}
}
@@ -1132,12 +1153,15 @@ static void acl_update_user(const char *
{
if (plugin->str[0])
{
- acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
- acl_user->plugin.length= plugin->length;
+ acl_user->plugin= *plugin;
acl_user->auth_string.str= auth->str ?
strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
acl_user->auth_string.length= auth->length;
+ if (fix_user_plugin_ptr(acl_user))
+ acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
}
+ else
+ set_user_salt(acl_user, password, password_len);
acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
@@ -1157,8 +1181,6 @@ static void acl_update_user(const char *
acl_user->x509_subject= (x509_subject ?
strdup_root(&mem,x509_subject) : 0);
}
- if (password)
- set_user_salt(acl_user, password, password_len);
/* search complete: */
break;
}
@@ -1186,11 +1208,12 @@ static void acl_insert_user(const char *
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
if (plugin->str[0])
{
- acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
- acl_user.plugin.length= plugin->length;
+ acl_user.plugin= *plugin;
acl_user.auth_string.str= auth->str ?
strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
acl_user.auth_string.length= auth->length;
+ if (fix_user_plugin_ptr(&acl_user))
+ acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
}
else
{
@@ -1198,6 +1221,7 @@ static void acl_insert_user(const char *
old_password_plugin_name : native_password_plugin_name;
acl_user.auth_string.str= strmake_root(&mem, password, password_len);
acl_user.auth_string.length= password_len;
+ set_user_salt(&acl_user, password, password_len);
}
acl_user.access=privileges;
@@ -1210,8 +1234,6 @@ static void acl_insert_user(const char *
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
- set_user_salt(&acl_user, password, password_len);
-
VOID(push_dynamic(&acl_users,(uchar*) &acl_user));
if (!acl_user.host.hostname ||
(acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1]))
1
0

[Maria-developers] Rev 2788: MWL#90: Subqueries: Inside-out execution for non-semijoin materialized in file:///home/psergey/dev/maria-5.3-subqueries-r12/
by Sergey Petrunya 05 Apr '10
by Sergey Petrunya 05 Apr '10
05 Apr '10
At file:///home/psergey/dev/maria-5.3-subqueries-r12/
------------------------------------------------------------
revno: 2788
revision-id: psergey(a)askmonty.org-20100405201645-kuavh2rxc9whflc0
parent: psergey(a)askmonty.org-20100329200940-9ikx6gpww0gtsx00
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r12
timestamp: Tue 2010-04-06 00:16:45 +0400
message:
MWL#90: Subqueries: Inside-out execution for non-semijoin materialized
subqueries that are AND-parts of the WHERE
- First code (needs cleanup).
=== modified file 'mysql-test/include/mix1.inc'
--- a/mysql-test/include/mix1.inc 2010-03-20 12:01:47 +0000
+++ b/mysql-test/include/mix1.inc 2010-04-05 20:16:45 +0000
@@ -1522,6 +1522,12 @@
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
+--echo # MariaDB note:
+--echo # This will show 2 for table which has 5 rows.
+--echo # This is because the access method employed is actually range access
+--echo # which scans 2 records (yes, EXPLAIN displays it incorrectly).
+--echo # our correct printing is an artifact of changing in select_describe()
+--echo # from printing table->starts.records() to tab->records.
EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
@@ -1535,6 +1541,7 @@
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
+--echo # See above "MariaDB note"
EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
@@ -1549,6 +1556,7 @@
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
+--echo # See above "MariaDB note"
EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
=== modified file 'mysql-test/r/group_min_max.result'
--- a/mysql-test/r/group_min_max.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/r/group_min_max.result 2010-04-05 20:16:45 +0000
@@ -2255,7 +2255,8 @@
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL NULL NULL NULL NULL 8
+1 PRIMARY t1_outer ref a a 5 materialized subselect.max(b) 2 Using index
2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
=== modified file 'mysql-test/r/having.result'
--- a/mysql-test/r/having.result 2009-01-16 15:38:38 +0000
+++ b/mysql-test/r/having.result 2010-04-05 20:16:45 +0000
@@ -249,11 +249,11 @@
group by t2.col1, t2.col2 having t2.col1 <= 10);
col1
10
+10
+10
20
30
10
-10
-10
select t1.col1 from t1
where t1.col2 in
(select t2.col2 from t2
@@ -262,11 +262,11 @@
(select min(t3.col1) from t3));
col1
10
+10
+10
20
30
10
-10
-10
select t1.col1 from t1
where t1.col2 in
(select t2.col2 from t2
=== modified file 'mysql-test/r/innodb_mysql.result'
--- a/mysql-test/r/innodb_mysql.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/r/innodb_mysql.result 2010-04-05 20:16:45 +0000
@@ -1727,12 +1727,18 @@
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
1
1
+# MariaDB note:
+# This will show 2 for table which has 5 rows.
+# This is because the access method employed is actually range access
+# which scans 2 records (yes, EXPLAIN displays it incorrectly).
+# our correct printing is an artifact of changing in select_describe()
+# from printing table->starts.records() to tab->records.
EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
-2 DERIVED t1 index c3,c2 c2 10 NULL 5
+2 DERIVED t1 index c3,c2 c2 10 NULL 2
DROP TABLE t1;
CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3))
ENGINE=InnoDB;
@@ -1741,12 +1747,13 @@
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
1
1
+# See above "MariaDB note"
EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
-2 DERIVED t1 index c3,c2 c2 18 NULL 5
+2 DERIVED t1 index c3,c2 c2 18 NULL 2
DROP TABLE t1;
CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2),
KEY (c3), KEY (c2, c3))
@@ -1756,12 +1763,13 @@
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
1
1
+# See above "MariaDB note"
EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
-2 DERIVED t1 index c3,c2 c2 14 NULL 5
+2 DERIVED t1 index c3,c2 c2 14 NULL 2
DROP TABLE t1;
End of 5.1 tests
drop table if exists t1, t2, t3;
=== modified file 'mysql-test/r/partition.result'
--- a/mysql-test/r/partition.result 2010-03-04 08:03:07 +0000
+++ b/mysql-test/r/partition.result 2010-04-05 20:16:45 +0000
@@ -1382,7 +1382,7 @@
2
explain partitions select * from t1 where a is null or a < 0 or a > 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pn,p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 pn,p2 ALL NULL NULL NULL NULL 2 Using where
drop table t1;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, name VARCHAR(20))
ENGINE=MyISAM DEFAULT CHARSET=latin1
=== modified file 'mysql-test/r/partition_hash.result'
--- a/mysql-test/r/partition_hash.result 2008-07-07 20:42:19 +0000
+++ b/mysql-test/r/partition_hash.result 2010-04-05 20:16:45 +0000
@@ -69,25 +69,25 @@
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
explain partitions select * from t1 where a is null or (a >= 5 and a <= 7);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p2,p3 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0,p2,p3 ALL NULL NULL NULL NULL 7 Using where
explain partitions select * from t1 where a is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1 where a is not null;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
explain partitions select * from t1 where a >= 1 and a < 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 5 Using where
explain partitions select * from t1 where a >= 3 and a <= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a > 2 and a < 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 3 and a <= 6;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a > 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
=== modified file 'mysql-test/r/partition_pruning.result'
--- a/mysql-test/r/partition_pruning.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/r/partition_pruning.result 2010-04-05 20:16:45 +0000
@@ -89,7 +89,7 @@
1
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE a <= 2;
a
-1
@@ -98,7 +98,7 @@
2
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 4 Using where; Using index
SELECT * FROM t1 WHERE a <= 3;
a
-1
@@ -108,7 +108,7 @@
3
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 5 Using where; Using index
SELECT * FROM t1 WHERE a <= 4;
a
-1
@@ -119,7 +119,7 @@
4
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 6 Using where; Using index
SELECT * FROM t1 WHERE a <= 5;
a
-1
@@ -131,7 +131,7 @@
5
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2,p3,p4,p5 index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p0,p1,p2,p3,p4,p5 index PRIMARY PRIMARY 4 NULL 7 Using where; Using index
SELECT * FROM t1 WHERE a <= 6;
a
-1
@@ -213,7 +213,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1,p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p1,p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 8 Using where; Using index
SELECT * FROM t1 WHERE a >= 2;
a
2
@@ -225,7 +225,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 7 Using where; Using index
SELECT * FROM t1 WHERE a >= 3;
a
3
@@ -236,7 +236,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 6 Using where; Using index
SELECT * FROM t1 WHERE a >= 4;
a
4
@@ -246,7 +246,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p4,p5,max index PRIMARY PRIMARY 4 NULL 5 Using where; Using index
SELECT * FROM t1 WHERE a >= 5;
a
5
@@ -255,7 +255,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p5,max index PRIMARY PRIMARY 4 NULL 4 Using where; Using index
SELECT * FROM t1 WHERE a >= 6;
a
6
@@ -263,7 +263,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 6;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE a >= 7;
a
7
@@ -282,7 +282,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 7 Using where; Using index
SELECT * FROM t1 WHERE a > 2;
a
3
@@ -293,7 +293,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 6 Using where; Using index
SELECT * FROM t1 WHERE a > 3;
a
4
@@ -303,7 +303,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p4,p5,max index PRIMARY PRIMARY 4 NULL 5 Using where; Using index
SELECT * FROM t1 WHERE a > 4;
a
5
@@ -312,7 +312,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 p5,max index PRIMARY PRIMARY 4 NULL 4 Using where; Using index
SELECT * FROM t1 WHERE a > 5;
a
6
@@ -320,7 +320,7 @@
8
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index
+1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE a > 6;
a
7
@@ -408,7 +408,7 @@
1
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p0,p1 index PRIMARY PRIMARY 4 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE a <= 2;
a
-1
@@ -417,7 +417,7 @@
2
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p0,p1,p2 index PRIMARY PRIMARY 4 NULL 4 Using where; Using index
SELECT * FROM t1 WHERE a <= 3;
a
-1
@@ -427,7 +427,7 @@
3
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p0,p1,p2,p3 index PRIMARY PRIMARY 4 NULL 5 Using where; Using index
SELECT * FROM t1 WHERE a <= 4;
a
-1
@@ -438,7 +438,7 @@
4
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p0,p1,p2,p3,p4 index PRIMARY PRIMARY 4 NULL 6 Using where; Using index
SELECT * FROM t1 WHERE a <= 5;
a
-1
@@ -511,7 +511,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1,p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p1,p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 7 Using where; Using index
SELECT * FROM t1 WHERE a >= 2;
a
2
@@ -522,7 +522,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 6 Using where; Using index
SELECT * FROM t1 WHERE a >= 3;
a
3
@@ -532,7 +532,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p3,p4,max index PRIMARY PRIMARY 4 NULL 5 Using where; Using index
SELECT * FROM t1 WHERE a >= 4;
a
4
@@ -541,7 +541,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p4,max index PRIMARY PRIMARY 4 NULL 4 Using where; Using index
SELECT * FROM t1 WHERE a >= 5;
a
5
@@ -549,7 +549,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE a >= 6;
a
6
@@ -567,7 +567,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 6 Using where; Using index
SELECT * FROM t1 WHERE a > 2;
a
3
@@ -577,7 +577,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 2;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p3,p4,max index PRIMARY PRIMARY 4 NULL 5 Using where; Using index
SELECT * FROM t1 WHERE a > 3;
a
4
@@ -586,7 +586,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 p4,max index PRIMARY PRIMARY 4 NULL 4 Using where; Using index
SELECT * FROM t1 WHERE a > 4;
a
5
@@ -594,7 +594,7 @@
7
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index
+1 SIMPLE t1 max index PRIMARY PRIMARY 4 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE a > 5;
a
6
@@ -880,34 +880,34 @@
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
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 pNULL,p2001-01-01 ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 3 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
@@ -917,25 +917,25 @@
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
+1 SIMPLE t1 pNULL,p2001-01-01 ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 pNULL,p2001-01-01 ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 3 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
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 ALL NULL NULL NULL NULL 6 Using where
DROP TABLE t1;
# test of LIST and index
CREATE TABLE t1 (a DATE, KEY(a))
@@ -1209,62 +1209,62 @@
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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 3 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 3 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 pNULL,p1001-01-01 ALL NULL NULL NULL NULL 4 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
+1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 5 Using where
DROP TABLE t1;
# Test with DATETIME column NOT NULL
CREATE TABLE t1 (
@@ -1289,25 +1289,25 @@
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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+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-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
+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-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
+1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 3 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
@@ -1315,99 +1315,99 @@
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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+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 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
+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 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 6 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 8 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 6 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 6 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
+1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 3 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 6 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 8 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+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 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
+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 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 10 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
+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-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
+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-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
+1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 3 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
@@ -1440,21 +1440,21 @@
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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 8 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
+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-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
+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-02 23:59:59' AS DATETIME);
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -1462,79 +1462,79 @@
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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+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 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
+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 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 8 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 5 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 7 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 8 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 5 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 5 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 5 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 7 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
+1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 8 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
+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 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
+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 00:00:01' AS DATETIME);
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -1542,19 +1542,19 @@
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
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 8 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 index NULL PRIMARY 7 NULL 8 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
+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-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
+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-02 23:59:58' AS DATETIME);
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -1562,11 +1562,11 @@
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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 10 Using where; Using index
DROP TABLE t1;
# Test with DATETIME column NULL
CREATE TABLE t1 (
@@ -1590,25 +1590,25 @@
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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 3 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
@@ -1616,99 +1616,99 @@
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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+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 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
+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 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 3 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+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 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
+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 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 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
+1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 3 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
@@ -1740,21 +1740,21 @@
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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
@@ -1762,79 +1762,79 @@
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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+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 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
+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 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 7 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 7 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
+1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 2 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 8 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
+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 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
+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 00:00:01' AS DATETIME);
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -1842,19 +1842,19 @@
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
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090401,p20090404,p20090405 ALL NULL NULL NULL NULL 8 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
+1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 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
@@ -1862,11 +1862,11 @@
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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 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
+1 SIMPLE t1 p20090401,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 10 Using where
DROP TABLE t1;
# For better code coverage of the patch
CREATE TABLE t1 (
@@ -1930,7 +1930,7 @@
1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t2 where a=1 and b=1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 2 Using where
create table t3 (
a int
)
@@ -1988,25 +1988,25 @@
explain partitions select * from t5
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t5 where (a=10 and b=2) or (a=10 and b=3)
or (a=10 and b = 4);
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t5 where (c=1 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p1_p1sp0 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p1_p1sp0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t5 where (c=2 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
(c=2 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
(b=2 and c=2 and d=1);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t5 p0_p0sp0,p0_p0sp1,p1_p1sp1 ALL NULL NULL NULL NULL 3 Using where
create table t6 (a int not null) partition by LIST(a) (
partition p1 values in (1),
partition p3 values in (3),
@@ -2044,7 +2044,7 @@
1 SIMPLE t6 p5,p7,p9 system NULL NULL NULL NULL 1
explain partitions select * from t6 where a >= 3 and a <= 8;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 3 and a < 5;
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
@@ -2086,7 +2086,7 @@
1 SIMPLE t6 p5,p7,p9 system NULL NULL NULL NULL 1
explain partitions select * from t6 where a >= 3 and a <= 8;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t6 where a > 3 and a < 5;
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
@@ -2241,7 +2241,7 @@
explain partitions
select * from t1 X, t1 Y where X.a = Y.a and (X.a=1 or X.a=2);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE X p1,p2 ALL a NULL NULL NULL 4 Using where
+1 SIMPLE X p1,p2 ALL a NULL NULL NULL 2 Using where
1 SIMPLE Y p1,p2 ref a a 4 test.X.a 2
drop table t1;
create table t1 (a int) partition by hash(a) partitions 20;
@@ -2254,7 +2254,7 @@
1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 1 and a <= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a >= 1 and a <= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2,p3 ALL NULL NULL NULL NULL 3 Using where
@@ -2344,22 +2344,22 @@
1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 1010
explain partitions select * from t2 where a < 801 and a > 200;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p1,p2,p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p1,p2,p3,p4 ALL NULL NULL NULL NULL 800 Using where
explain partitions select * from t2 where a < 801 and a > 800;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 200 Using where
explain partitions select * from t2 where a > 600;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where a > 600 and b = 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where a > 600 and b = 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where a > 600 and b = 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 1010 Using where
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 400 Using where
explain partitions select * from t2 where b = 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 1010 Using where
@@ -2414,19 +2414,19 @@
1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 910
explain partitions select * from t2 where a = 101;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 110 Using where
explain partitions select * from t2 where a = 550;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 200 Using where
explain partitions select * from t2 where a = 833;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p4 ALL NULL NULL NULL NULL 200 Using where
explain partitions select * from t2 where (a = 100 OR a = 900);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0,p4 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p0,p4 ALL NULL NULL NULL NULL 310 Using where
explain partitions select * from t2 where (a > 100 AND a < 600);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 910 Using where
+1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 510 Using where
explain partitions select * from t2 where b = 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t2 p0,p1,p2,p3,p4 ref b b 5 const 76
@@ -2712,17 +2712,17 @@
explain partitions select * from t1
where a >= 18446744073709551000-1 and a <= 18446744073709551000+1;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1
where a between 18446744073709551001 and 18446744073709551002;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551000;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551613;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551614;
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
@@ -2749,10 +2749,10 @@
1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a=0xFE;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t2 where a=0xFE;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 0xFE AND a <= 0xFF;
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
@@ -2761,22 +2761,22 @@
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain partitions select * from t1 where a >= 0xFE AND a <= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t2 where a >= 0xFE AND a <= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a < 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t2 where a < 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 4 Using where
+1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a <= 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t2 where a <= 64 AND a >= 63;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 4 Using where
drop table t1;
drop table t2;
create table t1(a bigint unsigned not null) partition by range(a+0) (
=== modified file 'mysql-test/r/partition_range.result'
--- a/mysql-test/r/partition_range.result 2009-08-26 10:59:49 +0000
+++ b/mysql-test/r/partition_range.result 2010-04-05 20:16:45 +0000
@@ -59,13 +59,13 @@
1 SIMPLE t1 pnull system NULL NULL NULL NULL 1
explain partitions select * from t1 where a >= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a < 0;
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 a <= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull,p0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 pnull,p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a > 1;
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
@@ -98,16 +98,16 @@
a b
explain partitions select * from t1 where a is null;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a >= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a < 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a <= 0;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1,p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1,p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a > 1;
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
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/r/subselect.result 2010-04-05 20:16:45 +0000
@@ -3417,7 +3417,8 @@
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
@@ -3428,7 +3429,8 @@
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
+1 PRIMARY t1 ALL a NULL NULL NULL 9
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
@@ -4322,16 +4324,18 @@
INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
=== modified file 'mysql-test/r/subselect3.result'
--- a/mysql-test/r/subselect3.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect3.result 2010-04-05 20:16:45 +0000
@@ -1212,24 +1212,28 @@
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10 Using where
explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY A ALL NULL NULL NULL NULL 10
1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.A.a 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10
explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1
2 SUBQUERY A ALL NULL NULL NULL NULL 10
2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1
2 SUBQUERY A ALL NULL NULL NULL NULL 10
2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
explain select straight_join * from t2 X, t2 Y
where X.a in (select straight_join A.a from t1 A, t1 B);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY X ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY X ALL NULL NULL NULL NULL 10
1 PRIMARY Y ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.X.a 1
2 SUBQUERY A ALL NULL NULL NULL NULL 10
2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
create table t0 (a int, b int);
=== modified file 'mysql-test/r/subselect3_jcl6.result'
--- a/mysql-test/r/subselect3_jcl6.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect3_jcl6.result 2010-04-05 20:16:45 +0000
@@ -1217,24 +1217,28 @@
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10 Using where
explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY A ALL NULL NULL NULL NULL 10
1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.A.a 1
2 SUBQUERY t2 ALL NULL NULL NULL NULL 10
explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1
2 SUBQUERY A ALL NULL NULL NULL NULL 10
2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1
2 SUBQUERY A ALL NULL NULL NULL NULL 10
2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
explain select straight_join * from t2 X, t2 Y
where X.a in (select straight_join A.a from t1 A, t1 B);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY X ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY X ALL NULL NULL NULL NULL 10
1 PRIMARY Y ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.X.a 1
2 SUBQUERY A ALL NULL NULL NULL NULL 10
2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
create table t0 (a int, b int);
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result 2010-03-29 14:04:35 +0000
+++ b/mysql-test/r/subselect_mat.result 2010-04-05 20:16:45 +0000
@@ -38,10 +38,11 @@
explain extended
select * from t1 where a1 in (select b1 from t2 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 9 test.t1.a1 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0')) join `test`.`t1` where (`materialized subselect`.`b1` = `test`.`t1`.`a1`)
select * from t1 where a1 in (select b1 from t2 where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -49,10 +50,11 @@
explain extended
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 9 test.t1.a1 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`) join `test`.`t1` where (`materialized subselect`.`b1` = `test`.`t1`.`a1`)
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -60,10 +62,11 @@
explain extended
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`b2` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -71,10 +74,11 @@
explain extended
select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,min(`test`.`t2`.`b2`) AS `min(b2)` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`min(b2)`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,min(`test`.`t2`.`b2`) AS `min(b2)` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`) join `test`.`t1` where ((`materialized subselect`.`min(b2)` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -82,10 +86,11 @@
explain extended
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
+1 PRIMARY t1i index it1i1,it1i3 it1i3 18 NULL 3 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 9 test.t1i.a1 1 100.00
2 SUBQUERY t2i index it2i1,it2i3 it2i1 9 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where (`materialized subselect`.`b1` = `test`.`t1i`.`a1`)
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -93,10 +98,11 @@
explain extended
select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 3 100.00
+1 PRIMARY t1i ref it1i1,it1i3 it1i3 9 materialized subselect.b1 1 100.00 Using index
2 SUBQUERY t2i range it2i1,it2i3 it2i1 9 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where (`test`.`t1i`.`a1` = `materialized subselect`.`b1`)
select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -104,10 +110,11 @@
explain extended
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
+1 PRIMARY t1i index it1i1,it1i2,it1i3 it1i3 18 NULL 3 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1i.a1,test.t1i.a2 1 100.00
2 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`)))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`materialized subselect`.`b2` = `test`.`t1i`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1i`.`a1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -115,10 +122,11 @@
explain extended
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 3 100.00
+1 PRIMARY t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.b2 1 100.00 Using index
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`)))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -126,10 +134,11 @@
explain extended
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 3 100.00
+1 PRIMARY t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.min(b2) 1 100.00 Using index
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`min(b2)`)))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1i` where ((`test`.`t1i`.`a2` = `materialized subselect`.`min(b2)`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -137,10 +146,11 @@
explain extended
select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2i range NULL it2i3 9 NULL 3 100.00 Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,max(`test`.`t2i`.`b2`) AS `max(b2)` from `test`.`t2i` group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`max(b2)`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,max(`test`.`t2i`.`b2`) AS `max(b2)` from `test`.`t2i` group by `test`.`t2i`.`b1`) join `test`.`t1` where ((`materialized subselect`.`max(b2)` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1);
a1 a2
1 - 01 2 - 01
@@ -148,11 +158,13 @@
prepare st1 from "explain select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1)";
execute st1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1
2 SUBQUERY t2i range NULL it2i3 9 NULL 3 Using index for group-by
execute st1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1
2 SUBQUERY t2i range NULL it2i3 9 NULL 3 Using index for group-by
prepare st2 from "select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1)";
execute st2;
@@ -166,10 +178,11 @@
explain extended
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`min(b2)`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`) join `test`.`t1` where ((`materialized subselect`.`min(b2)` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -206,10 +219,11 @@
explain extended
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`b2` = `test`.`t1`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1`.`a1`))
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -217,10 +231,11 @@
explain extended
select * from t1i where (a1, a2) in (select b1, b2 from t2i order by b1, b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
+1 PRIMARY t1i index it1i1,it1i2,it1i3 it1i3 18 NULL 3 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 18 test.t1i.a1,test.t1i.a2 1 100.00
2 SUBQUERY t2i index NULL it2i3 18 NULL 5 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`)))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where ((`materialized subselect`.`b2` = `test`.`t1i`.`a2`) and (`materialized subselect`.`b1` = `test`.`t1i`.`a1`))
select * from t1i where (a1, a2) in (select b1, b2 from t2i order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -270,12 +285,15 @@
(a1, a2) in (select c1, c2 from t3
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
+1 PRIMARY SUBQUERY#3 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer
+3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
+3 SUBQUERY SUBQUERY#4 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
4 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key wh
ere ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0')) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))
select * from t1
where (a1, a2) in (select b1, b2 from t2 where b1 > '0') and
(a1, a2) in (select c1, c2 from t3
@@ -289,12 +307,15 @@
(a1, a2) in (select c1, c2 from t3i
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
-3 SUBQUERY t3i index NULL it3i3 18 NULL 4 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
+1 PRIMARY SUBQUERY#3 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+1 PRIMARY t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.c2 1 100.00 Using where; Using index
+3 SUBQUERY t3i index it3i1,it3i2,it3i3 it3i3 18 NULL 4 100.00 Using index
+3 SUBQUERY SUBQUERY#4 eq_ref distinct_key distinct_key 18 test.t3i.c1,test.t3i.c2 1 100.00
4 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where (<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from `test`.`t3i` where <in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary
table> on distinct_key where ((`test`.`t3i`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3i`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`c2`))))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`materialized subselect`.`b2` = `test`.`t3i`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`))
select * from t1i
where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i
@@ -310,14 +331,17 @@
(a1, a2) in (select c1, c2 from t3
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
+1 PRIMARY SUBQUERY#5 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer
+5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
+5 SUBQUERY SUBQUERY#6 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
6 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materi
alized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(
`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))))) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -335,14 +359,16 @@
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-5 SUBQUERY t3c ALL NULL NULL NULL NULL 4 100.00 Using where
+1 PRIMARY SUBQUERY#5 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
+5 SUBQUERY t3c ALL NULL NULL NULL NULL 4 100.00
+5 SUBQUERY SUBQUERY#6 eq_ref distinct_key distinct_key 18 test.t3c.c1,test.t3c.c2 1 100.00
6 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
4 SUBQUERY t3b ALL NULL NULL NULL NULL 4 100.00 Using where
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c
`.`c2` AS `c2` from `test`.`t3` `t3c` where <in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key where ((`test`.`t3c`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3c`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` `t3c` where ((`materialized subselect`.`b2` = `test`.`t3c`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3c`.`c1`))) join `test`.`t1` where ((`materialized subselect`.`c2` = `test`.`t1`.`a2`) and (`materialized subselect`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` fr
om `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
@@ -366,19 +392,25 @@
(a1, a2) in (select c1, c2 from t3i
where (c1, c2) in (select b1, b2 from t2i where b2 > '0')));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 5 0.00
+1 PRIMARY SUBQUERY#5 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer
+5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
+5 SUBQUERY SUBQUERY#6 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
6 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
-7 UNION t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
-9 SUBQUERY t3i index NULL it3i3 18 NULL 4 100.00 Using where; Using index
+7 UNION SUBQUERY#8 ALL distinct_key NULL NULL NULL 5 0.00
+7 UNION SUBQUERY#9 eq_ref distinct_key distinct_key 18 materialized subselect.b1,materialized subselect.b2 1 100.00
+7 UNION t1i ref it1i1,it1i2,it1i3 it1i3 18 materialized subselect.b1,materialized subselect.c2 1 100.00 Using where; Using index
+9 SUBQUERY t3i index it3i1,it3i2,it3i3 it3i3 18 NULL 4 100.00 Using index
+9 SUBQUERY SUBQUERY#10 eq_ref distinct_key distinct_key 18 test.t3i.c1,test.t3i.c2 1 100.00
10 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
8 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
NULL UNION RESULT <union1,7> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on dis
tinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` A
S `a2` from `test`.`t1i` where (<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from `test`.`t3i` where <in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key where ((`test`.`t3i`.`c1` = `materiali
zed subselect`.`b1`) and (`test`.`t3i`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`c2`)))))))
+Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>
(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a1` = `materialized subselect`.`b1`))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3i` where ((`materialized subselect`.`b2` = `test`.`t3i`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3i`.`c1`))) join <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0')) join `test`.`t1i
` where ((`materialized subselect`.`c2` = `materialized subselect`.`b2`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`) and (`materialized subselect`.`c1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))
(select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -401,13 +433,15 @@
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
+1 PRIMARY SUBQUERY#4 eq_ref distinct_key distinct_key 18 test.t1.a1,test.t1.a2 1 100.00
+4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
+4 SUBQUERY SUBQUERY#5 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
5 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <p
rimary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join `test`.`t1` where ((`materialized subselect`.`c2` = `test`.`t1`.`a2`) and (`materialized subselect`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`t
est`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
select * from t1
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(a1, a2) in (select c1, c2 from t3
@@ -423,14 +457,16 @@
a1 = c1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY SUBQUERY#4 ALL distinct_key NULL NULL NULL 4 75.00 Using where; Using join buffer
1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer
-4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
+4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00
+4 SUBQUERY SUBQUERY#5 eq_ref distinct_key distinct_key 18 test.t3.c1,test.t3.c2 1 100.00
5 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (selec
t `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`c1`) and (`test`.`t3`.`c2` = `materialized subselect`.`c2`))))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0')) join `test`.`t3` where ((`materialized subselect`.`b2` = `test`.`t3`.`c2`) and (`materialized subselect`.`b1` = `test`.`t3`.`c1`))) join `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`c2` = `materialized subselect`.`c2`) and (`materialized subselect`.`c1` = `test`.`t1`.`a1`) and (`test`.`t3`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `
test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))))
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -608,10 +644,11 @@
from t1_16
where a1 in (select substring(b1,1,16) from t2_16 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 20 test.t1_16.a1 1 100.00 Using where
2 SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) AS `substring(b1,1,16)` from `test`.`t2_16` where (`test`.`t2_16`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_16`.`a1` = `materialized subselect`.`substring(b1,1,16)`)))))
+Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) AS `substring(b1,1,16)` from `test`.`t2_16` where (`test`.`t2_16`.`b1` > '0')) join `test`.`t1_16` where (`test`.`t1_16`.`a1` = `materialized subselect`.`substring(b1,1,16)`)
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select substring(b1,1,16) from t2_16 where b1 > '0');
@@ -637,10 +674,11 @@
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_16.a1 1 100.00 Using where
2 SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_16` group by `test`.`t2_16`.`b2` ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_16`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_16` group by `test`.`t2_16`.`b2`) join `test`.`t1_16` where (`test`.`t1_16`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -660,9 +698,10 @@
2 DEPENDENT SUBQUERY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer
+3 DEPENDENT SUBQUERY SUBQUERY#4 eq_ref distinct_key distinct_key 9 test.t2.b1 1 100.00 Using where
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(select 1 AS `Not_used` from `test`.`t1_16` where (<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(select `test`.`t2_16`.`b1` AS `b1`,`test`.`t2_16`.`b2` AS `b2` from `test`.`t2_16` join `test`.`t2` where ((`test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6)) and <in_optimizer>(`test`.`t2`.`b1`,`test`.`t2`.`b1` in ( <materialize> (select `test`.`t3`.`c1` AS `c1` from `test`.`t3` where (`test`.`t3`.`c2` > '0') ), <primary_index_lookup>(`test`.`t2`.`b1` in <temporary table> on distinct_key where ((`test`.`t2`.`b1` = `materialized subselect`.`c1`))))) and (<cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`) and (<cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))) and (<cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(select 1 AS `Not_used` from `test`.`t1_16` where (<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(select `test`.`t2_16`.`b1` AS `b1`,`test`.`t2_16`.`b2` AS `b2` from <materialize> (select `test`.`t3`.`c1` AS `c1` from `test`.`t3` where (`test`.`t3`.`c2` > '0')) join `test`.`t2_16` join `test`.`t2` where ((`materialized subselect`.`c1` = `test`.`t2`.`b1`) and (`test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6)) and (<cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`) and (<cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))) and (<cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8)))))
drop table t1_16, t2_16, t3_16;
set @blob_len = 512;
set @suffix_len = @blob_len - @prefix_len;
@@ -721,10 +760,11 @@
from t1_512
where a1 in (select substring(b1,1,512) from t2_512 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 517 test.t1_512.a1 1 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) AS `substring(b1,1,512)` from `test`.`t2_512` where (`test`.`t2_512`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_512`.`a1` = `materialized subselect`.`substring(b1,1,512)`)))))
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) AS `substring(b1,1,512)` from `test`.`t2_512` where (`test`.`t2_512`.`b1` > '0')) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `materialized subselect`.`substring(b1,1,512)`)
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select substring(b1,1,512) from t2_512 where b1 > '0');
@@ -735,10 +775,11 @@
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_512.a1 1 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -748,10 +789,11 @@
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_512.a1 1 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where (`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -817,7 +859,7 @@
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in (select 1 AS `Not_used` from `test`.`t2_1024` where ((`test`.`t2_1024`.`b1` > '0') and (<cache>(`test`.`t1_1024`.`a1`) = substr(`test`.`t2_1024`.`b1`,1,1024)))))
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,<exists>(select 1 AS `Not_used` from `test`.`t2_1024` where ((`test`.`t2_1024`.`b1` > '0') and (<cache>(`test`.`t1_1024`.`a1`) = substr(`test`.`t2_1024`.`b1`,1,1024)) and (<cache>(`test`.`t1_1024`.`a1`) = 1))))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select substring(b1,1,1024) from t2_1024 where b1 > '0');
@@ -828,10 +870,11 @@
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1024.a1 1 100.00 Using where
2 SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where (`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -841,10 +884,11 @@
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1024.a1 1 100.00 Using where
2 SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where (`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -910,7 +954,7 @@
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in (select 1 AS `Not_used` from `test`.`t2_1025` where ((`test`.`t2_1025`.`b1` > '0') and (<cache>(`test`.`t1_1025`.`a1`) = substr(`test`.`t2_1025`.`b1`,1,1025)))))
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,<exists>(select 1 AS `Not_used` from `test`.`t2_1025` where ((`test`.`t2_1025`.`b1` > '0') and (<cache>(`test`.`t1_1025`.`a1`) = substr(`test`.`t2_1025`.`b1`,1,1025)) and (<cache>(`test`.`t1_1025`.`a1`) = 1))))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select substring(b1,1,1025) from t2_1025 where b1 > '0');
@@ -921,10 +965,11 @@
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1025.a1 1 100.00 Using where
2 SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where (`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -934,10 +979,11 @@
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 261 test.t1_1025.a1 1 100.00 Using where
2 SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where (`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -956,10 +1002,11 @@
from t1bit
where (a1, a2) in (select b1, b2 from t2bit);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1bit ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1bit ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 10 test.t1bit.a1,test.t1bit.a2 1 100.00 Using where
2 SUBQUERY t2bit ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from `test`.`t1bit` where <in_optimizer>((`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`),(`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`) in ( <materialize> (select `test`.`t2bit`.`b1` AS `b1`,`test`.`t2bit`.`b2` AS `b2` from `test`.`t2bit` ), <primary_index_lookup>(`test`.`t1bit`.`a1` in <temporary table> on distinct_key where ((`test`.`t1bit`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1bit`.`a2` = `materialized subselect`.`b2`)))))
+Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from <materialize> (select `test`.`t2bit`.`b1` AS `b1`,`test`.`t2bit`.`b2` AS `b2` from `test`.`t2bit`) join `test`.`t1bit` where ((`test`.`t1bit`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1bit`.`a2` = `materialized subselect`.`b2`))
select bin(a1), bin(a2)
from t1bit
where (a1, a2) in (select b1, b2 from t2bit);
@@ -1027,10 +1074,11 @@
explain extended
select a from t1 where a in (select c from t2 where d >= 20);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t1.a 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
+Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`materialized subselect`.`c` = `test`.`t1`.`a`)
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1041,10 +1089,11 @@
explain extended
select a from t1 where a in (select c from t2 where d >= 20);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using where; Using index
+1 PRIMARY t1 index it1a it1a 4 NULL 7 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t1.a 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
+Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`materialized subselect`.`c` = `test`.`t1`.`a`)
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1055,10 +1104,11 @@
explain extended
select a from t1 where a in (select c from t2 where d >= 20);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using where; Using index
+1 PRIMARY t1 index it1a it1a 4 NULL 7 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t1.a 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
+Note 1003 select `test`.`t1`.`a` AS `a` from <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20)) join `test`.`t1` where (`materialized subselect`.`c` = `test`.`t1`.`a`)
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1138,10 +1188,12 @@
insert into t1 values (5);
explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
-2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+1 PRIMARY t1 system NULL NULL NULL NULL 1
+1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 5 const 1
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
min(a1)
+NULL
set @@optimizer_switch='default,materialization=off';
explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
id select_type table type possible_keys key key_len ref rows Extra
@@ -1152,17 +1204,27 @@
set @@optimizer_switch='default,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
-2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+1 PRIMARY t1 system NULL NULL NULL NULL 1
+1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 5 const 1
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
select min(a1) from t1 where 7 in (select b1 from t2);
min(a1)
+NULL
set @@optimizer_switch='default,materialization=off';
+# with MariaDB and MWL#90, this particular case is solved:
explain select min(a1) from t1 where 7 in (select b1 from t2);
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
select min(a1) from t1 where 7 in (select b1 from t2);
min(a1)
NULL
+# but when we go around MWL#90 code, the problem still shows up:
+explain select min(a1) from t1 where 7 in (select b1 from t2) or 2> 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+select min(a1) from t1 where 7 in (select b1 from t2) or 2> 4;
+min(a1)
drop table t1,t2;
create table t1 (a char(2), b varchar(10));
insert into t1 values ('a', 'aaa');
@@ -1170,7 +1232,8 @@
set @@optimizer_switch='default,semijoin=off';
explain select a,b from t1 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 3 test.t1.b 1 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
select a,b from t1 where b in (select a from t1);
a b
=== modified file 'mysql-test/r/subselect_no_semijoin.result'
--- a/mysql-test/r/subselect_no_semijoin.result 2010-03-20 12:01:47 +0000
+++ b/mysql-test/r/subselect_no_semijoin.result 2010-04-05 20:16:45 +0000
@@ -1299,31 +1299,34 @@
4
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 4 100.00
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer
2 SUBQUERY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1`) join `test`.`t2` where (`test`.`t2`.`a` = `materialized subselect`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
4
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
+1 PRIMARY SUBQUERY#2 ALL distinct_key NULL NULL NULL 4 100.00
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer
2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`test`.`t2`.`a` = `materialized subselect`.`a`)
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
3
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 4 test.t2.a 1 100.00
2 SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using index
2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1342,31 +1345,34 @@
4
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1`) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
4
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
3
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t3 index a a 5 NULL 3 100.00 Using index
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using where; Using index; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1379,10 +1385,11 @@
4
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
2 SUBQUERY t1 index NULL a 10 NULL 10005 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30)) join `test`.`t2` where (`materialized subselect`.`a` = `test`.`t2`.`a`)
drop table t0, t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -2833,10 +2840,11 @@
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 10 test.t1.one,test.t1.two 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = 'N') ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where ((`test`.`t1`.`one` = `materialized subselect`.`one`) and (`test`.`t1`.`two` = `materialized subselect`.`two`)))))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from <materialize> (select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = 'N')) join `test`.`t1` where ((`materialized subselect`.`two` = `test`.`t1`.`two`) and (`materialized subselect`.`one` = `test`.`t1`.`one`))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -3421,7 +3429,8 @@
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
@@ -3432,7 +3441,8 @@
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
+1 PRIMARY t1 ALL a NULL NULL NULL 9
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
@@ -4206,7 +4216,8 @@
CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t1 ALL I2 NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 2 test.t1.b 1 Using where
2 SUBQUERY t1 index NULL I1 2 NULL 2 Using index
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
@@ -4216,14 +4227,16 @@
CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t2 ALL I2 NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 5 test.t2.b 1 Using where
2 SUBQUERY t2 index NULL I1 4 NULL 2 Using index
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
a b
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t1 ALL I2 NULL NULL NULL 2
+1 PRIMARY SUBQUERY#2 eq_ref distinct_key distinct_key 2 test.t1.b 1 Using where
2 SUBQUERY t1 index NULL I1 2 NULL 2 Using where; Using index
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
a b
@@ -4326,16 +4339,18 @@
INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY SUBQUERY#2 const distinct_key distinct_key 4 const 1 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`materialized subselect`.`1` = 1)
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
=== modified file 'mysql-test/suite/parts/r/partition_alter3_innodb.result'
--- a/mysql-test/suite/parts/r/partition_alter3_innodb.result 2008-11-12 17:51:47 +0000
+++ b/mysql-test/suite/parts/r/partition_alter3_innodb.result 2010-04-05 20:16:45 +0000
@@ -141,7 +141,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -165,7 +165,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -190,7 +190,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -226,7 +226,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -248,7 +248,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -269,7 +269,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -289,7 +289,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -308,7 +308,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -326,7 +326,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 10 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -452,7 +452,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -476,7 +476,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -504,7 +504,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -538,7 +538,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -563,7 +563,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -587,7 +587,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 23 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 10 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -610,7 +610,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -632,7 +632,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -653,7 +653,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 10 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
=== modified file 'mysql-test/suite/parts/r/partition_alter3_myisam.result'
--- a/mysql-test/suite/parts/r/partition_alter3_myisam.result 2008-11-12 17:51:47 +0000
+++ b/mysql-test/suite/parts/r/partition_alter3_myisam.result 2010-04-05 20:16:45 +0000
@@ -155,7 +155,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -187,7 +187,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -228,7 +228,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -278,7 +278,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -312,7 +312,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 4 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -343,7 +343,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -371,7 +371,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -396,7 +396,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part1 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -418,7 +418,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) FROM t1 WHERE f_date = '1000-02-10';
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 10 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -552,7 +552,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -584,7 +584,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -628,7 +628,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p6 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -676,7 +676,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -713,7 +713,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 3 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -747,7 +747,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 10 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -778,7 +778,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 5 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -806,7 +806,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 part7 ALL NULL NULL NULL NULL 7 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
@@ -831,7 +831,7 @@
t1.par
EXPLAIN PARTITIONS SELECT COUNT(*) <> 1 FROM t1 WHERE f_int1 = 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 20 Using where
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 10 Using where
# check read single success: 1
# check read all success: 1
# check read row by row success: 1
=== modified file 'mysql-test/t/subselect_mat.test'
--- a/mysql-test/t/subselect_mat.test 2010-03-13 20:04:52 +0000
+++ b/mysql-test/t/subselect_mat.test 2010-04-05 20:16:45 +0000
@@ -829,8 +829,12 @@
# This is the only correct result of all four queries. This difference is
# filed as BUG#40037.
set @@optimizer_switch='default,materialization=off';
+-- echo # with MariaDB and MWL#90, this particular case is solved:
explain select min(a1) from t1 where 7 in (select b1 from t2);
select min(a1) from t1 where 7 in (select b1 from t2);
+-- echo # but when we go around MWL#90 code, the problem still shows up:
+explain select min(a1) from t1 where 7 in (select b1 from t2) or 2> 4;
+select min(a1) from t1 where 7 in (select b1 from t2) or 2> 4;
drop table t1,t2;
#
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2010-03-29 14:04:35 +0000
+++ b/sql/item_subselect.cc 2010-04-05 20:16:45 +0000
@@ -468,6 +468,12 @@
return (res);
}
+int Item_subselect::optimize()
+{
+ int res;
+ res= engine->optimize();
+ return res;
+}
/*
Compute the IN predicate if the left operand's cache changed.
@@ -2088,7 +2094,7 @@
@retval FALSE an execution method was chosen successfully
*/
-bool Item_in_subselect::setup_engine()
+bool Item_in_subselect::setup_engine(bool dont_switch_arena)
{
subselect_hash_sj_engine *new_engine= NULL;
bool res= FALSE;
@@ -2103,7 +2109,7 @@
old_engine= (subselect_single_select_engine*) engine;
- if (arena->is_conventional())
+ if (arena->is_conventional() || dont_switch_arena)
arena= 0;
else
thd->set_n_backup_active_arena(arena, &backup);
@@ -3457,7 +3463,7 @@
bitmap_set_bit(&partial_match_key_parts, i);
++count_partial_match_columns;
}
- }
+ };
}
/* If no column contains NULLs use regular hash index lookups. */
@@ -3970,6 +3976,17 @@
}
+int subselect_hash_sj_engine::optimize()
+{
+ int res= 0;
+ SELECT_LEX *save_select= thd->lex->current_select;
+ thd->lex->current_select= materialize_join->select_lex;
+ res= materialize_join->optimize();
+ thd->lex->current_select= save_select;
+
+ return res;
+}
+
/**
Execute a subquery IN predicate via materialization.
=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h 2010-03-29 14:04:35 +0000
+++ b/sql/item_subselect.h 2010-04-05 20:16:45 +0000
@@ -52,9 +52,9 @@
public:
/* unit of subquery */
st_select_lex_unit *unit;
-protected:
/* engine that perform execution of subselect (single select or union) */
subselect_engine *engine;
+protected:
/* old engine if engine was changed */
subselect_engine *old_engine;
/* cache of used external tables */
@@ -139,6 +139,7 @@
bool mark_as_dependent(THD *thd, st_select_lex *select, Item *item);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void recalc_used_tables(st_select_lex *new_parent, bool after_pullout);
+ virtual int optimize();
virtual bool exec();
virtual void fix_length_and_dec();
table_map used_tables() const;
@@ -333,7 +334,9 @@
all JOIN in UNION
*/
Item *expr;
+public:
Item_in_optimizer *optimizer;
+protected:
bool was_null;
bool abort_on_null;
public:
@@ -379,6 +382,10 @@
};
enum_exec_method exec_method;
+ /* JTBM: temporary measure to tell JTBM predicates from SJ predicates */
+ bool convert_to_semi_join;
+ double startup_cost;
+
bool *get_cond_guard(int i)
{
return pushed_cond_guards ? pushed_cond_guards + i : NULL;
@@ -428,7 +435,7 @@
bool fix_fields(THD *thd, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void update_used_tables();
- bool setup_engine();
+ bool setup_engine(bool dont_switch_arena);
bool init_left_expr_cache();
/* Inform 'this' that it was computed, and contains a valid result. */
void set_first_execution() { if (first_execution) first_execution= FALSE; }
@@ -502,6 +509,7 @@
THD * get_thd() { return thd; }
virtual int prepare()= 0;
virtual void fix_length_and_dec(Item_cache** row)= 0;
+ virtual int optimize() { DBUG_ASSERT(0); return 0; }
/*
Execute the engine
@@ -734,7 +742,7 @@
class subselect_hash_sj_engine : public subselect_engine
{
-protected:
+public:
/* The table into which the subquery is materialized. */
TABLE *tmp_table;
/* TRUE if the subquery was materialized into a temp table. */
@@ -746,14 +754,16 @@
of subselect_single_select_engine::[prepare | cols].
*/
subselect_single_select_engine *materialize_engine;
+protected:
/* The engine used to compute the IN predicate. */
subselect_engine *lookup_engine;
/*
QEP to execute the subquery and materialize its result into a
temporary table. Created during the first call to exec().
*/
+public:
JOIN *materialize_join;
-
+protected:
/* Keyparts of the only non-NULL composite index in a rowid merge. */
MY_BITMAP non_null_key_parts;
/* Keyparts of the single column indexes with NULL, one keypart per index. */
@@ -766,7 +776,9 @@
IN results because index lookups sometimes match values that are actually
not equal to the search key in SQL terms.
*/
+public:
Item_cond_and *semi_join_conds;
+protected:
/* Possible execution strategies that can be used to compute hash semi-join.*/
enum exec_strategy {
UNDEFINED,
@@ -806,6 +818,7 @@
bool init_runtime();
void cleanup();
int prepare() { return 0; } /* Override virtual function in base class. */
+ int optimize();
int exec();
virtual void print(String *str, enum_query_type query_type);
uint cols()
=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc 2010-03-20 12:01:47 +0000
+++ b/sql/opt_range.cc 2010-04-05 20:16:45 +0000
@@ -2285,7 +2285,7 @@
quick=0;
needed_reg.clear_all();
quick_keys.clear_all();
- if (keys_to_use.is_clear_all())
+ if (keys_to_use.is_clear_all() || head->pos_in_table_list->jtbm_subselect)
DBUG_RETURN(0);
records= head->file->stats.records;
if (!records)
=== modified file 'sql/opt_subselect.cc'
--- a/sql/opt_subselect.cc 2010-03-15 19:52:58 +0000
+++ b/sql/opt_subselect.cc 2010-04-05 20:16:45 +0000
@@ -25,6 +25,8 @@
static int subq_sj_candidate_cmp(Item_in_subselect* const *el1,
Item_in_subselect* const *el2);
static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred);
+static bool convert_subq_to_jtbm(JOIN *parent_join,
+ Item_in_subselect *subq_pred, bool *remove);
static TABLE_LIST *alloc_join_nest(THD *thd);
static
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
@@ -166,6 +168,7 @@
(void)subquery_types_allow_materialization(in_subs);
in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
+ in_subs->convert_to_semi_join= TRUE; //JTBM
/* Register the subquery for further processing in flatten_subqueries() */
select_lex->
@@ -220,10 +223,21 @@
(in_subs->is_top_level_item() ||
optimizer_flag(thd, OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE) ||
optimizer_flag(thd, OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN)) &&//4
- !in_subs->is_correlated && // 5
- in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED) // 6
+ !in_subs->is_correlated) // 5
{
+ if (in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED)
in_subs->exec_method= Item_in_subselect::MATERIALIZATION;
+
+ // psergey-jtbm: "if we're top-level, register for
+ // conversion-to-join-tab".
+ if (in_subs->exec_method == Item_in_subselect::MATERIALIZATION &&
+ thd->thd_marker.emb_on_expr_nest == (TABLE_LIST*)0x1)
+ {
+ in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
+ in_subs->convert_to_semi_join= FALSE; //JTBM
+ select_lex->outer_select()->
+ join->sj_subselects.append(thd->mem_root, in_subs);//JTBM
+ }
}
Item_subselect::trans_res trans_res;
@@ -338,6 +352,60 @@
}
+static bool make_in_exists_conversion(THD *thd, JOIN *join, Item_in_subselect *item)
+{
+ DBUG_ENTER("make_in_exists_conversion");
+ JOIN *child_join= item->unit->first_select()->join;
+ Item_subselect::trans_res res;
+ item->changed= 0;
+ item->fixed= 0;
+
+ SELECT_LEX *save_select_lex= thd->lex->current_select;
+ thd->lex->current_select= item->unit->first_select();
+
+ res= item->select_transformer(child_join);
+
+ thd->lex->current_select= save_select_lex;
+
+ if (res == Item_subselect::RES_ERROR)
+ DBUG_RETURN(TRUE);
+
+ item->changed= 1;
+ item->fixed= 1;
+
+ Item *substitute= item->substitution;
+ bool do_fix_fields= !item->substitution->fixed;
+ Item **tree= (item->emb_on_expr_nest == (TABLE_LIST*)1)?
+ &join->conds : &(item->emb_on_expr_nest->on_expr);
+
+ Item *replace_me= item;
+ /*
+ JTBM: the subquery was already mapped with Item_in_optimizer, so we
+ should search for that, not for original Item_in_subselect.
+ TODO: what about delaying that rewrite until here?
+ */
+ if (!item->convert_to_semi_join)
+ {
+ replace_me= item->optimizer;
+ }
+
+ if (replace_where_subcondition(join, tree, replace_me, substitute,
+ do_fix_fields))
+ DBUG_RETURN(TRUE);
+ item->substitution= NULL;
+
+ if (!thd->stmt_arena->is_conventional())
+ {
+ tree= (item->emb_on_expr_nest == (TABLE_LIST*)1)?
+ &join->select_lex->prep_where :
+ &(item->emb_on_expr_nest->prep_on_expr);
+
+ if (replace_where_subcondition(join, tree, replace_me, substitute,
+ FALSE))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
/*
Convert semi-join subquery predicates into semi-join join nests
@@ -445,6 +513,7 @@
// #tables-in-parent-query + #tables-in-subquery < MAX_TABLES
/* Replace all subqueries to be flattened with Item_int(1) */
arena= thd->activate_stmt_arena_if_needed(&backup);
+#if 0
for (in_subq= join->sj_subselects.front();
in_subq != in_subq_end &&
join->tables + (*in_subq)->unit->first_select()->join->tables < MAX_TABLES;
@@ -452,18 +521,58 @@
{
Item **tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
&join->conds : &((*in_subq)->emb_on_expr_nest->on_expr);
- if (replace_where_subcondition(join, tree, *in_subq, new Item_int(1),
+ Item *replace_me= *in_subq;
+ /*
+ JTBM: the subquery was already mapped with Item_in_optimizer, so we
+ should search for that, not for original Item_in_subselect.
+ TODO: what about delaying that rewrite until here?
+ */
+ if (!(*in_subq)->convert_to_semi_join)
+ {
+ replace_me= (*in_subq)->optimizer;
+ }
+ if (replace_where_subcondition(join, tree, replace_me, new Item_int(1),
FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
}
+#endif
for (in_subq= join->sj_subselects.front();
in_subq != in_subq_end &&
join->tables + (*in_subq)->unit->first_select()->join->tables < MAX_TABLES;
in_subq++)
{
- if (convert_subq_to_sj(join, *in_subq))
- DBUG_RETURN(TRUE);
+ bool remove_item= TRUE;
+ //psergey-jtbm: todo: here: check if we should convert to semi-join or
+ // to JTBM nest.
+ if ((*in_subq)->convert_to_semi_join)
+ {
+ if (convert_subq_to_sj(join, *in_subq))
+ DBUG_RETURN(TRUE);
+ }
+ else
+ {
+ if (convert_subq_to_jtbm(join, *in_subq, &remove_item))
+ DBUG_RETURN(TRUE);
+ }
+ if (remove_item)
+ {
+ Item **tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
+ &join->conds : &((*in_subq)->emb_on_expr_nest->on_expr);
+ Item *replace_me= *in_subq;
+ /*
+ JTBM: the subquery was already mapped with Item_in_optimizer, so we
+ should search for that, not for original Item_in_subselect.
+ TODO: what about delaying that rewrite until here?
+ */
+ if (!(*in_subq)->convert_to_semi_join)
+ {
+ replace_me= (*in_subq)->optimizer;
+ }
+ if (replace_where_subcondition(join, tree, replace_me, new Item_int(1),
+ FALSE))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ }
}
skip_conversion:
/*
@@ -494,7 +603,19 @@
bool do_fix_fields= !(*in_subq)->substitution->fixed;
Item **tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
&join->conds : &((*in_subq)->emb_on_expr_nest->on_expr);
- if (replace_where_subcondition(join, tree, *in_subq, substitute,
+
+ Item *replace_me= *in_subq;
+ /*
+ JTBM: the subquery was already mapped with Item_in_optimizer, so we
+ should search for that, not for original Item_in_subselect.
+ TODO: what about delaying that rewrite until here?
+ */
+ if (!(*in_subq)->convert_to_semi_join)
+ {
+ replace_me= (*in_subq)->optimizer;
+ }
+
+ if (replace_where_subcondition(join, tree, replace_me, substitute,
do_fix_fields))
DBUG_RETURN(TRUE);
(*in_subq)->substitution= NULL;
@@ -505,7 +626,7 @@
&join->select_lex->prep_where :
&((*in_subq)->emb_on_expr_nest->prep_on_expr);
- if (replace_where_subcondition(join, tree, *in_subq, substitute,
+ if (replace_where_subcondition(join, tree, replace_me, substitute,
FALSE))
DBUG_RETURN(TRUE);
}
@@ -517,6 +638,36 @@
DBUG_RETURN(FALSE);
}
+
+void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows,
+ ha_rows *scan_time)
+{
+ item->optimize();
+
+ DBUG_ASSERT(item->engine->engine_type() ==
+ subselect_engine::HASH_SJ_ENGINE);
+
+ subselect_hash_sj_engine *hash_sj_engine=
+ ((subselect_hash_sj_engine*)item->engine);
+ JOIN *join= hash_sj_engine->materialize_join;
+
+ double rows= 1;
+ double read_time= 0.0;
+
+ /* Calculate #rows and cost of join execution */
+ for (uint i= join->const_tables; i < join->tables; i++)
+ {
+ rows *= join->best_positions[i].records_read;
+ read_time += join->best_positions[i].read_time;
+ }
+ *out_rows= rows;
+ item->startup_cost= read_time;
+ /* Calculate cost of scanning the temptable */
+ double data_size= rows * hash_sj_engine->tmp_table->s->reclength;
+ /* Do like in handler::read_time */
+ *scan_time= data_size/IO_SIZE + 2;
+}
+
/**
@brief Replaces an expression destructively inside the expression tree of
the WHERE clase.
@@ -887,6 +1038,114 @@
DBUG_RETURN(FALSE);
}
+
+static bool convert_subq_to_jtbm(JOIN *parent_join,
+ Item_in_subselect *subq_pred,
+ bool *remove_item)
+{
+ SELECT_LEX *parent_lex= parent_join->select_lex;
+ List<TABLE_LIST> *emb_join_list= &parent_lex->top_join_list;
+ TABLE_LIST *emb_tbl_nest= NULL; // will change when we learn to handle outer joins
+ TABLE_LIST *tl;//, *last_leaf;
+ DBUG_ENTER("convert_subq_to_jtbm");
+
+ if (subq_pred->setup_engine(TRUE))
+ DBUG_RETURN(TRUE);
+
+ if (subq_pred->engine->engine_type() != subselect_engine::HASH_SJ_ENGINE)
+ {
+ *remove_item= FALSE;
+ make_in_exists_conversion(parent_join->thd, parent_join, subq_pred);
+ DBUG_RETURN(FALSE);
+ }
+ *remove_item= TRUE;
+
+ TABLE_LIST *jtbm;
+ char *tbl_alias;
+ const char alias_mask[]="SUBQUERY#%d";
+ if (!(tbl_alias= (char*)parent_join->thd->calloc(sizeof(alias_mask)+5)) ||
+ !(jtbm= alloc_join_nest(parent_join->thd))) //todo: this is not a join nest!
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ jtbm->join_list= emb_join_list;
+ jtbm->embedding= emb_tbl_nest;
+ jtbm->alias= (char*)"(jtbm)";
+ jtbm->jtbm_subselect= subq_pred;
+ jtbm->nested_join= NULL;
+
+ /* Nests do not participate in those 'chains', so: */
+ /* jtbm->next_leaf= jtbm->next_local= jtbm->next_global == NULL*/
+ emb_join_list->push_back(jtbm);
+
+ /* Inject ourselves into next-leaf list */
+ /*
+ JTBM: Inject us into next_leaf and lext_local chains..
+ so that make_join_statistics et al find us.
+ */
+
+ /*
+ Reconnect the next_leaf chain.
+ TODO: Do we have to put subquery's tables at the end of the chain?
+ Inserting them at the beginning would be a bit faster.
+ NOTE: We actually insert them at the front! That's because the order is
+ reversed in this list.
+ */
+ for (tl= parent_lex->leaf_tables; tl->next_leaf; tl= tl->next_leaf) ;
+ tl->next_leaf= jtbm;
+
+ /*
+ Same as above for next_local chain
+ (a theory: a next_local chain always starts with ::leaf_tables
+ because view's tables are inserted after the view)
+ */
+ for (tl= parent_lex->leaf_tables; tl->next_local; tl= tl->next_local) ;
+ tl->next_local= jtbm;
+
+ /* A theory: no need to re-connect the next_global chain */
+
+ subselect_hash_sj_engine *hash_sj_engine=
+ ((subselect_hash_sj_engine*)subq_pred->engine);
+ jtbm->table= hash_sj_engine->tmp_table;
+
+ jtbm->table->tablenr= parent_join->tables;
+ jtbm->table->map= table_map(1) << (parent_join->tables);
+
+ parent_join->tables++;
+
+ Item *conds= hash_sj_engine->semi_join_conds;
+ conds->fix_after_pullout(parent_lex, &conds);
+
+ DBUG_EXECUTE("where", print_where(conds,"SJ-EXPR", QT_ORDINARY););
+
+ my_snprintf(tbl_alias, sizeof(alias_mask)+5, alias_mask,
+ hash_sj_engine->materialize_join->select_lex->select_number);
+ jtbm->alias= tbl_alias;
+
+ /* Inject sj_on_expr into the parent's WHERE or ON */
+ if (emb_tbl_nest)
+ {
+ DBUG_ASSERT(0);
+ /*emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr,
+ sj_nest->sj_on_expr);
+ emb_tbl_nest->on_expr->fix_fields(parent_join->thd, &emb_tbl_nest->on_expr);
+ */
+ }
+ else
+ {
+ /* Inject into the WHERE */
+ parent_join->conds= and_items(parent_join->conds, conds);
+ parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds);
+ parent_join->select_lex->where= parent_join->conds;
+ }
+
+ /* Don't unlink the child, the subquery is still there and used */
+
+ DBUG_RETURN(FALSE);
+}
+
+
static TABLE_LIST *alloc_join_nest(THD *thd)
{
TABLE_LIST *tbl;
@@ -3503,4 +3762,26 @@
}
}
+int do_jtbm_materialization_if_needed(JOIN_TAB *tab)
+{
+ Item_in_subselect *in_subs;
+ if (tab->table->pos_in_table_list &&
+ (in_subs= tab->table->pos_in_table_list->jtbm_subselect))
+ {
+ DBUG_ASSERT(in_subs->engine->engine_type() ==
+ subselect_engine::HASH_SJ_ENGINE);
+
+ subselect_hash_sj_engine *hash_sj_engine=
+ ((subselect_hash_sj_engine*)in_subs->engine);
+ if (!hash_sj_engine->is_materialized)
+ {
+ hash_sj_engine->materialize_join->exec();
+ hash_sj_engine->is_materialized= TRUE;
+
+ if (hash_sj_engine->materialize_join->error || tab->join->thd->is_fatal_error)
+ return 1;
+ }
+ }
+ return 0;
+}
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-03-20 12:01:47 +0000
+++ b/sql/sql_base.cc 2010-04-05 20:16:45 +0000
@@ -7661,6 +7661,17 @@
if (res)
DBUG_RETURN(1);
}
+ if (table_list->jtbm_subselect)
+ {
+ Item *item= table_list->jtbm_subselect;
+ if (item->fix_fields(thd, &item))
+ {
+ my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
+ DBUG_RETURN(1);
+ }
+ DBUG_ASSERT(item == table_list->jtbm_subselect);
+ table_list->jtbm_subselect->setup_engine(FALSE);
+ }
}
/* Precompute and store the row types of NATURAL/USING joins. */
=== modified file 'sql/sql_join_cache.cc'
--- a/sql/sql_join_cache.cc 2010-03-07 15:41:45 +0000
+++ b/sql/sql_join_cache.cc 2010-04-05 20:16:45 +0000
@@ -33,6 +33,7 @@
#define NO_MORE_RECORDS_IN_BUFFER (uint)(-1)
+int do_jtbm_materialization_if_needed(JOIN_TAB *tab);
/*****************************************************************************
* Join cache module
@@ -1778,6 +1779,10 @@
}
/* Start retrieving all records of the joined table */
+
+ //jtbm-todo: error handling!
+ do_jtbm_materialization_if_needed(join_tab);
+
if ((error= join_init_read_record(join_tab)))
{
rc= error < 0 ? NESTED_LOOP_NO_MORE_ROWS: NESTED_LOOP_ERROR;
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-03-29 20:09:40 +0000
+++ b/sql/sql_select.cc 2010-04-05 20:16:45 +0000
@@ -243,6 +243,10 @@
Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
bool *inherited_fl);
+void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows,
+ ha_rows *scan_time);
+int do_jtbm_materialization_if_needed(JOIN_TAB *tab);
+
/**
This handles SELECT with and without UNION.
*/
@@ -2445,7 +2449,7 @@
{
Item_in_subselect *in_subs= (Item_in_subselect*) subquery_predicate;
if (in_subs->exec_method == Item_in_subselect::MATERIALIZATION &&
- in_subs->setup_engine())
+ in_subs->setup_engine(FALSE))
return TRUE;
}
}
@@ -2531,9 +2535,10 @@
DBUG_ENTER("make_join_statistics");
table_count=join->tables;
- stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*table_count);
+
+ stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*(table_count));
stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
- table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
+ table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*((table_count)*2));
if (!stat || !stat_ref || !table_vector)
DBUG_RETURN(1); // Eom /* purecov: inspected */
@@ -2542,7 +2547,7 @@
stat_end=stat+table_count;
found_const_table_map= all_table_map=0;
const_count=0;
-
+
for (s= stat, i= 0;
tables;
s++, tables= tables->next_leaf, i++)
@@ -2565,7 +2570,7 @@
table->reginfo.join_tab=s;
table->reginfo.not_exists_optimize=0;
bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->s->keys);
- all_table_map|= table->map;
+ all_table_map|= s->table->map;
s->join=join;
s->info=0; // For describe
@@ -2574,15 +2579,17 @@
if (tables->schema_table)
table->file->stats.records= 2;
table->quick_condition_rows= table->file->stats.records;
-
+
s->on_expr_ref= &tables->on_expr;
if (*s->on_expr_ref)
{
/* s is the only inner table of an outer join */
#ifdef WITH_PARTITION_STORAGE_ENGINE
- if ((!table->file->stats.records || table->no_partitions_used) && !embedding)
+ if (!table->pos_in_table_list->jtbm_subselect &&
+ (!table->file->stats.records || table->no_partitions_used) && !embedding)
#else
- if (!table->file->stats.records && !embedding)
+ if (!table->pos_in_table_list->jtbm_subselect &&
+ !table->file->stats.records && !embedding)
#endif
{ // Empty table
s->dependent= 0; // Ignore LEFT JOIN depend.
@@ -2616,7 +2623,8 @@
#else
const bool no_partitions_used= FALSE;
#endif
- if ((table->s->system || table->file->stats.records <= 1 ||
+ if (!table->pos_in_table_list->jtbm_subselect &&
+ (table->s->system || table->file->stats.records <= 1 ||
no_partitions_used) &&
!s->dependent &&
(table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
@@ -2626,6 +2634,8 @@
no_rows_const_tables |= table->map;
}
}
+ //psergey-todo: inject jtbm JOIN_TABS here.
+
stat_vector[i]=0;
join->outer_join=outer_join;
@@ -2714,6 +2724,9 @@
{
table=s->table;
+ if (table->pos_in_table_list->jtbm_subselect)
+ continue;
+
/*
If equi-join condition by a key is null rejecting and after a
substitution of a const table the key value happens to be null
@@ -2873,8 +2886,21 @@
continue;
}
/* Approximate found rows and time to read them */
- s->found_records=s->records=s->table->file->stats.records;
- s->read_time=(ha_rows) s->table->file->scan_time();
+
+ if (s->table->pos_in_table_list->jtbm_subselect)
+ {
+ get_temptable_params(s->table->pos_in_table_list->jtbm_subselect,
+ &s->records,
+ &s->read_time);
+ s->found_records= s->records;
+ table->quick_condition_rows=s->records;
+ }
+ else
+ {
+ s->found_records=s->records=s->table->file->stats.records;
+ s->read_time=(ha_rows) s->table->file->scan_time();
+ }
+
/*
Set a max range of how many seeks we can expect when using keys
@@ -2897,10 +2923,11 @@
Don't do range analysis if we're on the inner side of an outer join (2).
Do range analysis if we're on the inner side of a semi-join (3).
*/
- if (!s->const_keys.is_clear_all() && // (1)
- (!s->table->pos_in_table_list->embedding || // (2)
- (s->table->pos_in_table_list->embedding && // (3)
- s->table->pos_in_table_list->embedding->sj_on_expr))) // (3)
+ if (!s->const_keys.is_clear_all() && // (1)
+ (!s->table->pos_in_table_list->embedding || // (2)
+ (s->table->pos_in_table_list->embedding && // (3)
+ s->table->pos_in_table_list->embedding->sj_on_expr)) && // (3)
+ !s->table->pos_in_table_list->jtbm_subselect)
{
ha_rows records;
SQL_SELECT *select;
@@ -4265,6 +4292,8 @@
double tmp;
ha_rows rec;
bool best_uses_jbuf= FALSE;
+ Item_in_subselect* jtbm_subselect= s->table->pos_in_table_list->jtbm_subselect;
+ bool jtbm_ref_used= FALSE;
Loose_scan_opt loose_scan_opt;
DBUG_ENTER("best_access_path");
@@ -4617,8 +4646,9 @@
else
tmp= best_time; // Do nothing
}
+ if (jtbm_subselect)
+ tmp += jtbm_subselect->startup_cost;
loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
-
} /* not ft_key */
if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
{
@@ -4628,6 +4658,8 @@
best_key= start_key;
best_max_key_part= max_key_part;
best_ref_depends_map= found_ref;
+ if (jtbm_subselect)
+ jtbm_ref_used= TRUE;
}
} /* for each key */
records= best_records;
@@ -4666,7 +4698,8 @@
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
!((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
! s->table->covering_keys.is_clear_all() && best_key && !s->quick) &&// (3)
- !(s->table->force_index && best_key && !s->quick)) // (4)
+ !(s->table->force_index && best_key && !s->quick) && // (4)
+ !jtbm_ref_used)
{ // Check full join
ha_rows rnd_records= s->found_records;
/*
@@ -4714,7 +4747,11 @@
else
{
/* Estimate cost of reading table. */
- tmp= s->table->file->scan_time();
+ if (jtbm_subselect)
+ tmp= s->read_time;
+ else
+ tmp= s->table->file->scan_time();
+
if ((s->table->map & join->outer_join) || disable_jbuf) // Can't use join cache
{
/*
@@ -4743,6 +4780,8 @@
}
}
+ if (jtbm_subselect)
+ tmp += jtbm_subselect->startup_cost;
/*
We estimate the cost of evaluating WHERE clause for found records
as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
@@ -7684,6 +7723,12 @@
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
table->file->ha_index_or_rnd_end();
+ //psergey-jtbm2:
+ if (table->pos_in_table_list &&
+ table->pos_in_table_list->jtbm_subselect)
+ {
+ table->pos_in_table_list->jtbm_subselect->cleanup();
+ }
/*
We need to reset this for next select
(Tested in part_of_refkey)
@@ -11396,6 +11441,8 @@
share->keys=1;
share->uniques= test(using_unique_constraint);
table->key_info= table->s->key_info= keyinfo;
+ table->keys_in_use_for_query.set_bit(0);
+ share->keys_in_use.set_bit(0);
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME;
keyinfo->usable_key_parts=keyinfo->key_parts= param->group_parts;
@@ -11411,6 +11458,8 @@
bool maybe_null=(*cur_group->item)->maybe_null;
key_part_info->null_bit=0;
key_part_info->field= field;
+ if (cur_group == group)
+ field->key_start.set_bit(0);
key_part_info->offset= field->offset(table->record[0]);
key_part_info->length= (uint16) field->key_length();
key_part_info->type= (uint8) field->key_type();
@@ -11481,6 +11530,8 @@
keyinfo->key_parts * sizeof(KEY_PART_INFO))))
goto err;
bzero((void*) key_part_info, keyinfo->key_parts * sizeof(KEY_PART_INFO));
+ table->keys_in_use_for_query.set_bit(0);
+ share->keys_in_use.set_bit(0);
table->key_info= table->s->key_info= keyinfo;
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
@@ -11519,6 +11570,14 @@
{
key_part_info->null_bit=0;
key_part_info->field= *reg_field;
+ //psergey-jtbm:
+ (*reg_field)->flags |= PART_KEY_FLAG;
+ if (key_part_info == keyinfo->key_part)
+ (*reg_field)->key_start.set_bit(0);
+ key_part_info->null_bit= (*reg_field)->null_bit;
+ key_part_info->null_offset= (uint) ((*reg_field)->null_ptr -
+ (uchar*) table->record[0]);
+
key_part_info->offset= (*reg_field)->offset(table->record[0]);
key_part_info->length= (uint16) (*reg_field)->pack_length();
/* TODO:
@@ -12804,7 +12863,9 @@
join_tab->last_inner->first_unmatched= join_tab;
}
join->thd->row_count= 0;
-
+
+ //jtbm-todo: error handling!
+ do_jtbm_materialization_if_needed(join_tab);
error= (*join_tab->read_first_record)(join_tab);
if (join_tab->keep_current_rowid)
@@ -18169,7 +18230,7 @@
if (tab->select && tab->select->quick)
examined_rows= tab->select->quick->records;
else if (tab->type == JT_NEXT || tab->type == JT_ALL)
- examined_rows= tab->limit ? tab->limit : tab->table->file->records();
+ examined_rows= tab->limit ? tab->limit : tab->records;
else
examined_rows=(ha_rows)join->best_positions[i].records_read;
@@ -18658,6 +18719,14 @@
print_join(thd, eliminated_tables, str, &nested_join->join_list, query_type);
str->append(')');
}
+ else if (jtbm_subselect)
+ {
+ str->append(STRING_WITH_LEN(" <materialize> ("));
+ subselect_hash_sj_engine *hash_engine;
+ hash_engine= (subselect_hash_sj_engine*)jtbm_subselect->engine;
+ hash_engine->materialize_engine->print(str, query_type);
+ str->append(')');
+ }
else
{
const char *cmp_name; // Name to compare with alias
=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h 2010-03-20 12:01:47 +0000
+++ b/sql/sql_select.h 2010-04-05 20:16:45 +0000
@@ -1551,7 +1551,18 @@
bool union_part; ///< this subselect is part of union
bool optimized; ///< flag to avoid double optimization in EXPLAIN
+ /*
+ Subqueries that will need to be converted to semi-join nests (the list
+ is emptied when conversion is done
+ */
Array<Item_in_subselect> sj_subselects;
+
+ /*
+ Subqueries that will need to be converted to JOIN_TABs
+ (Note this is different from the above in the respect that it's part
+ of WHERE clause or something like that?)
+ */
+ //Array<Item_in_subselect> jtbm_subselects;
/* Temporary tables used to weed-out semi-join duplicates */
List<TABLE> sj_tmp_tables;
@@ -1575,6 +1586,7 @@
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
:fields_list(fields_arg), sj_subselects(thd_arg->mem_root, 4)
+ //jtbm_subselects(thd_arg->mem_root, 4)
{
init(thd_arg, fields_arg, select_options_arg, result_arg);
}
=== modified file 'sql/table.h'
--- a/sql/table.h 2010-03-20 12:01:47 +0000
+++ b/sql/table.h 2010-04-05 20:16:45 +0000
@@ -1194,6 +1194,7 @@
/* Number of IN-compared expressions */
uint sj_in_exprs;
Item_in_subselect *sj_subq_pred;
+ Item_in_subselect *jtbm_subselect;
SJ_MATERIALIZATION_INFO *sj_mat_info;
/*
1
0

[Maria-developers] Rev 2772: fixed a bug in handling mysql_native_password specified explicitly: in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 05 Apr '10
by serg@askmonty.org 05 Apr '10
05 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2772
revision-id: sergii(a)pisem.net-20100405095031-bgjy005pcftkp6g1
parent: sergii(a)pisem.net-20100402200840-0nctbdvalpetkkzp
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Mon 2010-04-05 11:50:31 +0200
message:
fixed a bug in handling mysql_native_password specified explicitly:
CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password
pointers were not always fixed, salt wasn't updated
=== modified file 'mysql-test/r/connect.result'
--- a/mysql-test/r/connect.result 2009-04-25 09:04:38 +0000
+++ b/mysql-test/r/connect.result 2010-04-05 09:50:31 +0000
@@ -225,3 +225,17 @@ Connection on extra port 2 ok
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
+CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
+CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
+connect(localhost,mysqltest_up1,foo,test,13001,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'mysqltest_up1'@'localhost' (using password: YES)
+select user(), current_user();
+user() current_user()
+mysqltest_up1@localhost mysqltest_up1@%
+connect(localhost,mysqltest_up2,newpw,test,13001,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'mysqltest_up2'@'localhost' (using password: YES)
+select user(), current_user();
+user() current_user()
+mysqltest_up2@localhost mysqltest_up2@%
+DROP USER mysqltest_up1@'%';
+DROP USER mysqltest_up2@'%';
=== modified file 'mysql-test/t/connect.test'
--- a/mysql-test/t/connect.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/connect.test 2010-04-05 09:50:31 +0000
@@ -328,6 +328,34 @@ if ($error)
--disconnect extracon2
--connection default
+#
+# A couple of plugin tests - for builtin plugins only
+#
+CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
+CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
+
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect(pcon1,localhost,mysqltest_up1,foo,,$MASTER_EXTRA_PORT,);
+
+connect(pcon2,localhost,mysqltest_up1,bar,,$MASTER_EXTRA_PORT,);
+connection pcon2;
+select user(), current_user();
+disconnect pcon2;
+
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect(pcon3,localhost,mysqltest_up2,newpw,,$MASTER_EXTRA_PORT,);
+
+connect(pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_EXTRA_PORT,);
+connection pcon4;
+select user(), current_user();
+disconnect pcon4;
+
+connection default;
+DROP USER mysqltest_up1@'%';
+DROP USER mysqltest_up2@'%';
+
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-04-02 20:08:40 +0000
+++ b/sql/sql_acl.cc 2010-04-05 09:50:31 +0000
@@ -319,6 +319,35 @@ set_user_salt(ACL_USER *acl_user, const
acl_user->salt_len= 0;
}
+/**
+ Fix ACL::plugin pointer to point to a hard-coded string, if appropriate
+
+ Make sure that if ACL_USER's plugin is a built-in, then it points
+ to a hard coded string, not to an allocated copy. Run-time, for
+ authentication, we want to be able to detect built-ins by comparing
+ pointers, not strings.
+
+ Additionally - update the salt if the plugin is built-in.
+
+ @retval 0 the pointers were fixed
+ @retval 1 this ACL_USER uses a not built-in plugin
+*/
+static bool fix_user_plugin_ptr(ACL_USER *user)
+{
+ if (my_strcasecmp(system_charset_info, user->plugin.str,
+ native_password_plugin_name.str) == 0)
+ user->plugin= native_password_plugin_name;
+ else
+ if (my_strcasecmp(system_charset_info, user->plugin.str,
+ old_password_plugin_name.str) == 0)
+ user->plugin= old_password_plugin_name;
+ else
+ return true;
+
+ set_user_salt(user, user->auth_string.str, user->auth_string.length);
+ return false;
+}
+
/*
This after_update function is used when user.password is less than
SCRAMBLE_LENGTH bytes.
@@ -662,6 +691,8 @@ static my_bool acl_load(THD *thd, TABLE_
char *tmpstr= get_field(&mem, table->field[next_field++]);
if (tmpstr)
{
+ user.plugin.str= tmpstr;
+ user.plugin.length= strlen(user.plugin.str);
if (user.auth_string.length)
{
sql_print_warning("'user' entry '%s@%s' has both a password "
@@ -670,22 +701,12 @@ static my_bool acl_load(THD *thd, TABLE_
user.user ? user.user : "",
user.host.hostname ? user.host.hostname : "");
}
- if (my_strcasecmp(system_charset_info, tmpstr,
- native_password_plugin_name.str) == 0)
- user.plugin= native_password_plugin_name;
- else
- if (my_strcasecmp(system_charset_info, tmpstr,
- old_password_plugin_name.str) == 0)
- user.plugin= old_password_plugin_name;
- else
- {
- user.plugin.str= tmpstr;
- user.plugin.length= strlen(tmpstr);
- }
user.auth_string.str= get_field(&mem, table->field[next_field++]);
if (!user.auth_string.str)
user.auth_string.str= const_cast<char*>("");
user.auth_string.length= strlen(user.auth_string.str);
+
+ fix_user_plugin_ptr(&user);
}
}
}
@@ -1132,12 +1153,15 @@ static void acl_update_user(const char *
{
if (plugin->str[0])
{
- acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
- acl_user->plugin.length= plugin->length;
+ acl_user->plugin= *plugin;
acl_user->auth_string.str= auth->str ?
strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
acl_user->auth_string.length= auth->length;
+ if (fix_user_plugin_ptr(acl_user))
+ acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
}
+ else
+ set_user_salt(acl_user, password, password_len);
acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
@@ -1157,8 +1181,6 @@ static void acl_update_user(const char *
acl_user->x509_subject= (x509_subject ?
strdup_root(&mem,x509_subject) : 0);
}
- if (password)
- set_user_salt(acl_user, password, password_len);
/* search complete: */
break;
}
@@ -1186,11 +1208,12 @@ static void acl_insert_user(const char *
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
if (plugin->str[0])
{
- acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
- acl_user.plugin.length= plugin->length;
+ acl_user.plugin= *plugin;
acl_user.auth_string.str= auth->str ?
strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
acl_user.auth_string.length= auth->length;
+ if (fix_user_plugin_ptr(&acl_user))
+ acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
}
else
{
@@ -1198,6 +1221,7 @@ static void acl_insert_user(const char *
old_password_plugin_name : native_password_plugin_name;
acl_user.auth_string.str= strmake_root(&mem, password, password_len);
acl_user.auth_string.length= password_len;
+ set_user_salt(&acl_user, password, password_len);
}
acl_user.access=privileges;
@@ -1210,8 +1234,6 @@ static void acl_insert_user(const char *
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
- set_user_salt(&acl_user, password, password_len);
-
VOID(push_dynamic(&acl_users,(uchar*) &acl_user));
if (!acl_user.host.hostname ||
(acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1]))
1
0

[Maria-developers] Rev 2751: options for CREATE TABLE (MWL#43) in file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/
by sanja@askmonty.org 05 Apr '10
by sanja@askmonty.org 05 Apr '10
05 Apr '10
At file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/
------------------------------------------------------------
revno: 2751
revision-id: sanja(a)askmonty.org-20100405084956-cesl6d5fm56m644z
parent: sergii(a)pisem.net-20100323092233-t2gwaclx94hd6exa
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-createoptions2
timestamp: Mon 2010-04-05 11:49:56 +0300
message:
options for CREATE TABLE (MWL#43)
=== modified file 'Docs/sp-imp-spec.txt'
--- a/Docs/sp-imp-spec.txt 2004-03-23 11:04:40 +0000
+++ b/Docs/sp-imp-spec.txt 2010-04-05 08:49:56 +0000
@@ -1075,7 +1075,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_NOERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -1097,4 +1097,4 @@
) comment='Stored Procedures';
--
-
\ No newline at end of file
+
=== modified file 'include/my_base.h'
--- a/include/my_base.h 2010-02-10 19:06:24 +0000
+++ b/include/my_base.h 2010-04-05 08:49:56 +0000
@@ -314,6 +314,8 @@
#define HA_OPTION_RELIES_ON_SQL_LAYER 512
#define HA_OPTION_NULL_FIELDS 1024
#define HA_OPTION_PAGE_CHECKSUM 2048
+/* .frm has extra create options in linked-list format */
+#define HA_OPTION_TEXT_CREATE_OPTIONS (1L << 14)
#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */
#define HA_OPTION_READ_ONLY_DATA (1L << 16) /* Set by isamchk */
#define HA_OPTION_NO_CHECKSUM (1L << 17)
=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt 2010-01-31 09:13:21 +0000
+++ b/libmysqld/CMakeLists.txt 2010-04-05 08:49:56 +0000
@@ -139,7 +139,8 @@
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
- ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/create_options.cc
${GEN_SOURCES}
${LIB_SOURCES})
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-12-03 11:19:05 +0000
+++ b/libmysqld/Makefile.am 2010-04-05 08:49:56 +0000
@@ -75,7 +75,7 @@
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
debug_sync.cc \
- sql_tablespace.cc \
+ sql_tablespace.cc create_options.cc \
rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc event_parse_data.cc opt_table_elimination.cc
=== added file 'mysql-test/r/create_options.result'
--- a/mysql-test/r/create_options.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/create_options.result 2010-04-05 08:49:56 +0000
@@ -0,0 +1,182 @@
+drop table if exists t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'
+Warning 1650 Unknown option 'dff'
+Warning 1650 Unknown option 'tkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v1'
+drop table t1;
+#reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'
+Warning 1650 Unknown option 'dff'
+Warning 1650 Unknown option 'tkey1'
+Warning 1650 Unknown option 'tkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1'
+#add option
+alter table t1 tkey4=4v1;
+Warnings:
+Warning 1650 Unknown option 'tkey4'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1' `tkey4`='4v1'
+#remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+Warnings:
+Warning 1650 Unknown option 'tkey3'
+Warning 1650 Unknown option 'tkey4'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`='vvv',
+ KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1' `tkey4`='4v1'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unknown option 'fkey1'
+Warning 1650 Unknown option 'kkey1'
+Warning 1650 Unknown option 'TKEY1'
+Warning 1650 Unknown option 'tkey2'
+Warning 1650 Unknown option 'tkey3'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v1',
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+Warnings:
+Warning 1650 Unknown option 'FKEY1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `FKEY1`='v1',
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning 1650 Unknown option 'fkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new column no options
+alter table t1 add column b int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning 1650 Unknown option 'kkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+Warnings:
+Warning 1650 Unknown option 'fkey1'
+Warning 1650 Unknown option 'fkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#drop column
+alter table t1 drop b;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#add column with options after delete
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning 1650 Unknown option 'fkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ `b` int(11) DEFAULT NULL `fkey2`='v1',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#add key
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning 1650 Unknown option 'kkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`='v2',
+ `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+ `b` int(11) DEFAULT NULL `fkey2`='v1',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`),
+ KEY `bkey` (`b`) `kkey2`='v2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+drop table t1;
+create table t1 (a int) tkey1=100;
+Warnings:
+Warning 1650 Unknown option 'tkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=100
+drop table t1;
+#error on unknown option
+SET SQL_MODE='';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+ERROR HY000: Unknown option 'fkey'
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/r/events_bugs.result'
--- a/mysql-test/r/events_bugs.result 2009-03-11 20:30:56 +0000
+++ b/mysql-test/r/events_bugs.result 2010-04-05 08:49:56 +0000
@@ -729,9 +729,8 @@
create event e1 on schedule every 1 day do select 1;
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_ERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
name
=== modified file 'mysql-test/r/information_schema.result'
--- a/mysql-test/r/information_schema.result 2010-03-15 11:51:23 +0000
+++ b/mysql-test/r/information_schema.result 2010-04-05 08:49:56 +0000
@@ -615,7 +615,7 @@
proc definer char(77)
proc created timestamp
proc modified timestamp
-proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
proc comment char(64)
proc character_set_client char(32)
proc collation_connection char(32)
=== modified file 'mysql-test/r/plugin_load.result'
--- a/mysql-test/r/plugin_load.result 2008-01-26 00:05:15 +0000
+++ b/mysql-test/r/plugin_load.result 2010-04-05 08:49:56 +0000
@@ -1,3 +1,57 @@
SELECT @@global.example_enum_var = 'e2';
@@global.example_enum_var = 'e2'
1
+#legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `complex`='c,f,f,f'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000 `STR`='dskj' `one_or_two`='one' `YESNO`=0
+drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+#illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+Warnings:
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS'
+#alter table
+alter table t1 ULL=10000000;
+Warnings:
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS' `ULL`='10000000'
+alter table t1 change a a int complex='c,c,c';
+Warnings:
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+Warning 1651 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1651 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1651 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `complex`='c,c,c'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS' `ULL`='10000000'
+drop table t1;
+#illegal value error
+SET SQL_MODE='';
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+ERROR HY000: Incorrect value '10000000000000000000' for option 'ULL'
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result 2009-12-23 13:44:03 +0000
+++ b/mysql-test/r/sp.result 2010-04-05 08:49:56 +0000
@@ -6940,9 +6940,8 @@
call p();
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_NOERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
name
=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result 2009-10-27 10:09:36 +0000
+++ b/mysql-test/r/system_mysql_db.result 2010-04-05 08:49:56 +0000
@@ -200,7 +200,7 @@
`definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
- `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
@@ -225,7 +225,7 @@
`ends` datetime DEFAULT NULL,
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
- `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`originator` int(10) unsigned NOT NULL,
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2009-10-28 09:23:02 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-04-05 08:49:56 +0000
@@ -49,7 +49,7 @@
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned select,insert,update,references
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql event sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select,insert,update,references
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references
@@ -124,7 +124,7 @@
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql proc sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI select,insert,update,references
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references
@@ -327,7 +327,7 @@
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +402,7 @@
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result 2009-05-19 16:43:50 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result 2010-04-05 08:49:56 +0000
@@ -49,7 +49,7 @@
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE')
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64)
@@ -124,7 +124,7 @@
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER')
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64)
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL
@@ -327,7 +327,7 @@
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +402,7 @@
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== added file 'mysql-test/t/create_options.test'
--- a/mysql-test/t/create_options.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/create_options.test 2010-04-05 08:49:56 +0000
@@ -0,0 +1,68 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+show create table t1;
+drop table t1;
+
+--echo #reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+show create table t1;
+
+-- echo #add option
+alter table t1 tkey4=4v1;
+show create table t1;
+
+--echo #remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+show create table t1;
+
+drop table t1;
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+show create table t1;
+
+--echo #change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+show create table t1;
+--echo #change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+show create table t1;
+--echo #new column no options
+alter table t1 add column b int;
+show create table t1;
+--echo #new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+show create table t1;
+--echo #new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+show create table t1;
+--echo #new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+--echo #drop column
+alter table t1 drop b;
+show create table t1;
+--echo #add column with options after delete
+alter table t1 add column b int fkey2=v1;
+show create table t1;
+--echo #add key
+alter table t1 add key bkey (b) kkey2=v2;
+show create table t1;
+drop table t1;
+
+#numeric (unquoted) value
+create table t1 (a int) tkey1=100;
+show create table t1;
+drop table t1;
+
+--echo #error on unknown option
+SET SQL_MODE='';
+--error ER_UNKNOWN_OPTION
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/t/events_bugs.test'
--- a/mysql-test/t/events_bugs.test 2009-03-11 20:30:56 +0000
+++ b/mysql-test/t/events_bugs.test 2010-04-05 08:49:56 +0000
@@ -1204,7 +1204,6 @@
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
drop event e1;
=== modified file 'mysql-test/t/exampledb.test'
--- a/mysql-test/t/exampledb.test 2006-05-05 17:08:40 +0000
+++ b/mysql-test/t/exampledb.test 2010-04-05 08:49:56 +0000
@@ -20,3 +20,4 @@
drop table t1;
# End of 4.1 tests
+
=== modified file 'mysql-test/t/plugin_load.test'
--- a/mysql-test/t/plugin_load.test 2009-10-08 08:39:15 +0000
+++ b/mysql-test/t/plugin_load.test 2010-04-05 08:49:56 +0000
@@ -2,3 +2,30 @@
--source include/have_example_plugin.inc
SELECT @@global.example_enum_var = 'e2';
+
+--echo #legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+drop table t1;
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+
+--echo #illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+show create table t1;
+
+--echo #alter table
+alter table t1 ULL=10000000;
+show create table t1;
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+drop table t1;
+
+
+--echo #illegal value error
+SET SQL_MODE='';
+--error ER_BAD_OPTION_VALUE
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/t/sp.test'
--- a/mysql-test/t/sp.test 2009-12-23 13:44:03 +0000
+++ b/mysql-test/t/sp.test 2010-04-05 08:49:56 +0000
@@ -8210,7 +8210,6 @@
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
drop procedure p;
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql 2009-10-27 10:09:36 +0000
+++ b/scripts/mysql_system_tables.sql 2010-04-05 08:49:56 +0000
@@ -60,7 +60,7 @@
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
-CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
+CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'CREATE_OPTIONS_NOERR', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
@@ -80,7 +80,7 @@
EXECUTE stmt;
DROP PREPARE stmt;
-CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
+CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
=== modified file 'scripts/mysql_system_tables_fix.sql'
--- a/scripts/mysql_system_tables_fix.sql 2009-12-03 16:15:47 +0000
+++ b/scripts/mysql_system_tables_fix.sql 2010-04-05 08:49:56 +0000
@@ -368,7 +368,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_ERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -482,14 +482,14 @@
ALTER TABLE event DROP PRIMARY KEY;
ALTER TABLE event ADD PRIMARY KEY(db, name);
# Add sql_mode column just in case.
-ALTER TABLE event ADD sql_mode set ('NOT_USED') AFTER on_completion;
+ALTER TABLE event ADD sql_mode set ('CREATE_OPTIONS_ERR') AFTER on_completion;
# Update list of sql_mode values.
ALTER TABLE event MODIFY sql_mode
set('REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_ERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2010-03-03 14:44:14 +0000
+++ b/sql/CMakeLists.txt 2010-04-05 08:49:56 +0000
@@ -77,6 +77,7 @@
rpl_rli.cc rpl_mi.cc sql_servers.cc
sql_connect.cc scheduler.cc
sql_profile.cc event_parse_data.cc opt_table_elimination.cc
+ create_options.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/sql/Makefile.am 2010-04-05 08:49:56 +0000
@@ -78,7 +78,8 @@
sql_plugin.h authors.h event_parse_data.h \
event_data_objects.h event_scheduler.h \
sql_partition.h partition_info.h partition_element.h \
- contributors.h sql_servers.h
+ contributors.h sql_servers.h \
+ create_options.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -124,7 +125,7 @@
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \
sql_servers.cc event_parse_data.cc \
- opt_table_elimination.cc
+ opt_table_elimination.cc create_options.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
=== added file 'sql/create_options.cc'
--- a/sql/create_options.cc 1970-01-01 00:00:00 +0000
+++ b/sql/create_options.cc 2010-04-05 08:49:56 +0000
@@ -0,0 +1,651 @@
+#include "mysql_priv.h"
+#include <my_getopt.h>
+
+/* bits of first byte (type byte of frm imege) */
+#define FRM_TYPE_MASK 0x03
+#define FRM_QUATED_VALUE 0x80
+
+/**
+ Links this item to the given list end
+
+ @param start The list beginning or NULL
+ @param end The list last element or does not matter
+*/
+
+void engine_option_value::link(engine_option_value **start,
+ engine_option_value **end)
+{
+ engine_option_value *opt;
+ /* check duplicates to avoid writing them to frm*/
+ for(opt= *start;
+ opt && (opt->deleted ||
+ my_strnncoll(system_charset_info,
+ (uchar *)name.str, name.length,
+ (uchar*)opt->name.str, opt->name.length));
+ opt= opt->next) {};
+ if (opt)
+ {
+ /* remove previous value */
+ opt->value.str= NULL;
+ opt->parsed= TRUE;
+ opt->deleted= TRUE;
+ }
+ /*
+ Add this option to the end of the list
+
+ @note: We add even if it is opt->value.str == NULL because it can be
+ ALTER TABLE to remove the option.
+ */
+ if (*start)
+ {
+ (*end)->next= this;
+ *end= this;
+ }
+ else
+ {
+ *start= *end= this;
+ }
+}
+
+static bool report_wrong_value(THD *thd, const char *name, const char *val,
+ my_bool suppress_warning)
+{
+ if (!(thd->variables.sql_mode & MODE_CREATE_OPTIONS_NOERR))
+ {
+ my_error(ER_BAD_OPTION_VALUE, MYF(0), val, name);
+ return 1;
+ }
+
+ /*
+ We suppress errors to avoid double messages about the same value. It has
+ no sense to supress errors as they lead to execution abortion.
+ */
+ if (!suppress_warning)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_OPTION_VALUE,
+ ER(ER_BAD_OPTION_VALUE), val, name);
+ return 0;
+}
+
+static bool report_unknown_option(THD *thd, engine_option_value *val,
+ my_bool suppress_warning)
+{
+ DBUG_ENTER("report_unknown_option");
+ if (val->parsed)
+ {
+ DBUG_PRINT("info", ("parsed => exiting"));
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!(thd->variables.sql_mode & MODE_CREATE_OPTIONS_NOERR))
+ {
+ my_error(ER_UNKNOWN_OPTION, MYF(0), val->name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ We suppress errors to avoid double messages about the same value. It has
+ no sense to supress errors as they lead to execution abortion.
+ */
+ if (!suppress_warning)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_OPTION,
+ ER(ER_UNKNOWN_OPTION),
+ val->name.str);
+ DBUG_RETURN(FALSE);
+}
+
+static bool set_one_value(ha_create_table_option *opt,
+ THD *thd, LEX_STRING *value, void *base,
+ my_bool suppress_warning,
+ MEM_ROOT *root)
+{
+ DBUG_ENTER("set_one_value");
+ DBUG_PRINT("enter", ("opt: 0x%lx type: %u name '%s' value: '%s'",
+ (ulong) opt,
+ opt->type, opt->name,
+ (value->str ? value->str : "<DEFAULT>")));
+ switch (opt->type)
+ {
+ case HA_OPTION_TYPE_ULL:
+ {
+ ulonglong *val= (ulonglong*)((char*)base + opt->offset);
+ *val= opt->def_value;
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ my_option optp= { opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
+ REQUIRED_ARG, opt->def_value, opt->min_value, opt->max_value,
+ 0, opt->block_size, 0};
+
+ ulonglong orig_val= strtoull(value->str, NULL, 10);
+ my_bool unused;
+ *val= orig_val;
+ *val= getopt_ull_limit_value(*val, &optp, &unused);
+ if (*val == orig_val)
+ DBUG_RETURN(0);
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ case HA_OPTION_TYPE_STRING:
+ {
+ char **val= (char **)((char *)base + opt->offset);
+ *val= 0;
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (!(*val= strmake_root(root, value->str, value->length)))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+ }
+ case HA_OPTION_TYPE_ENUM:
+ {
+ uint *val= (uint *)((char *)base + opt->offset), num;
+ *val= opt->def_value;
+
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ const char *start= opt->values, *end;
+
+ num= 0;
+ while (*start)
+ {
+ for (end=start;
+ *end && *end != ',';
+ end+= my_mbcharlen(system_charset_info, *end)) /* no-op */;
+ if (!my_strnncoll(system_charset_info,
+ (uchar*)start, end-start,
+ (uchar*)value->str, value->length))
+ {
+ *val= num;
+ DBUG_RETURN(0);
+ }
+ if (*end) *end++;
+ start= end;
+ num++;
+ }
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ case HA_OPTION_TYPE_BOOL:
+ {
+ bool *val= (bool *)((char *)base + opt->offset);
+ *val= opt->def_value;
+
+ if (!value->str)
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (!my_strnncoll(system_charset_info,
+ (const uchar*)"NO", 2,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"OFF", 3,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"N", 1,
+ (uchar *)value->str, value->length))
+ {
+ *val= FALSE;
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!my_strnncoll(system_charset_info,
+ (const uchar*)"YES", 3,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"ON", 2,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"N", 1,
+ (uchar *)value->str, value->length))
+ {
+ *val= TRUE;
+ DBUG_RETURN(FALSE);
+ }
+
+ /* numeric value */
+ if (value->str[0] < '0' || value->str[0] > '9')
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+
+ if (strtoull(value->str, NULL, 10))
+ *val= 1;
+ else
+ *val= 0;
+
+ DBUG_RETURN(FALSE);
+ }
+ }
+ DBUG_ASSERT(0);
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ DBUG_RETURN(1);
+}
+
+static const size_t ha_option_type_sizeof[]=
+{ sizeof(ulonglong), sizeof(char *), sizeof(uint), sizeof(uint)};
+
+/**
+ Creates option structure and parses list of options in it
+
+ @param thd thread handler
+ @param option_struct where to store pointer on the option struct
+ @param option_list list of options given by user
+ @param rules list of option description by engine
+ @param suppress_warning second parse so we do not need warnings
+ @param root MEM_ROOT where allocate memory
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool parse_option_list(THD* thd, void **option_struct,
+ engine_option_value *option_list,
+ ha_create_table_option *rules,
+ my_bool suppress_warning,
+ MEM_ROOT *root)
+{
+ ha_create_table_option *opt;
+ size_t option_struct_size= 0;
+ engine_option_value *val= option_list;
+ DBUG_ENTER("parse_option_list");
+ DBUG_PRINT("enter",
+ ("struct: 0x%lx list: 0x%lx rules: 0x%lx suppres %u root 0x%lx",
+ (ulong) *option_struct, (ulong)option_list, (ulong)rules,
+ (uint) suppress_warning, (ulong) root));
+
+ if (rules)
+ {
+ LEX_STRING default_val= {NULL, 0};
+ for (opt= rules; opt->name; opt++)
+ set_if_bigger(option_struct_size, opt->offset +
+ ha_option_type_sizeof[opt->type]);
+
+ *option_struct= alloc_root(root, option_struct_size);
+
+ /* set all values to default */
+ for (opt= rules; opt->name; opt++)
+ set_one_value(opt, thd, &default_val, *option_struct,
+ suppress_warning, root);
+ }
+
+ for (; val; val= val->next)
+ {
+ //if (!val->value.str) continue; // skip deleted
+ for (opt= rules; opt && opt->name; opt++)
+ {
+ if (my_strnncoll(system_charset_info,
+ (uchar*)opt->name, opt->name_length,
+ (uchar*)val->name.str, val->name.length))
+ continue;
+
+ if (set_one_value(opt, thd, &val->value,
+ *option_struct, suppress_warning, root))
+ DBUG_RETURN(TRUE);
+ val->parsed= true;
+ break;
+ }
+ if (report_unknown_option(thd, val, suppress_warning))
+ DBUG_RETURN(TRUE);
+ val->parsed= true;
+ }
+
+ DBUG_RETURN(FALSE);;
+}
+
+
+/**
+ Parses all table/fields/keys options
+
+ @param thd thread handler
+ @param file handler of the table
+ @parem share descriptor of the table
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+ TABLE_SHARE *share)
+{
+ MEM_ROOT *root= &share->mem_root;
+ DBUG_ENTER("parse_engine_table_options");
+
+ if (parse_option_list(thd, &share->option_struct, share->option_list,
+ ht->table_opt_rules, TRUE, root))
+ DBUG_RETURN(TRUE);
+
+ for (Field **field= share->field; *field; field++)
+ {
+ if (parse_option_list(thd, &(*field)->option_struct, (*field)->option_list,
+ ht->field_opt_rules, TRUE, root))
+ DBUG_RETURN(TRUE);
+ }
+
+ for (uint index= 0; index < share->keys; index ++)
+ {
+ if (parse_option_list(thd, &share->key_info[index].option_struct,
+ share->key_info[index].option_list,
+ ht->key_opt_rules, TRUE, root))
+ DBUG_RETURN(TRUE);
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Returns representation length of key and value in the frm file
+*/
+
+uint engine_option_value::frm_length()
+{
+ /*
+ 2 bytes - value length
+ 1 byte - key length
+ */
+ return 2 + 1 + name.length + value.length;
+}
+
+
+/**
+ Returns length of representation of option list in the frm file
+
+ @param opt list of options;
+ @param overhead length of additional information per option
+
+ @returns length of image in frm
+*/
+
+static uint option_list_frm_length(engine_option_value *opt, uint overhead)
+{
+ uint res= 0;
+
+ for (; opt; opt= opt->next)
+ if (opt->value.str)
+ res+= opt->frm_length() + overhead;
+
+ return res;
+}
+
+
+/**
+ Calculates length of options image in the .frm
+
+ @param table_option_list list of table options
+ @param create_fields field descriptors list
+ @param keys number of keys
+ @param key_info array of key descriptors
+
+ @returns length of image in frm
+*/
+
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ uint res, index;
+ DBUG_ENTER("engine_table_options_frm_length");
+
+ /* 1 byte - record type */
+ res= option_list_frm_length(table_option_list, 1);
+
+ while ((field= it++))
+ {
+ /*
+ 1 byte - record type
+ 2 bytes - field number
+ */
+ res+= option_list_frm_length(field->option_list, 1 + 2);
+ }
+
+ for (index= 0; index < keys; index++, key_info++)
+ {
+
+ /*
+ 1 byte - record type
+ 2 bytes - key number
+ */
+ res+= option_list_frm_length(key_info->option_list, 1 + 2);
+ }
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Writes image of the key and value to the frm image buffer
+
+ @param buff pointer to the buffer free space beginning
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_option_value::frm_image(uchar *buff)
+{
+ buff[0]= name.length;
+ buff++;
+ memcpy(buff, name.str, name.length);
+ buff+= name.length;
+ int2store(buff, value.length);
+ buff+= 2;
+ memcpy(buff, (const uchar *) value.str, value.length);
+ buff+= value.length;
+ return buff;
+}
+
+/**
+ Writes image of the key and value to the frm image buffer
+
+ @param buff pointer to the buffer free space beginning
+ @param opt list of options;
+ @param type option type (CREATE_OPTION_*)
+ @param index for keys and fields index of them
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+static uchar *option_list_frm_image(uchar *buff,
+ engine_option_value *opt,
+ CREATE_OPTION_TYPES type,
+ uint index)
+{
+ for (; opt; opt= opt->next)
+ {
+ /* skip deleted options */
+ if (opt->value.str)
+ {
+ *(buff++)= (type | (opt->quoted_value ? FRM_QUATED_VALUE : 0));
+ if (type != CREATE_OPTION_TABLE)
+ {
+ int2store(buff, index);
+ buff+= 2;
+ }
+ buff= opt->frm_image(buff);
+ }
+ }
+
+ return buff;
+}
+
+
+/**
+ Writes options image in the .frm buffer
+
+ @param buff pointer to the buffer
+ @param table_option_list list of table options
+ @param create_fields field descriptors list
+ @param keys number of keys
+ @param key_info array of key descriptors
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ uint index;
+ DBUG_ENTER("engine_table_options_frm_image");
+
+ buff= option_list_frm_image(buff, table_option_list, CREATE_OPTION_TABLE, 0);
+
+ for (index= 0; (field= it++); index++)
+ buff= option_list_frm_image(buff, field->option_list,
+ CREATE_OPTION_FIELD, index);
+
+ for (index= 0; index < keys; index++, key_info++)
+ buff= option_list_frm_image(buff, key_info->option_list,
+ CREATE_OPTION_KEY, index);
+ DBUG_RETURN(buff);
+}
+
+/**
+ Reads name and value from buffer, then link it in the list
+
+ @param buff the buffer to read from
+ @param start The list beginning or NULL
+ @param end The list last element or does not matter
+ @param root MEM_ROOT for allocating
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+uchar *engine_option_value::frm_read(const uchar *buff,
+ engine_option_value **start,
+ engine_option_value **end,
+ MEM_ROOT *root)
+{
+ name.length= buff[0];
+ buff++;
+ if (!(name.str= strmake_root(root, (const char*)buff,
+ name.length)))
+ return NULL;
+ buff+= name.length;
+ value.length= uint2korr(buff);
+ buff+= 2;
+ if (!(value.str= strmake_root(root, (const char*)buff,
+ value.length)))
+ return NULL;
+ buff+= value.length;
+ link(start, end);
+ return (uchar *)buff;
+}
+
+
+/**
+ Reads options from this buffer
+
+ @param buff the buffer to read from
+ @param length buffer length
+ @param share table descriptor
+ @param root MEM_ROOT for allocating
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool engine_table_options_frm_read(const uchar *buff,
+ uint length,
+ TABLE_SHARE *share)
+{
+ const uchar *buff_end= buff + length;
+ engine_option_value *tbl_end, **fld_end, **key_end;
+ MEM_ROOT *root= &share->mem_root;
+ DBUG_ENTER("engine_table_options_frm_read");
+
+ /* temporary list end pointers to construct lists */
+ tbl_end= NULL;
+ if (!(fld_end= (engine_option_value **)
+ alloc_root(root, sizeof(engine_option_value *) * share->fields)) ||
+ !(key_end= (engine_option_value **)
+ alloc_root(root, sizeof(engine_option_value *) * share->keys)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ while (buff < buff_end)
+ {
+ engine_option_value *option;
+ CREATE_OPTION_TYPES type;
+ uint index= 0;
+
+ if (!(option= new (root) engine_option_value()))
+ DBUG_RETURN(TRUE);
+
+ DBUG_ASSERT(buff + 4 <= buff_end);
+
+ type= (CREATE_OPTION_TYPES)(FRM_TYPE_MASK & buff[0]);
+ option->set_quoted_value(FRM_QUATED_VALUE & buff[0]);
+ buff++;
+ switch (type) {
+ case CREATE_OPTION_FIELD:
+ index= uint2korr(buff);
+ buff+= 2;
+ if (!(buff= option->frm_read(buff,
+ &share->field[index]->option_list,
+ fld_end + index,
+ root)))
+ DBUG_RETURN(TRUE);
+ break;
+ case CREATE_OPTION_KEY:
+ index= uint2korr(buff);
+ buff+= 2;
+ if (!(buff= option->frm_read(buff,
+ &share->key_info[index].option_list,
+ key_end + index,
+ root)))
+ DBUG_RETURN(TRUE);
+ break;
+ case CREATE_OPTION_TABLE:
+ if (!(buff= option->frm_read(buff,
+ &share->option_list,
+ &tbl_end,
+ root)))
+ DBUG_RETURN(TRUE);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ DBUG_PRINT("info", ("type: %u index: %u key: '%s' value: '%s'",
+ (uint) type, (uint) index,
+ option->name.str, option->value.str));
+ }
+ DBUG_RETURN(FALSE);
+}
+
+/**
+ Adds (merges) chages to source
+*/
+
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+ engine_option_value *changes,
+ MEM_ROOT *root)
+{
+ engine_option_value *end, *opt;
+ DBUG_ENTER("merge_engine_table_options");
+
+ /* find last element */
+ if (source)
+ for (end= source; end->next; end= end->next){};
+
+ for (opt= changes; opt; opt= opt->next)
+ {
+ new (root) engine_option_value(opt->name,
+ opt->value.str, opt->value.length,
+ &source, &end);
+ }
+ DBUG_RETURN(source);
+}
=== added file 'sql/create_options.h'
--- a/sql/create_options.h 1970-01-01 00:00:00 +0000
+++ b/sql/create_options.h 2010-04-05 08:49:56 +0000
@@ -0,0 +1,139 @@
+/* Copyright (C) 2010 Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Engine defined options of tables/fields/keys in CREATE/ALTER TABLE.
+*/
+
+#ifndef SQL_CREATE_OPTIONS_INCLUDED
+#define SQL_CREATE_OPTIONS_INCLUDED
+
+class Item;
+#include "handler.h"
+
+/* types of cretate options records on disk, also it is length of extra data */
+typedef enum enum_create_options_type {
+ CREATE_OPTION_TABLE= 0,
+ CREATE_OPTION_KEY= 1,
+ CREATE_OPTION_FIELD= 2
+} CREATE_OPTION_TYPES;
+
+class engine_option_value: public Sql_alloc
+{
+ public:
+ LEX_STRING name;
+ LEX_STRING value;
+ engine_option_value *next;
+ bool parsed;
+ bool deleted;
+ bool quoted_value;
+ engine_option_value() :
+ next(NULL), parsed(false)
+ {}
+ engine_option_value(const char *name_arg, size_t name_len_arg,
+ const char *value_arg, size_t value_len_arg,
+ engine_option_value **start, engine_option_value **end) :
+ next(NULL), parsed(false), deleted(false), quoted_value(true)
+ {
+ name.str= const_cast<char*>(name_arg);
+ name.length= name_len_arg;
+ value.str= const_cast<char*>(value_arg);
+ value.length= value_len_arg;
+ link(start, end);
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ const char *value_arg, size_t value_len_arg,
+ engine_option_value **start, engine_option_value **end) :
+ name(name_arg), next(NULL), parsed(false), deleted(false),
+ quoted_value(true)
+ {
+ value.str= const_cast<char*>(value_arg);
+ value.length= value_len_arg;
+ link(start, end);
+ }
+ engine_option_value(const char *name_arg, size_t name_len_arg,
+ ulonglong value_arg,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root) :
+ next(NULL), parsed(false), deleted(false), quoted_value(false)
+ {
+ name.str= const_cast<char*>(name_arg);
+ name.length= name_len_arg;
+ if ((value.str= (char *)alloc_root(root, 22)))
+ {
+ value.length= my_snprintf(value.str, 22, "%llu", value_arg);
+ link(start, end);
+ }
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ ulonglong value_arg,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root) :
+ name(name_arg), next(NULL), parsed(false), deleted(false),
+ quoted_value(false)
+ {
+ if ((value.str= (char *)alloc_root(root, 22)))
+ {
+ value.length= my_snprintf(value.str, 22, "%llu", value_arg);
+ link(start, end);
+ }
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ ha_choice value_arg,
+ engine_option_value **start, engine_option_value **end) :
+ name(name_arg), next(NULL), parsed(false), deleted(false),
+ quoted_value(false)
+ {
+ value.length= 1;
+ switch (value_arg) {
+ case HA_CHOICE_UNDEF:
+ value.str= NULL;
+ value.length= 0;
+ break;
+ case HA_CHOICE_NO:
+ value.str= (char*)"0";
+ break;
+ case HA_CHOICE_YES:
+ value.str= (char*)"1";
+ break;
+ }
+ }
+ void set_quoted_value(bool quoted) {quoted_value= quoted;}
+ void link(engine_option_value **start, engine_option_value **end);
+ uint frm_length();
+ uchar *frm_image(uchar *buff);
+ uchar *frm_read(const uchar *buff,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root);
+};
+
+class handler;
+class THD;
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+ TABLE_SHARE *share);
+my_bool parse_option_list(THD* thd, void **option_struct,
+ engine_option_value *option_list,
+ ha_create_table_option *rules,
+ my_bool suppress_warning,
+ MEM_ROOT *root);
+my_bool engine_table_options_frm_read(const uchar *buff,
+ uint length,
+ TABLE_SHARE *share);
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+ engine_option_value *changes,
+ MEM_ROOT *root);
+#endif
=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc 2010-03-15 11:51:23 +0000
+++ b/sql/event_db_repository.cc 2010-04-05 08:49:56 +0000
@@ -105,7 +105,8 @@
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY',"
+ "'NO_UNSIGNED_SUBTRACTION',"
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2010-03-17 02:32:31 +0000
+++ b/sql/field.cc 2010-04-05 08:49:56 +0000
@@ -1306,14 +1306,13 @@
Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg)
- :ptr(ptr_arg), null_ptr(null_ptr_arg),
- table(0), orig_table(0), table_name(0),
- field_name(field_name_arg),
- 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),
- vcol_info(0), stored_in_db(TRUE)
+ :ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0),
+ table_name(0), field_name(field_name_arg), option_list(0),
+ option_struct(0), 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), vcol_info(0),
+ stored_in_db(TRUE)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -9567,7 +9566,8 @@
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,
- Virtual_column_info *fld_vcol_info)
+ Virtual_column_info *fld_vcol_info,
+ engine_option_value *create_opt)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9578,6 +9578,7 @@
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
+ option_list= create_opt;
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
@@ -10217,6 +10218,8 @@
decimals= old_field->decimals();
vcol_info= old_field->vcol_info;
stored_in_db= old_field->stored_in_db;
+ option_list= old_field->option_list;
+ option_struct= old_field->option_struct;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -10291,6 +10294,19 @@
/**
+ Makes a clone of this object for ALTER/CREATE TABLE
+
+ @param mem_root MEM_ROOT where to clone the field
+*/
+
+Create_field *Create_field::clone(MEM_ROOT *mem_root) const
+{
+ Create_field *res= new (mem_root) Create_field(*this);
+ return res;
+}
+
+
+/**
maximum possible display length for blob.
@return
=== modified file 'sql/field.h'
--- a/sql/field.h 2010-03-15 11:51:23 +0000
+++ b/sql/field.h 2010-04-05 08:49:56 +0000
@@ -137,6 +137,9 @@
struct st_table *table; // Pointer for table
struct st_table *orig_table; // Pointer to original table
const char **table_name, *field_name;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -2145,6 +2148,9 @@
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
+ engine_option_value *option_list;
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
@@ -2162,11 +2168,11 @@
*/
bool stored_in_db;
- Create_field() :after(0) {}
+ Create_field() :after(0), option_list(NULL), option_struct(NULL)
+ {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
- Create_field *clone(MEM_ROOT *mem_root) const
- { return new (mem_root) Create_field(*this); }
+ Create_field *clone(MEM_ROOT *mem_root) const;
void create_length_to_internal_length(void);
/* Init for a tmp table field. To be extended if need be. */
@@ -2178,8 +2184,8 @@
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,
- Virtual_column_info *vcol_info);
+ uint uint_geom_type, Virtual_column_info *vcol_info,
+ engine_option_value *option_list);
bool field_flags_are_binary()
{
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc 2010-04-05 08:49:56 +0000
@@ -1218,7 +1218,9 @@
DBUG_ENTER("prepare_new_partition");
if ((error= set_up_table_before_create(tbl, part_name, create_info,
- 0, p_elem)))
+ 0, p_elem)) ||
+ parse_engine_table_options(ha_thd(), file->ht,
+ file->table_share))
goto error_create;
if ((error= file->ha_create(part_name, tbl, create_info)))
{
@@ -1869,6 +1871,8 @@
{
if ((error= set_up_table_before_create(table_arg, from_buff,
create_info, i, NULL)) ||
+ parse_engine_table_options(ha_thd(), (*file)->ht,
+ (*file)->table_share) ||
((error= (*file)->ha_create(from_buff, table_arg, create_info))))
goto create_error;
}
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-03-15 11:51:23 +0000
+++ b/sql/handler.cc 2010-04-05 08:49:56 +0000
@@ -3716,7 +3716,12 @@
name= get_canonical_filename(table.file, share.path.str, name_buff);
+ if (parse_engine_table_options(thd, table.file->ht, &share))
+ goto err;
+
error= table.file->ha_create(name, &table, create_info);
+
+
VOID(closefrm(&table, 0));
if (error)
{
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2010-02-01 06:14:12 +0000
+++ b/sql/handler.h 2010-04-05 08:49:56 +0000
@@ -16,6 +16,9 @@
/* Definitions for parameters to do with handler-routines */
+#ifndef SQL_HANDLER_INCLUDED
+#define SQL_HANDLER_INCLUDED
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -23,6 +26,7 @@
#include <my_handler.h>
#include <ft_global.h>
#include <keycache.h>
+#include "create_options.h"
#ifndef NO_HASH
#define NO_HASH /* Not yet implemented */
@@ -516,6 +520,7 @@
struct st_table;
typedef struct st_table TABLE;
typedef struct st_table_share TABLE_SHARE;
+class engine_option;
struct st_foreign_key_info;
typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
@@ -549,6 +554,65 @@
enum log_status status;
};
+enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */
+ HA_OPTION_TYPE_STRING, /* char * */
+ HA_OPTION_TYPE_ENUM, /* uint */
+ HA_OPTION_TYPE_BOOL}; /* bool */
+
+#define HA_xOPTION_ULL(name, struc, field, def, min, max, blk_siz) \
+ { HA_OPTION_TYPE_ULL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, min, max, blk_siz, 0 }
+#define HA_xOPTION_STRING(name, struc, field) \
+ { HA_OPTION_TYPE_STRING, name, sizeof(name)-1, \
+ offsetof(struc, field), 0, 0, 0, 0, 0 }
+#define HA_xOPTION_ENUM(name, struc, field, values, def) \
+ { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, \
+ sizeof(values)-1, 0, values }
+#define HA_xOPTION_BOOL(name, struc, field, def) \
+ { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, 1, 0, 0 }
+#define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define HA_TOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_table_option_struct, field, def, min, max, blk_siz)
+#define HA_TOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_table_option_struct, field)
+#define HA_TOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def)
+#define HA_TOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_table_option_struct, field, def)
+#define HA_TOPTION_END HA_xOPTION_END
+
+#define HA_FOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_field_option_struct, field, def, min, max, blk_siz)
+#define HA_FOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_field_option_struct, field)
+#define HA_FOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def)
+#define HA_FOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_field_option_struct, field, def)
+#define HA_FOPTION_END HA_xOPTION_END
+
+#define HA_KOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_key_option_struct, field, def, min, max, blk_siz)
+#define HA_KOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_key_option_struct, field)
+#define HA_KOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_BOOL(name, field, values, def) \
+ HA_xOPTION_BOOL(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_END HA_xOPTION_END
+
+typedef struct st_ha_create_table_option {
+ enum ha_option_type type;
+ const char *name;
+ size_t name_length;
+ ptrdiff_t offset;
+ ulonglong def_value;
+ ulonglong min_value, max_value, block_size;
+ const char *values;
+} ha_create_table_option;
enum handler_iterator_type
{
@@ -721,7 +785,11 @@
int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
const char *name);
uint32 license; /* Flag for Engine License */
- void *data; /* Location for engines to keep personal structures */
+ /* CREATE OPTIONS rules for parameter parsing */
+ ha_create_table_option *table_opt_rules,
+ *field_opt_rules,
+ *key_opt_rules;
+
};
@@ -950,6 +1018,14 @@
bool varchar; /* 1 if table has a VARCHAR */
enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
enum ha_choice page_checksum; /* If we have page_checksums */
+ engine_option_value *option_list; /* list of table create options */
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
+ /* following 4 fields assigned only for check_if_incompatible_data() */
+ void *old_option_struct;
+ void **old_new_fileds_option_struct[2];
+ void **old_new_keys_option_struct[2];
+ uint fields, keys;
} HA_CREATE_INFO;
@@ -2241,3 +2317,5 @@
#define ha_binlog_wait(a) do {} while (0)
#define ha_binlog_end(a) do {} while (0)
#endif
+
+#endif
=== modified file 'sql/log_event.h'
--- a/sql/log_event.h 2010-03-15 11:51:23 +0000
+++ b/sql/log_event.h 2010-04-05 08:49:56 +0000
@@ -1371,7 +1371,7 @@
MODE_PIPES_AS_CONCAT==0x2
MODE_ANSI_QUOTES==0x4
MODE_IGNORE_SPACE==0x8
- MODE_NOT_USED==0x10
+ MODE_CREATE_OPTIONS_NOERR==0x10
MODE_ONLY_FULL_GROUP_BY==0x20
MODE_NO_UNSIGNED_SUBTRACTION==0x40
MODE_NO_DIR_IN_CREATE==0x80
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2010-03-15 11:51:23 +0000
+++ b/sql/mysql_priv.h 2010-04-05 08:49:56 +0000
@@ -54,7 +54,6 @@
#include "sql_plugin.h"
#include "scheduler.h"
#include "log_slow.h"
-
class Parser_state;
/**
@@ -520,7 +519,7 @@
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
-#define MODE_NOT_USED 16
+#define MODE_CREATE_OPTIONS_NOERR 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define MODE_NO_DIR_IN_CREATE 128
@@ -783,6 +782,7 @@
ulonglong *engine_data);
#include "sql_string.h"
#include "sql_list.h"
+#include "create_options.h"
#include "sql_map.h"
#include "my_decimal.h"
#include "handler.h"
@@ -1508,7 +1508,8 @@
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info);
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
@@ -2625,4 +2626,14 @@
#endif /* MYSQL_CLIENT */
+/* Define to force use of my_malloc() if the allocated memory block is big */
+
+#ifndef HAVE_ALLOCA
+#define my_safe_alloca(size, min_length) my_alloca(size)
+#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
+#else
+#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
+#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
+#endif
+
#endif /* MYSQL_PRIV_H */
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-15 11:51:23 +0000
+++ b/sql/mysqld.cc 2010-04-05 08:49:56 +0000
@@ -243,7 +243,7 @@
static const char *sql_mode_names[]=
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "CREATE_OPTIONS_NOERR", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"NO_DIR_IN_CREATE",
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
@@ -263,7 +263,7 @@
/*PIPES_AS_CONCAT*/ 15,
/*ANSI_QUOTES*/ 11,
/*IGNORE_SPACE*/ 12,
- /*?*/ 1,
+ /*CREATE_OPTIONS_NOERR*/ 20,
/*ONLY_FULL_GROUP_BY*/ 18,
/*NO_UNSIGNED_SUBTRACTION*/ 23,
/*NO_DIR_IN_CREATE*/ 16,
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2010-03-15 11:51:23 +0000
+++ b/sql/share/errmsg.txt 2010-04-05 08:49:56 +0000
@@ -6240,3 +6240,8 @@
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"
+
+ER_UNKNOWN_OPTION
+ eng "Unknown option '%-.64s'"
+ER_BAD_OPTION_VALUE
+ eng "Incorrect value '%-.64s' for option '%-.64s'"
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp.cc 2010-04-05 08:49:56 +0000
@@ -147,7 +147,8 @@
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY',"
+ "'NO_UNSIGNED_SUBTRACTION',"
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp_head.cc 2010-04-05 08:49:56 +0000
@@ -2216,7 +2216,7 @@
lex->charset ? lex->charset :
thd->variables.collation_database,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, NULL))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_class.cc 2010-04-05 08:49:56 +0000
@@ -106,6 +106,7 @@
key_create_info(rhs.key_create_info),
columns(rhs.columns, mem_root),
name(rhs.name),
+ option_list(rhs.option_list),
generated(rhs.generated)
{
list_copy_and_replace_each_value(columns, mem_root);
@@ -775,6 +776,7 @@
void THD::push_internal_handler(Internal_error_handler *handler)
{
+ DBUG_ENTER("THD::push_internal_handler");
if (m_internal_handler)
{
handler->m_prev_internal_handler= m_internal_handler;
@@ -784,6 +786,7 @@
{
m_internal_handler= handler;
}
+ DBUG_VOID_RETURN;
}
@@ -803,8 +806,10 @@
void THD::pop_internal_handler()
{
+ DBUG_ENTER("THD::pop_internal_handler");
DBUG_ASSERT(m_internal_handler != NULL);
m_internal_handler= m_internal_handler->m_prev_internal_handler;
+ DBUG_VOID_RETURN;
}
extern "C"
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_class.h 2010-04-05 08:49:56 +0000
@@ -204,13 +204,15 @@
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
+ engine_option_value *option_list;
bool generated;
Key(enum Keytype type_par, const char *name_arg,
KEY_CREATE_INFO *key_info_arg,
- bool generated_arg, List<Key_part_spec> &cols)
+ bool generated_arg, List<Key_part_spec> &cols,
+ engine_option_value *create_opt)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
- name(name_arg), generated(generated_arg)
+ name(name_arg), option_list(create_opt), generated(generated_arg)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -239,7 +241,7 @@
Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
- :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_insert.cc 2010-04-05 08:49:56 +0000
@@ -72,15 +72,6 @@
#endif
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
-/* Define to force use of my_malloc() if the allocated memory block is big */
-
-#ifndef HAVE_ALLOCA
-#define my_safe_alloca(size, min_length) my_alloca(size)
-#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
-#else
-#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
-#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
-#endif
/*
Check that insert/update fields are from the same single table of a view.
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_lex.h 2010-04-05 08:49:56 +0000
@@ -1747,6 +1747,11 @@
const char *stmt_definition_end;
/**
+ Collects create options for Field and KEY
+ */
+ engine_option_value *option_list, *option_list_last;
+
+ /**
During name resolution search only in the table list given by
Name_resolution_context::first_name_resolution_table and
Name_resolution_context::last_name_resolution_table
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_parse.cc 2010-04-05 08:49:56 +0000
@@ -6155,7 +6155,8 @@
char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info)
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6173,7 +6174,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::PRIMARY, NullS,
&default_key_create_info,
- 0, lex->col_list);
+ 0, lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6183,7 +6184,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
- lex->col_list);
+ lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6241,7 +6242,8 @@
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, vcol_info))
+ interval_list, cs, uint_geom_type, vcol_info,
+ create_options))
DBUG_RETURN(1);
lex->alter_info.create_list.push_back(new_field);
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_show.cc 2010-04-05 08:49:56 +0000
@@ -951,6 +951,30 @@
DBUG_RETURN(0);
}
+
+/**
+ Goes through all character combinations and ensure that it is number.
+
+ @param name attribute name
+ @param name_length length of name
+
+ @retval # Pointer to conflicting character
+ @retval 0 No conflicting character
+*/
+
+static const char *is_unsigned_number(const char *name, uint name_length)
+{
+ const char *end= name + name_length;
+
+ for (; name < end ; name++)
+ {
+ uchar chr= (uchar) *name;
+ if (chr < '0' || chr > '9')
+ return name;
+ }
+ return 0;
+}
+
/*
Go through all character combinations and ensure that sql_lex.cc can
parse it as an identifier.
@@ -1013,7 +1037,7 @@
/*
The identifier must be quoted as it includes a quote character or
- it's a keyword
+ it's a keyword
*/
VOID(packet->reserve(length*2 + 2));
@@ -1076,7 +1100,6 @@
return '`';
}
-
/* Append directory name (if exists) to CREATE INFO */
static void append_directory(THD *thd, String *packet, const char *dir_type,
@@ -1173,6 +1196,32 @@
return has_default;
}
+
+/**
+ Appends list of options to string
+
+ @param thd thread handler
+ @param packet string to append
+ @param opt list of options
+*/
+
+static void append_create_options(THD *thd, String *packet,
+ engine_option_value *opt)
+{
+ for(; opt; opt= opt->next)
+ {
+ DBUG_ASSERT(opt->value.str);
+ packet->append(' ');
+ append_identifier(thd, packet, opt->name.str, opt->name.length);
+ packet->append('=');
+ if (!opt->quoted_value && opt->value.length < 21 &&
+ is_unsigned_number(opt->value.str, opt->value.length) == NULL)
+ packet->append(opt->value.str, opt->value.length);
+ else
+ append_unescaped(packet, opt->value.str, opt->value.length);
+ }
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1355,6 +1404,8 @@
packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
+ if (field->option_list)
+ append_create_options(thd, packet, field->option_list);
}
key_info= table->key_info;
@@ -1426,6 +1477,8 @@
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
}
+ if (key_info->option_list)
+ append_create_options(thd, packet, key_info->option_list);
}
/*
@@ -1585,6 +1638,10 @@
packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
+ /* create_table_options can be NULL for temporary tables */
+ if (share->option_list)
+ append_create_options(thd, packet,
+ share->option_list);
append_directory(thd, packet, "DATA", create_info.data_file_name);
append_directory(thd, packet, "INDEX", create_info.index_file_name);
}
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_table.cc 2010-04-05 08:49:56 +0000
@@ -2863,6 +2863,11 @@
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
+ if (parse_option_list(thd, &sql_field->option_struct,
+ sql_field->option_list,
+ create_info->db_type->field_opt_rules, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
/*
For now skip fields that are not physically stored in the database
(virtual fields) and update their offset later
@@ -3061,6 +3066,12 @@
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
key_info->algorithm= key->key_create_info.algorithm;
+ key_info->option_list= key->option_list;
+ if (parse_option_list(thd, &key_info->option_struct,
+ key_info->option_list,
+ create_info->db_type->key_opt_rules, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
if (key->type == Key::FULLTEXT)
{
@@ -3438,6 +3449,12 @@
}
}
+ if (parse_option_list(thd, &create_info->option_struct,
+ create_info->option_list,
+ create_info->db_type->table_opt_rules, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
+
DBUG_RETURN(FALSE);
}
@@ -5679,6 +5696,7 @@
KEY_PART_INFO *key_part;
KEY_PART_INFO *end;
THD *thd= table->in_use;
+ uint i;
/*
Remember if the new definition has new VARCHAR column;
create_info->varchar will be reset in mysql_prepare_create_table.
@@ -5766,6 +5784,25 @@
DBUG_RETURN(0);
}
+ create_info->fields= table->s->fields;
+ create_info->keys= table->s->keys;
+ if (!(create_info->old_new_fileds_option_struct[0]=
+ (void**)thd->alloc(sizeof(void*) * 2 * (create_info->fields) +
+ sizeof(void*) * 2 * (create_info->keys))))
+ DBUG_RETURN(1);
+ bzero(create_info->old_new_fileds_option_struct[0],
+ sizeof(void*) * 2 * (create_info->fields) +
+ sizeof(void*) * 2 * (create_info->keys));
+ create_info->old_new_fileds_option_struct[1]=
+ create_info->old_new_fileds_option_struct[0] +
+ sizeof(void*) * (create_info->fields);
+ create_info->old_new_keys_option_struct[0]=
+ create_info->old_new_fileds_option_struct[1] +
+ sizeof(void*) * (create_info->fields);
+ create_info->old_new_keys_option_struct[1]=
+ create_info->old_new_keys_option_struct[0] +
+ sizeof(void*) * (create_info->keys);
+
/*
Use transformed info to evaluate possibility of fast ALTER TABLE
but use the preserved field to persist modifications.
@@ -5776,12 +5813,15 @@
/* Go through fields and check if the original ones are compatible
with new table.
*/
- for (f_ptr= table->field, new_field= new_field_it++,
+ for (i= 0, f_ptr= table->field, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++;
(field= *f_ptr);
+ i++,
f_ptr++, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++)
{
+ create_info->old_new_fileds_option_struct[0][i]= field->option_struct;
+
/* Make sure we have at least the default charset in use. */
if (!new_field->charset)
new_field->charset= create_info->default_table_charset;
@@ -5809,6 +5849,10 @@
DBUG_RETURN(0);
}
+ /* to allow check_if_incompatible_data compare */
+ create_info->old_new_fileds_option_struct[1][i]=
+ tmp_new_field->option_struct;
+
/* 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) ||
@@ -5934,8 +5978,9 @@
/*
Step through all keys of the new table and find matching old keys.
*/
- for (new_key= *key_info_buffer; new_key < new_key_end; new_key++)
+ for (i= 0, new_key= *key_info_buffer; new_key < new_key_end; i++, new_key++)
{
+ create_info->old_new_keys_option_struct[0][i]= new_key->option_struct;
/* Search an old key with the same name. */
for (table_key= table->key_info; table_key < table_key_end; table_key++)
{
@@ -5956,9 +6001,13 @@
}
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
}
+ else
+ create_info->old_new_keys_option_struct[1][i]=
+ new_key->option_struct;
}
/* Check if changes are compatible with current handler without a copy */
+ create_info->old_option_struct= table->s->option_struct;
if (table->file->check_if_incompatible_data(create_info, changes))
{
DBUG_PRINT("info", ("check_if_incompatible_data() -> "
@@ -6132,6 +6181,16 @@
}
restore_record(table, s->default_values); // Empty record for DEFAULT
+ if (create_info->option_list)
+ {
+ create_info->option_list=
+ merge_engine_table_options(table->s->option_list,
+ create_info->option_list,
+ thd->mem_root);
+ }
+ else
+ create_info->option_list= table->s->option_list;
+
/*
First collect all fields from table which isn't in drop_list
*/
@@ -6384,7 +6443,7 @@
key= new Key(key_type, key_name,
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts);
+ key_parts, key_info->option_list);
new_key_list.push_back(key);
}
}
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2010-03-04 08:03:07 +0000
+++ b/sql/sql_view.cc 2010-04-05 08:49:56 +0000
@@ -1183,7 +1183,7 @@
+ MODE_PIPES_AS_CONCAT affect expression parsing
+ MODE_ANSI_QUOTES affect expression parsing
+ MODE_IGNORE_SPACE affect expression parsing
- - MODE_NOT_USED not used :)
+ - MODE_CREATE_OPTIONS_NOERR affect only CREATE/ALTER TABLE parsing
* MODE_ONLY_FULL_GROUP_BY affect execution
* MODE_NO_UNSIGNED_SUBTRACTION affect execution
- MODE_NO_DIR_IN_CREATE affect table creation only
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-03-15 11:51:23 +0000
+++ b/sql/sql_yacc.yy 2010-04-05 08:49:56 +0000
@@ -607,6 +607,7 @@
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change= NullS;
+ lex->option_list= lex->option_list_last= NULL;
return FALSE;
}
@@ -616,7 +617,7 @@
{
Key *key;
key= new Key(type, name, info ? info : &lex->key_create_info, generated,
- lex->col_list);
+ lex->col_list, lex->option_list);
if (key == NULL)
return TRUE;
@@ -3895,7 +3896,11 @@
;
create2a:
- field_list ')' opt_create_table_options
+ field_list ')'
+ {
+ Lex->create_info.option_list= Lex->option_list_last= NULL;
+ }
+ opt_create_table_options
opt_partitioning
create3 {}
| opt_partitioning
@@ -4748,6 +4753,39 @@
Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
Lex->create_info.transactional= $3;
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
;
default_charset:
@@ -4869,25 +4907,33 @@
;
key_def:
- normal_key_type opt_ident key_alg '(' key_list ')' normal_key_options
+ normal_key_type opt_ident key_alg '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $1, $2))
MYSQL_YYABORT;
}
| fulltext opt_key_or_index opt_ident init_key_options
- '(' key_list ')' fulltext_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ fulltext_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| spatial opt_key_or_index opt_ident init_key_options
- '(' key_list ')' spatial_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ spatial_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| opt_constraint constraint_key_type opt_ident key_alg
- '(' key_list ')' normal_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $2, $3 ? $3 : $1))
MYSQL_YYABORT;
@@ -4950,6 +4996,7 @@
lex->comment=null_lex_str;
lex->charset=NULL;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
field_def
{
@@ -4960,7 +5007,7 @@
&lex->comment,
lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
;
@@ -5380,6 +5427,39 @@
Lex->charset=$2;
}
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
;
now_or_signed_literal:
@@ -5669,6 +5749,39 @@
all_key_opt:
KEY_BLOCK_SIZE opt_equal ulong_num
{ Lex->key_create_info.block_size= $3; }
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ }
;
normal_key_opt:
@@ -6158,6 +6271,7 @@
LEX *lex=Lex;
lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->option_list= lex->option_list_last= NULL;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -6169,6 +6283,7 @@
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
field_def
{
@@ -6180,7 +6295,7 @@
&lex->comment,
$3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
opt_place
@@ -6287,8 +6402,7 @@
}
| create_table_options_space_separated
{
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_OPTIONS;
+ Lex->alter_info.flags|= ALTER_OPTIONS;
}
| FORCE_SYM
{
@@ -13630,6 +13744,7 @@
lex->interval_list.empty();
lex->type= 0;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
type /* $11 */
{ /* $12 */
@@ -13880,6 +13995,7 @@
}
;
+
/**
@} (end of group Parser)
*/
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2010-02-01 06:14:12 +0000
+++ b/sql/structs.h 2010-04-05 08:49:56 +0000
@@ -68,6 +68,7 @@
uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;
+class engine_option_value;
typedef struct st_key {
uint key_length; /* Tot length of key */
@@ -101,6 +102,9 @@
int bdb_return_if_eq;
} handler;
struct st_table *table;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
} KEY;
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/table.cc 2010-04-05 08:49:56 +0000
@@ -667,12 +667,13 @@
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 extra_rec_buf_length, options_len;
uint i,j;
bool use_hash;
char *keynames, *names, *comment_pos, *vcol_screen_pos;
uchar *record;
- uchar *disk_buff, *strpos, *null_flags, *null_pos;
+ uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+ uchar *buff= 0;
ulong pos, record_offset, *rec_per_key, rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -788,7 +789,6 @@
for (i=0 ; i < keys ; i++, keyinfo++)
{
- keyinfo->table= 0; // Updated in open_frm
if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -858,15 +858,14 @@
if ((n_length= uint4korr(head+55)))
{
/* Read extra data segment */
- uchar *buff, *next_chunk, *buff_end;
+ uchar *next_chunk, *buff_end;
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
goto err;
if (my_pread(file, buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
share->connect_string.length= uint2korr(buff);
if (!(share->connect_string.str= strmake_root(&share->mem_root,
@@ -874,8 +873,7 @@
share->connect_string.
length)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
next_chunk+= share->connect_string.length + 2;
buff_end= buff + n_length;
@@ -895,8 +893,7 @@
plugin_data(tmp_plugin, handlerton *)))
{
/* bad file, legacy_db_type did not match the name */
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
/*
tmp_plugin is locked with a local lock.
@@ -925,8 +922,7 @@
error= 8;
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
@@ -940,8 +936,7 @@
/* purecov: begin inspected */
error= 8;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
/* purecov: end */
}
next_chunk+= str_db_type_length + 2;
@@ -957,16 +952,14 @@
memdup_root(&share->mem_root, next_chunk + 4,
partition_info_len + 1)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
#else
if (partition_info_len)
{
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
#endif
next_chunk+= 5 + partition_info_len;
@@ -992,6 +985,16 @@
#endif
next_chunk++;
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ /*
+ store options position, but skip till the time we will
+ know number of fields
+ */
+ options_len= uint4korr(next_chunk);
+ options= next_chunk + 4;
+ next_chunk+= options_len + 4;
+ }
keyinfo= share->key_info;
for (i= 0; i < keys; i++, keyinfo++)
{
@@ -1002,8 +1005,7 @@
{
DBUG_PRINT("error",
("fulltext key uses parser that is not defined in .frm"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
parser_name.str= (char*) next_chunk;
parser_name.length= strlen((char*) next_chunk);
@@ -1013,12 +1015,10 @@
if (! keyinfo->parser)
{
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
}
- my_free(buff, MYF(0));
}
share->key_block_size= uint2korr(head+62);
@@ -1028,21 +1028,21 @@
share->rec_buff_length= rec_buff_length;
if (!(record= (uchar *) alloc_root(&share->mem_root,
rec_buff_length)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->default_values= record;
if (my_pread(file, record, (size_t) share->reclength,
record_offset, MYF(MY_NABP)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file, head,288,MYF(MY_NABP)))
- goto err;
+ goto free_and_err;
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err; // Wrong password
+ goto free_and_err; // Wrong password
}
#endif
@@ -1062,6 +1062,8 @@
share->comment.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*)+
@@ -1070,14 +1072,14 @@
keys+3)*sizeof(char *)+
(n_length+int_length+com_length+
vcol_screen_length)))))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->field= field_ptr;
read_length=(uint) (share->fields * field_pack_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 */
+ goto free_and_err; /* purecov: inspected */
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
@@ -1104,7 +1106,7 @@
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
if (share->fieldnames.count != share->fields)
- goto err;
+ goto free_and_err;
fix_type_pointers(&interval_array, share->intervals, interval_count,
&names);
@@ -1118,7 +1120,7 @@
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
count)))
- goto err;
+ goto free_and_err;
for (count= 0; count < interval->count; count++)
{
char *val= (char*) interval->type_names[count];
@@ -1134,7 +1136,7 @@
/* Allocate handler */
if (!(handler_file= get_new_handler(share, thd->mem_root,
share->db_type())))
- goto err;
+ goto free_and_err;
record= share->default_values-1; /* Fieldstart = 1 */
if (share->null_field_first)
@@ -1196,7 +1198,7 @@
charset= &my_charset_bin;
#else
error= 4; // unsupported field type
- goto err;
+ goto free_and_err;
#endif
}
else
@@ -1207,7 +1209,7 @@
{
error= 5; // Unknown or unavailable charset
errarg= (int) strpos[14];
- goto err;
+ goto free_and_err;
}
}
@@ -1247,7 +1249,7 @@
if ((uint)vcol_screen_pos[0] != 1)
{
error= 4;
- goto err;
+ goto free_and_err;
}
field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
fld_stored_in_db= (bool) (uint) vcol_screen_pos[2];
@@ -1256,7 +1258,7 @@
(char *)memdup_root(&share->mem_root,
vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE,
vcol_expr_length)))
- goto err;
+ goto free_and_err;
vcol_info->expr_str.length= vcol_expr_length;
vcol_screen_pos+= vcol_info_length;
share->vfields++;
@@ -1346,7 +1348,7 @@
if (!reg_field) // Not supported field type
{
error= 4;
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
}
reg_field->field_index= i;
@@ -1385,7 +1387,7 @@
sent (OOM).
*/
error= 8;
- goto err;
+ goto free_and_err;
}
}
if (!reg_field->stored_in_db)
@@ -1462,7 +1464,7 @@
if (!key_part->fieldnr)
{
error= 4; // Wrong file
- goto err;
+ goto free_and_err;
}
field= key_part->field= share->field[key_part->fieldnr-1];
key_part->type= field->key_type();
@@ -1627,6 +1629,15 @@
null_length, 255);
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ DBUG_ASSERT(options_len);
+ if (engine_table_options_frm_read(options, options_len, share) ||
+ parse_engine_table_options(thd, handler_file->ht, share))
+ goto free_and_err;
+ }
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
if (share->found_next_number_field)
{
reg_field= *share->found_next_number_field;
@@ -1685,6 +1696,8 @@
#endif
DBUG_RETURN (0);
+ free_and_err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
err:
share->error= error;
share->open_errno= my_errno;
@@ -2883,6 +2896,7 @@
ulong length;
uchar fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
+ DBUG_ENTER("create_frm");
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2964,7 +2978,7 @@
{
VOID(my_close(file,MYF(0)));
VOID(my_delete(name,MYF(0)));
- return(-1);
+ DBUG_RETURN(-1);
}
}
}
@@ -2975,7 +2989,7 @@
else
my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
}
- return (file);
+ DBUG_RETURN(file);
} /* create_frm */
@@ -2994,6 +3008,7 @@
create_info->comment= share->comment;
create_info->transactional= share->transactional;
create_info->page_checksum= share->page_checksum;
+ create_info->option_list= share->option_list;
DBUG_VOID_RETURN;
}
=== modified file 'sql/table.h'
--- a/sql/table.h 2010-02-12 08:47:31 +0000
+++ b/sql/table.h 2010-04-05 08:49:56 +0000
@@ -340,6 +340,8 @@
#ifdef NOT_YET
struct st_table *open_tables; /* link to open tables */
#endif
+ engine_option_value *option_list; /* text options for table */
+ void *option_struct; /* structure with parsed options */
/* The following is copied to each TABLE on OPEN */
Field **field;
=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc 2010-01-04 17:54:42 +0000
+++ b/sql/unireg.cc 2010-04-05 08:49:56 +0000
@@ -29,6 +29,9 @@
#define FCOMP 17 /* Bytes for a packed field */
+/* max length of options in frm which be allocated on stack */
+#define OPTIONS_ON_STACK 256
+
static uchar * pack_screens(List<Create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
@@ -46,6 +49,18 @@
uint reclength, ulong data_offset,
handler *handler);
+/*
+ We declare engine_table_options_frm_length end
+ engine_table_options_frm_image here because
+ List, Create_field, KEY are not declared in create_options.h
+*/
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
/**
An interceptor to hijack ER_TOO_MANY_FIELDS error from
pack_screens and retry again without UNIREG screens.
@@ -75,6 +90,7 @@
return is_handled;
}
+
/*
Create a frm (table definition) file
@@ -107,6 +123,7 @@
ulong key_buff_length;
File file;
ulong filepos, data_offset;
+ uint options_len;
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
@@ -183,6 +200,15 @@
create_info->extra_size+= key_info[i].parser_name->length + 1;
}
+ options_len= engine_table_options_frm_length(create_info->option_list,
+ create_fields,
+ keys, key_info);
+ if (options_len)
+ {
+ create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+ create_info->extra_size+= (options_len + 4);
+ }
+
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
{
@@ -294,6 +320,25 @@
if (my_write(file, (uchar*) buff, 6, MYF_RW))
goto err;
}
+
+ if (options_len)
+ {
+ uchar *optbuff= (uchar *)my_safe_alloca(options_len + 4, OPTIONS_ON_STACK);
+ my_bool error;
+ DBUG_PRINT("info", ("Create options length: %u", options_len));
+ if (!optbuff)
+ goto err;
+ int4store(optbuff, options_len);
+ engine_table_options_frm_image(optbuff + 4,
+ create_info->option_list,
+ create_fields,
+ keys, key_info);
+ error= my_write(file, optbuff, options_len + 4, MYF_RW);
+ my_safe_afree(optbuff, options_len + 4, OPTIONS_ON_STACK);
+ if (error)
+ goto err;
+ }
+
for (i= 0; i < keys; i++)
{
if (key_info[i].parser_name)
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc 2010-04-05 08:49:56 +0000
@@ -113,6 +113,47 @@
/* The mutex used to init the hash; variable for example share methods */
pthread_mutex_t example_mutex;
+
+/**
+ structure for CREATE TABLE options (table options)
+*/
+
+struct example_table_options_struct
+{
+ const char *strparam;
+ ulonglong ullparam;
+ uint enumparam;
+ bool boolparam;
+};
+
+
+/**
+ structure for CREATE TABLE options (table options)
+*/
+
+struct example_field_options_struct
+{
+ const char *compex_param_to_parse_it_in_engine;
+};
+
+#define ha_table_option_struct example_table_options_struct
+ha_create_table_option example_table_option_list[]=
+{
+ HA_TOPTION_ULL("ULL", ullparam, UINT_MAX32, 0, UINT_MAX32, 1),
+ HA_TOPTION_STRING("STR", strparam),
+ HA_TOPTION_ENUM("one_or_two", enumparam, "one,two", 0),
+ HA_TOPTION_BOOL("YESNO", boolparam, 1),
+ HA_TOPTION_END
+};
+
+#define ha_field_option_struct example_field_options_struct
+ha_create_table_option example_field_option_list[]=
+{
+ HA_FOPTION_STRING("COMPLEX", compex_param_to_parse_it_in_engine),
+ HA_FOPTION_END
+};
+
+
/**
@brief
Function we use in the creation of our hash to get key.
@@ -138,6 +179,9 @@
example_hton->state= SHOW_OPTION_YES;
example_hton->create= example_create_handler;
example_hton->flags= HTON_CAN_RECREATE;
+ example_hton->table_opt_rules= example_table_option_list;
+ example_hton->field_opt_rules= example_field_option_list;
+ example_hton->key_opt_rules= NULL;
DBUG_RETURN(0);
}
@@ -774,27 +818,6 @@
/**
@brief
- Renames a table from one name to another via an alter table call.
-
- @details
- If you do not implement this, the default rename_table() is called from
- handler.cc and it will delete all files with the file extensions returned
- by bas_ext().
-
- Called from sql_table.cc by mysql_rename_table().
-
- @see
- mysql_rename_table() in sql_table.cc
-*/
-int ha_example::rename_table(const char * from, const char * to)
-{
- DBUG_ENTER("ha_example::rename_table ");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/**
- @brief
Given a starting key and an ending key, estimate the number of rows that
will exist between the two keys.
@@ -836,15 +859,110 @@
int ha_example::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
+ example_table_options_struct *prm=
+ (example_table_options_struct *)table_arg->s->option_struct;
DBUG_ENTER("ha_example::create");
/*
- This is not implemented but we want someone to be able to see that it
- works.
+ This example shows how to support custom engine specific table and field
+ options.
*/
+ DBUG_ASSERT(prm);
+ DBUG_PRINT("info", ("strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prm->strparam ? prm->strparam : "<NULL>"),
+ prm->ullparam, prm->enumparam, prm->boolparam));
+ for (Field **field= table_arg->s->field; *field; field++)
+ {
+ example_field_options_struct *fprm=
+ (example_field_options_struct *)(*field)->option_struct;
+ DBUG_ASSERT(fprm);
+ DBUG_PRINT("info", ("field: %s complex: '%-.64s'",
+ (*field)->field_name,
+ (fprm->compex_param_to_parse_it_in_engine ?
+ fprm->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+
+ }
+
DBUG_RETURN(0);
}
+/**
+ check_if_incompatible_data() called if ALTER TABLE can't detect otherwise
+ if new and old definition are compatible
+
+ @details If there are no other explicit signs like changed number of
+ fields this function will be called by compare_tables()
+ (sql/sql_tables.cc) to decide should we rewrite whole table or only .frm
+ file.
+
+*/
+
+bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes)
+{
+ example_table_options_struct *prmo, *prmn;
+ uint i;
+ DBUG_ENTER("ha_example::check_if_incompatible_data");
+ DBUG_ASSERT(info->option_struct);
+ DBUG_ASSERT(info->old_option_struct);
+ /*
+ This example shows how custom engine specific table and field
+ options can be accessed from this function to be compared.
+ */
+
+ prmn= (example_table_options_struct *)info->option_struct;
+ DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prmn->strparam ? prmn->strparam : "<NULL>"),
+ prmn->ullparam, prmn->enumparam, prmn->boolparam));
+
+ prmo= (example_table_options_struct *)info->old_option_struct;
+ DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prmo->strparam ? prmo->strparam : "<NULL>"),
+ prmo->ullparam, prmo->enumparam, prmo->boolparam));
+
+ /* check important parameters */
+ if (prmn->ullparam != prmo->ullparam || prmn->boolparam != prmo->boolparam)
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+
+ for (i= 0; i < info->fields; i++)
+ {
+ example_field_options_struct *fprmo, *fprmn;
+ if (info->old_new_fileds_option_struct[1][i])
+ {
+ fprmn=
+ (example_field_options_struct *)
+ info->old_new_fileds_option_struct[1][i];
+ DBUG_PRINT("info", ("old field: %u new complex: '%-.64s'", i,
+ (fprmn->compex_param_to_parse_it_in_engine ?
+ fprmn->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ /*
+ if (!structure_is_the_same(fprmn->compex_param_to_parse_it_in_engine,
+ fprmo->compex_param_to_parse_it_in_engine)
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+ */
+ }
+ else
+ DBUG_PRINT("info", ("old field %i did not changed", i));
+
+ fprmo=
+ (example_field_options_struct *)info->old_new_fileds_option_struct[0][i];
+ DBUG_ASSERT(fprmo);
+ DBUG_PRINT("info", ("old field: %u old complex: '%-.64s'", i,
+ (fprmo->compex_param_to_parse_it_in_engine ?
+ fprmo->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ }
+
+ DBUG_RETURN(COMPATIBLE_DATA_YES);
+}
+
+
+
struct st_mysql_storage_engine example_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
=== modified file 'storage/example/ha_example.h'
--- a/storage/example/ha_example.h 2007-08-13 13:11:25 +0000
+++ b/storage/example/ha_example.h 2010-04-05 08:49:56 +0000
@@ -242,9 +242,10 @@
ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
- int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required
+ bool check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required
=== modified file 'storage/pbxt/src/discover_xt.cc'
--- a/storage/pbxt/src/discover_xt.cc 2010-02-01 06:14:12 +0000
+++ b/storage/pbxt/src/discover_xt.cc 2010-04-05 08:49:56 +0000
@@ -1623,7 +1623,7 @@
#endif
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/,
- NULL /*vcol_info*/))
+ NULL /*vcol_info*/, NULL /* create options */))
#endif
goto error;
1
0
W dniu 2010-04-04 12:59, Henrik Ingo pisze:
> On Sat, Apr 3, 2010 at 8:23 PM, Mchl<mchlpl(a)gmail.com> wrote:
>> Regarding comment from colincharles here:
>> http://www.bytebot.net/blog/archives/2010/04/02/mariadb-5-1-44-released
>
> Hi Mchl!
>
> I'm currently traveling / on easter vacation, but Colin or Kristian
> Cc'd here can respond to your questions.
>
>> I am assuming that by 'resources' needed for creeating win32 builds, you
>> mean a buildbot slave.
>
> Yes and no. If you want to contribute a buildbot slave, this is appreciated.
>
> But with the above we actually refer to the fact that most of our
> developers use Linux as primary platform, and the QA and build system
> doesn't work "by itself" on Windows, so we actually would need someone
> to work on the build scripts, the automated tests and even fix MariaDB
> source code on Windows. Currently MariaDB does not compile at all on
> 64 bit Windows, and the test scripts are unreliable producing spurious
> failures that are not real MariaDB failures.
>
>> I have an Athlon XP box under my desk, which used to be my primary
>> machine, but right now is being used mostly for backups, so most of the
>> time it does nothing but gathers dust. I could probably set it up with
>> another hard disk, install Windows XP/Vista on it and donate it for
>> MariaDB builds. It depends on a few factors though.
>> 1. How autoamted is the process? Ideally all I would like to do is to
>> switch the power on, login and let the machine do its job with as little
>> interaction from my side as possible.
>> 2. How often and for how long would it need to run? I can run it for
>> 8-10 hours several times a week, but certainly not 24/7
>> 3. How much upload/download bandwidth is required? While my download
>> bandwidth is pretty good, my upload is not. Still, as long as we are not
>> talking several tens of gigabytes per day, I should manage.
>>
>> Also please take into consideration, that I've never done anything like
>> this before, so I might require a lot of help setting this up.
>>
>> Please tell me what you think! ;)
>
> Colin and Kristian will help you out here...
>
> Thanks for offering to help!
>
> henrik
>
>
Thanks a lot for replying!
That doesn't sound too good to me. I'm mostly PHP/JS developer, and
while I know some C++ it is almost certainly too little to be able to
contribute to MariaDB code. Most of all I'm afraid I cannot commit much
time to this.
I will take a look at how all this looks like, but it can be just way
over my head.
Anyway, if this doesn't work, this machine is still here to use if you
have a need for a slave for any linux flavor (or other OS) I could
install on this hardware and that would be less problematic to maintain
for an unexperienced person like me.
Also I would like to apologise to all list members, for apparently
contacting them directly instead of posting to the list. It was my first
attempt at using launchpad's lists, and it seems I did something wrong.
Mchl
1
0

Re: [Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2742) WL#86
by Michael Widenius 04 Apr '10
by Michael Widenius 04 Apr '10
04 Apr '10
Hi!
>>>>> "Igor" == Igor Babaev <igor(a)askmonty.org> writes:
Igor> Please review this patch that is based on the contribution patch
Igor> attached to WL#86.
<cut>
First some things we discussed in Iceland:
Functions with starts with s_.... should be changed to simple_....
Move select.test to suite/select and run it with different keycache
parameters (to not repeat select.result)
Igor> 2742 Igor Babaev 2010-02-16
Igor> WL#86: Partitioned key cache for MyISAM.
Igor> This is the base patch for the task.
Igor> === modified file 'mysys/mf_keycache.c'
Igor> +#define KEYCACHE_BASE_EXPR(f, pos)
Igor> \
Igor> + ((ulong) ((pos) / keycache->key_cache_block_size) + (ulong) (f))
Igor> #define KEYCACHE_HASH(f, pos)
Igor> \
Igor> -(((ulong) ((pos) / keycache->key_cache_block_size) +
Igor> \
Igor> - (ulong) (f)) &
Igor> (keycache->hash_entries-1))
Igor> + ((KEYCACHE_BASE_EXPR(f, pos) / keycache->hash_factor) &
Igor> \
Igor> + (keycache->hash_entries-1))
Igor> #define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
As all the divisiors are powers of two, would it be more efficent to store
the shift factor in 'keycache' and do shifts instead of / ?
(I assume that even on modern CPU:s shift is much faster then /)
Igor> +static
Igor> +void s_finish_resize_key_cache(void *keycache_cb,
Igor> + my_bool with_resize_queue,
Igor> + my_bool acquire_lock)
Igor> +{
Igor> + S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
Igor> + DBUG_ENTER("s_finish_resize_key_cache");
Igor> +
Igor> + if (acquire_lock)
Igor> + keycache_pthread_mutex_lock(&keycache->cache_lock);
Igor> +
Add after this:
safe_mutex_assert_owner((&keycache->cache_lock);
<cut>
Igor> +static
Igor> +int s_resize_key_cache(void *keycache_cb, uint key_cache_block_size,
Igor> + size_t use_mem, uint division_limit,
Igor> + uint age_threshold)
Igor> +{
Igor> + S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
It may be better if this function would take S_KEY_CACHE_CB as a parameter.
This can easily be done by doing a cast when storing the function pointer
into the st_key_cache_funcs array.
This way all casts are in one place and all real functions can avoid
casts. The same thing applies for all other interface functions.
This mainly makes the real code look a bit nicer
Igor> + int blocks= 0;
Igor> + DBUG_ENTER("s_resize_key_cache");
Igor> +
Igor> + if (!keycache->key_cache_inited)
Igor> + DBUG_RETURN(keycache->disk_blocks);
Shouldn't we return 0 if cache was not initied ?
(if not inited, disk_blocks may contain random data)
Igor> @@ -670,7 +894,7 @@ finish:
Igor> /*
Igor> Increment counter blocking resize key cache operation
Igor> */
Igor> -static inline void inc_counter_for_resize_op(KEY_CACHE *keycache)
Igor> +static inline void inc_counter_for_resize_op(S_KEY_CACHE_CB *keycache)
Igor> {
Igor> keycache->cnt_for_resize_op++;
Igor> }
Igor> @@ -680,35 +904,49 @@ static inline void inc_counter_for_resiz
Igor> Decrement counter blocking resize key cache operation;
Igor> Signal the operation to proceed when counter becomes equal zero
Igor> */
Igor> -static inline void dec_counter_for_resize_op(KEY_CACHE *keycache)
Igor> +static inline void dec_counter_for_resize_op(S_KEY_CACHE_CB *keycache)
Many changes are just like the one above.
Wouldn't it been easier to keep KEY_CACHE as the orignal value
and add KEY_CACHE_MULTI as the new one ?
(This would make future merger with the MySQL code easier too)
<cut>
Igor> +
Igor> +/*
Igor> + Get statistics for a simple key cache
Igor> +
Igor> + SYNOPSIS
Igor> + get_key_cache_statistics()
Igor> + keycache_cb pointer to the control block of a simple key cache
Igor> + partition_no partition number (not used)
Igor> + key_cache_stats OUT pointer to the structure for the returned
Igor> statistics
Igor> +
Igor> + DESCRIPTION
Igor> + This function is the implementation of the get_key_cache_statistics
Igor> + interface function that is employed by simple (non-partitioned) key
Igor> caches.
Igor> + The function considers the parameter keycache_cb as a pointer to the
Igor> + control block structure of the type S_KEY_CACHE_CB for a simple key
Igor> cache.
Igor> + This function returns the statistical data for the key cache.
Igor> + The parameter partition_no is not used by this function.
Igor> +
Igor> + RETURN
Igor> + none
Igor> +
Igor> +*/
A small thing, but better point them out (to ensure we agree on the
coding style):
Remove the extra empty line after 'none'.
The current style is:
No empty lines at end of comments
One empty line between function comment and function.
Two empty lines before function comment (to separate it from previous function)
Igor> +
Igor> +static
Igor> +void s_get_key_cache_statistics(void *keycache_cb,
Igor> + uint partition_no __attribute__((unused)),
Igor> + KEY_CACHE_STATISTICS *key_cache_stats)
Igor> +{
Igor> + S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
Igor> + DBUG_ENTER("s_get_key_cache_statistics");
Igor> +
Igor> + key_cache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
Igor> + key_cache_stats->block_size= (longlong) keycache->key_cache_block_size;
Igor> + key_cache_stats->blocks_used= keycache->blocks_used;
Igor> + key_cache_stats->blocks_unused= keycache->blocks_unused;
Igor> + key_cache_stats->blocks_changed= keycache->global_blocks_changed;
Igor> + key_cache_stats->read_requests= keycache->global_cache_r_requests;
Igor> + key_cache_stats->reads= keycache->global_cache_read;
Igor> + key_cache_stats->write_requests= keycache->global_cache_w_requests;
Igor> + key_cache_stats->writes= keycache->global_cache_write;
Igor> + DBUG_VOID_RETURN;
Igor> +}
Please ensure that all keycache variables are of the same style.
Use either keycache or key_cache everywhere!
(See above for confusing example)
Igor> +
Igor> +
Igor> +static size_t s_key_cache_stat_var_offsets[]=
Igor> +{
Igor> + offsetof(S_KEY_CACHE_CB, blocks_used),
Igor> + offsetof(S_KEY_CACHE_CB, blocks_unused),
Igor> + offsetof(S_KEY_CACHE_CB, global_blocks_changed),
Igor> + offsetof(S_KEY_CACHE_CB, global_cache_w_requests),
Igor> + offsetof(S_KEY_CACHE_CB, global_cache_write),
Igor> + offsetof(S_KEY_CACHE_CB, global_cache_r_requests),
Igor> + offsetof(S_KEY_CACHE_CB, global_cache_read)
Igor> +};
Igor> +
Igor> +
Igor> +/*
Igor> + Get the value of a statistical variable for a simple key cache
Igor> +
Igor> + SYNOPSIS
Igor> + s_get_key_cache_stat_value()
Igor> + keycache_cb pointer to the control block of a simple key cache
Igor> + var_no the ordered number of a statistical variable
Igor> +
Igor> + DESCRIPTION
Igor> + This function is the implementation of the s_get_key_cache_stat_value
Igor> + interface function that is employed by simple (non-partitioned) key
Igor> caches.
Igor> + The function considers the parameter keycache_cb as a pointer to the
Igor> + control block structure of the type S_KEY_CACHE_CB for a simple key
Igor> cache.
Igor> + This function returns the value of the statistical variable var_no
Igor> + for this key cache. The variables are numbered starting from 0 to 6.
Igor> +
Igor> + RETURN
Igor> + The value of the specified statistical variable
Igor> +
Igor> +*/
Igor> +
Igor> +static
Igor> +ulonglong s_get_key_cache_stat_value(void *keycache_cb, uint var_no)
Igor> +{
Igor> + S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
Igor> + size_t var_ofs= s_key_cache_stat_var_offsets[var_no];
Igor> + ulonglong res= 0;
Igor> + DBUG_ENTER("s_get_key_cache_stat_value");
Igor> +
Igor> + if (var_no < 3)
Change the above to a define that is in the header file and add a
comment to where s_key_cache_stat_var_offsets are defined).
(Otherwise someone will surely break things sooner or later!)
Igor> + res= (ulonglong) (*(long *) ((char *) keycache + var_ofs));
Igor> + else
Igor> + res= *(ulonglong *) ((char *) keycache + var_ofs);
Igor> +
Igor> + DBUG_RETURN(res);
Igor> +}
Igor> +
Igor> +
Igor> +/*
Igor> + The array of pointer to the key cache interface functions used for simple
Igor> + key caches. Any simple key cache objects including those incorporated
Igor> into
Igor> + partitioned keys caches exploit this array.
Igor> +
Igor> + The current implementation of these functions allows to call them from
Igor> + the MySQL server code directly. We don't do it though.
Igor> +*/
Igor> +
Igor> +static KEY_CACHE_FUNCS s_key_cache_funcs =
Igor> +{
Igor> + s_init_key_cache,
Igor> + s_resize_key_cache,
Igor> + s_change_key_cache_param,
Igor> + s_key_cache_read,
Igor> + s_key_cache_insert,
Igor> + s_key_cache_write,
Igor> + s_flush_key_blocks,
Igor> + s_reset_key_cache_counters,
Igor> + s_end_key_cache,
Igor> + s_get_key_cache_statistics,
Igor> + s_get_key_cache_stat_value
Igor> +};
Here is where you can add casts so that you don't need them in the functions.
<cut>
Igor> +/* Control block for a partitioned key cache */
Igor> +
Igor> +typedef struct st_p_key_cache_cb
Igor> +{
Igor> + my_bool key_cache_inited; /*<=> control block is allocated
Igor> */
Igor> + S_KEY_CACHE_CB **partition_array; /* array of the key cache
Igor> partitions */
Igor> + uint partitions; /* number of partitions in the key
Igor> cache */
Igor> + size_t key_cache_mem_size; /* specified size of the cache memory
Igor> */
Igor> + uint key_cache_block_size; /* size of the page buffer of a cache
Igor> block */
Igor> +} P_KEY_CACHE_CB;
Please move the uint values after each other (gives better alignment)
Igor> +
Igor> +static
Igor> +void p_end_key_cache(void *keycache_cb, my_bool cleanup);
Move the above declaration to start of file (together with all other
static declarations)
<cut>
Igor> +
Igor> +static
Igor> +S_KEY_CACHE_CB *get_key_cache_partition_for_write(P_KEY_CACHE_CB
Igor> *keycache,
Igor> + File file, my_off_t
Igor> filepos,
Igor> + ulonglong*
Igor> dirty_part_map)
Put a new line after 'S_KEY_CACHE_CB *'; this makes the line more readable.
Igor> + If keycache->key_cache_inited != 0 then we assume that the memory for
Igor> + the array of partitions has been already allocated.
Igor> +
Igor> + It's assumed that no two threads call this function simultaneously
Igor> + referring to the same key cache handle.
Igor> +*/
I don't think we can assume that any memory is initialized to 0.
Better to have an argument that tells if the memory is already
initialized or not.
Igor> +
Igor> +static
Igor> +int p_init_key_cache(void *keycache_cb, uint key_cache_block_size,
Igor> + size_t use_mem, uint division_limit,
Igor> + uint age_threshold)
Igor> +{
Igor> + int i;
Igor> + size_t mem_per_cache;
Igor> + int cnt;
Igor> + S_KEY_CACHE_CB *partition;
Igor> + S_KEY_CACHE_CB **partition_ptr;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint partitions= keycache->partitions;
It would be better if partitions would be part of the init call, as
otherwise the caller need to initialize the keycache->partitions
before the call, which is more cumbersome.
Igor> + int blocks= -1;
Igor> + DBUG_ENTER("p_init_key_cache");
Igor> +
Igor> + keycache->key_cache_block_size = key_cache_block_size;
Igor> +
Igor> + if (keycache->key_cache_inited)
Remove above test; We can't make a decisions bases on a struct that we are
about to initialize.
Igor> + partition_ptr= keycache->partition_array;
Igor> + else
Igor> + {
Igor> + if(!(partition_ptr=
Igor> + (S_KEY_CACHE_CB **) my_malloc(sizeof(S_KEY_CACHE_CB *) * partitions,
Igor> + MYF(0))))
Igor> + DBUG_RETURN(blocks);
MYF(0) -> MYF(MY_WME) (So that we get a proper error message)
Please return -1 instead of blocks (easier to understand).
Igor> + keycache->partition_array= partition_ptr;
Igor> + }
Igor> +
Igor> + mem_per_cache = use_mem / partitions;
Igor> +
Igor> + for (i= 0; i < (int) partitions; i++)
Igor> + {
Igor> + my_bool key_cache_inited= keycache->key_cache_inited;
Igor> + if (key_cache_inited)
Igor> + partition= *partition_ptr;
Igor> + else
Igor> + {
Igor> + if (!(partition= (S_KEY_CACHE_CB *)
Igor> my_malloc(sizeof(S_KEY_CACHE_CB),
Igor> + MYF(0))))
Igor> + continue;
If we fail, shouldn't we abort ?
After all, we can't assume we will be able to allocate any other
partition after this one.
Here we should probably use MYF(MY_WME) too.
Igor> + partition->key_cache_inited= 0;
Igor> + }
Igor> +
Igor> + if ((cnt= s_init_key_cache(partition,
Igor> + key_cache_block_size, mem_per_cache,
Igor> + division_limit, age_threshold)) <= 0)
Igor> + {
Igor> + s_end_key_cache(partition, 1);
Igor> + my_free((uchar *) partition, MYF(0));
my_free() don't need a cast.
Igor> + partition= 0;
Igor> + if (key_cache_inited)
Igor> + {
Igor> + memmove(partition_ptr, partition_ptr+1,
Igor> + sizeof(partition_ptr)*(partitions-i-1));
Igor> + }
Igor> + if (i == 0)
Igor> + {
Igor> + i--;
Igor> + partitions--;
Igor> + if (partitions)
Igor> + mem_per_cache = use_mem / partitions;
Igor> + }
Igor> + continue;
Igor> + }
I don't like the above code to try to recalculate the memory size:
- You uncrease the size of the next partitions, but the total will
not be use_mem anyway, so it's a bit pointless.
- It will make the caches of different sizes, which is probably not
what the user wants anyway.
I think it would be better to be able to just fail if we can't
allocate all memory.
- Less confusing for the user
- If we get a memory error here, something is probably very wrong anyway so
it's better to release memory and abort.
- Simpler code
Igor> + if (blocks < 0)
Igor> + blocks= 0;
Whey the special logic with the first loop ?
Please add a commment or just set block to 0 instead of -1 and
set block to -1 on error / at abort
<cut>
Igor> +static
Igor> +int p_resize_key_cache(void *keycache_cb, uint key_cache_block_size,
Igor> + size_t use_mem, uint division_limit,
Igor> + uint age_threshold)
Igor> +{
Igor> + uint i;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint partitions= keycache->partitions;
Igor> + my_bool cleanup= use_mem == 0;
Igor> + int blocks= -1;
Igor> + int err= 0;
Igor> + DBUG_ENTER("p_resize_key_cache");
Igor> + if (use_mem == 0)
Change to test if (cleanup)
Igor> + {
Igor> + p_end_key_cache(keycache_cb, 0);
Igor> + DBUG_RETURN(blocks);
change to return -1
Igor> + }
Igor> + for (i= 0; i < partitions; i++)
Igor> + {
Igor> + err|= s_prepare_resize_key_cache(keycache->partition_array[i], 0, 1);
Igor> + }
Igor> + if (!err && use_mem)
You don't need to test use_mem here (you know it's not 0)
Igor> + blocks= p_init_key_cache(keycache_cb, key_cache_block_size, use_mem,
Igor> + division_limit, age_threshold);
Igor> + if (blocks > 0 && !cleanup)
Cleanup is always 0 here (as otherwise we return -1 at function start
functabove)
Igor> + {
Igor> + for (i= 0; i < partitions; i++)
Igor> + {
Igor> + s_finish_resize_key_cache(keycache->partition_array[i], 0, 1);
Igor> + }
Igor> + }
Igor> + DBUG_RETURN(blocks);
Igor> +}
<cut>
Igor> +static
Igor> +void p_end_key_cache(void *keycache_cb, my_bool cleanup)
Igor> +{
Igor> + uint i;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint partitions= keycache->partitions;
Igor> + DBUG_ENTER("p_end_key_cache");
Igor> + DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
Igor> +
Igor> + for (i= 0; i < partitions; i++)
Igor> + {
Igor> + s_end_key_cache(keycache->partition_array[i], cleanup);
Igor> + }
Igor> + if (cleanup) {
Move { to next line
Igor> + for (i= 0; i < partitions; i++)
Igor> + my_free((uchar*) keycache->partition_array[i], MYF(0));
Igor> + my_free((uchar*) keycache->partition_array, MYF(0));
Igor> + keycache->key_cache_inited= 0;
Igor> + }
Igor> + DBUG_VOID_RETURN;
Igor> +}
<cut>
Offset variable can be used (it's only set).
Igor> +static
Igor> +int p_key_cache_insert(void *keycache_cb,
Igor> + File file, my_off_t filepos, int level,
Igor> + uchar *buff, uint length)
Igor> +{
Igor> + uint w_length;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint offset= (uint) (filepos % keycache->key_cache_block_size);
Igor> + DBUG_ENTER("p_key_cache_insert");
Igor> + DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
Igor> + (uint) file,(ulong) filepos, length));
Igor> +
Igor> +
Igor> + /* Write data in key_cache_block_size increments */
Igor> + do
Igor> + {
Igor> + S_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
Igor> + file, filepos);
Igor> + w_length= length;
Igor> + set_if_smaller(w_length, keycache->key_cache_block_size);
Should be:
set_if_smaller(w_length, keycache->key_cache_block_size - offset);
Igor> + if (s_key_cache_insert((void *) partition,
Igor> + file, filepos, level,
Igor> + buff, w_length))
Igor> + DBUG_RETURN(1);
Igor> +
<cut>
Igor> +static
Igor> +int p_key_cache_write(void *keycache_cb,
Igor> + File file, void *file_extra,
Igor> + my_off_t filepos, int level,
Igor> + uchar *buff, uint length,
Igor> + uint block_length __attribute__((unused)),
Igor> + int dont_write)
Igor> +{
Igor> + uint w_length;
Igor> + ulonglong *part_map= (ulonglong *) file_extra;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint offset= (uint) (filepos % keycache->key_cache_block_size);
Igor> + DBUG_ENTER("p_key_cache_write");
Igor> + DBUG_PRINT("enter",
Igor> + ("fd: %u pos: %lu length: %u block_length: %u"
Igor> + " key_block_length: %u",
Igor> + (uint) file, (ulong) filepos, length, block_length,
Igor> + keycache ? keycache->key_cache_block_size : 0));
Igor> +
Igor> +
Igor> + /* Write data in key_cache_block_size increments */
Igor> + do
Igor> + {
Igor> + S_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
Igor> + file,
Igor> filepos,
Igor> + part_map);
Igor> + w_length = length;
Igor> + set_if_smaller(w_length, keycache->key_cache_block_size );
Should be:
set_if_smaller(w_length, keycache->key_cache_block_size - offset);
Igor> + if (s_key_cache_write(partition,
Igor> + file, 0, filepos, level,
Igor> + buff, w_length, block_length,
Igor> + dont_write))
Igor> + DBUG_RETURN(1);
<cut>
Igor> +static
Igor> +int p_flush_key_blocks(void *keycache_cb,
Igor> + File file, void *file_extra,
Igor> + enum flush_type type)
Igor> +{
Igor> + uint i;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint partitions= keycache->partitions;
Igor> + int err= 0;
Igor> + ulonglong *dirty_part_map= (ulonglong *) file_extra;
Igor> + DBUG_ENTER("p_flush_key_blocks");
Igor> + DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
Igor> +
Igor> + for (i= 0; i < partitions; i++)
Igor> + {
Igor> + S_KEY_CACHE_CB *partition= keycache->partition_array[i];
Igor> + if ((type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) &&
Igor> + !((*dirty_part_map) & (1<<i)))
Change 1<<i to ((ulonglong) 1 << i)
Igor> + continue;
Igor> + err+= test(s_flush_key_blocks(partition, file, 0, type));
You can change the + to |, and then remove the err > 0 below.
Igor> + }
Igor> + *dirty_part_map= 0;
Igor> +
Igor> + if (err > 0)
Igor> + err= 1;
Igor> +
Igor> + DBUG_RETURN(err);
Igor> +}
<cut>
Igor> +static
Igor> +void p_get_key_cache_statistics(void *keycache_cb, uint partition_no,
Igor> + KEY_CACHE_STATISTICS *key_cache_stats)
Igor> +{
Igor> + uint i;
Igor> + S_KEY_CACHE_CB *partition;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint partitions= keycache->partitions;
Igor> + DBUG_ENTER("p_get_key_cache_statistics_");
Igor> +
Igor> + if (partition_no != 0)
Igor> + {
Igor> + partition= keycache->partition_array[partition_no-1];
Igor> + s_get_key_cache_statistics((void *) partition, 0, key_cache_stats);
Igor> + DBUG_VOID_RETURN;
Igor> + }
Igor> + key_cache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
Igor> + key_cache_stats->block_size= (longlong) keycache->key_cache_block_size;
Igor> + for (i = 0; i < partitions; i++)
Igor> + {
Igor> + partition= keycache->partition_array[i];
Igor> + key_cache_stats->blocks_used+= partition->blocks_used;
Igor> + key_cache_stats->blocks_unused+= partition->blocks_unused;
Igor> + key_cache_stats->blocks_changed+= partition->global_blocks_changed;
Igor> + key_cache_stats->read_requests+= partition->global_cache_r_requests;
Igor> + key_cache_stats->reads+= partition->global_cache_read;
Igor> + key_cache_stats->write_requests+= partition->global_cache_w_requests;
Igor> + key_cache_stats->writes+= partition->global_cache_write;
Igor> + }
Shouldn't you start by reseting key_cache_stats ?
I think it's better to do the reset here than in
get_key_cache_statistics()
As you don't need the reset when you call s_get_key_cache_statistics()
(as this overwrites all stats entries)
Igor> + DBUG_VOID_RETURN;
Igor> +}
<cut>
Igor> +static
Igor> +ulonglong p_get_key_cache_stat_value(void *keycache_cb, uint var_no)
Igor> +{
Igor> + uint i;
Igor> + P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
Igor> + uint partitions= keycache->partitions;
Igor> + size_t var_ofs= s_key_cache_stat_var_offsets[var_no];
Igor> + ulonglong res= 0;
Igor> + DBUG_ENTER("p_get_key_cache_stat_value");
Igor> +
Igor> + if (var_no < 3)
Change to define (see earlier comment)
<cut>
Igor> +int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
Igor> + size_t use_mem, uint division_limit,
Igor> + uint age_threshold, uint partitions)
Igor> +{
Igor> + void *keycache_cb;
Igor> + int blocks;
Igor> + if (keycache->key_cache_inited)
Igor> + keycache_cb= keycache->keycache_cb;
See earlier comment about making this a parameter.
<cut>
Igor> +int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
Igor> + size_t use_mem, uint division_limit, uint age_threshold)
Igor> +{
Igor> + int blocks= -1;
Igor> + if (keycache->key_cache_inited)
Igor> + {
Igor> + if ((uint) keycache->param_partitions != keycache->partitions &&
Igor> use_mem)
Igor> + blocks= repartition_key_cache (keycache,
Igor> + key_cache_block_size, use_mem,
Igor> + division_limit, age_threshold,
Igor> + (uint) keycache->param_partitions);
Remove space after function name
Igor> + else
Igor> + {
Igor> + blocks= keycache->interface_funcs->resize(keycache->keycache_cb,
Igor> + key_cache_block_size,
Igor> + use_mem, division_limit,
Igor> + age_threshold);
Igor> +
Igor> + if (keycache->partitions)
Igor> + keycache->partitions=
Igor> + ((P_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
Igor> + }
Igor> + if (blocks <= 0)
Igor> + keycache->can_be_used= 0;
The last should probably be:
keycache->can_be_used= (blocks >= 0);
Safer, as it ensures that can_be_used is always correct.
Igor> +uchar *key_cache_read(KEY_CACHE *keycache,
Igor> + File file, my_off_t filepos, int level,
Igor> + uchar *buff, uint length,
Igor> + uint block_length, int return_buffer)
Igor> +{
Igor> + if (keycache->key_cache_inited && keycache->can_be_used)
Could we change this to only depend on keycache->can_be_used ?
(Faster if)
We can of course assume that keycache_init() has been called for the object.
Igor> + return keycache->interface_funcs->read(keycache->keycache_cb,
Igor> + file, filepos, level,
Igor> + buff, length,
Igor> + block_length, return_buffer);
Igor> +
Igor> + /* We can't use mutex here as the key cache may not be initialized */
Igor> + keycache->global_cache_r_requests++;
Igor> + keycache->global_cache_read++;
Igor> +
Igor> + if (my_pread(file, (uchar*) buff, length, filepos, MYF(MY_NABP)))
Igor> + return (uchar *) 0;
Igor> +
Igor> + return buff;
Igor> +}
<cut>
Igor> +int key_cache_insert(KEY_CACHE *keycache,
Igor> + File file, my_off_t filepos, int level,
Igor> + uchar *buff, uint length)
Igor> +{
Igor> + if (keycache->key_cache_inited && keycache->can_be_used)
Same here as above.
Igor> + return keycache->interface_funcs->insert(keycache->keycache_cb,
Igor> + file, filepos, level,
Igor> + buff, length);
Igor> + return 0;
Igor> +}
Igor> +
<cut>
Igor> +int key_cache_write(KEY_CACHE *keycache,
Igor> + File file, void *file_extra,
Igor> + my_off_t filepos, int level,
Igor> + uchar *buff, uint length,
Igor> + uint block_length, int force_write)
Igor> +{
Igor> + if (keycache->key_cache_inited && keycache->can_be_used)
And here.
Igor> +void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no,
Igor> + KEY_CACHE_STATISTICS *key_cache_stats)
Igor> +{
Igor> + bzero(key_cache_stats, sizeof(KEY_CACHE_STATISTICS));
Remove the above; Better to assume that get_stats() overwrites this.
(Which is the case for s_get_key_cache_statistics())
<cut>
Igor> === modified file 'sql/handler.cc'
Igor> --- a/sql/handler.cc 2010-02-01 06:14:12 +0000
Igor> +int ha_repartition_key_cache(KEY_CACHE *key_cache)
Igor> +{
Igor> + DBUG_ENTER("ha_repartition_key_cache");
Igor> +
Igor> + if (key_cache->key_cache_inited)
Igor> + {
Igor> + pthread_mutex_lock(&LOCK_global_system_variables);
Igor> + size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
Igor> + long tmp_block_size= (long) key_cache->param_block_size;
Igor> + uint division_limit= key_cache->param_division_limit;
Igor> + uint age_threshold= key_cache->param_age_threshold;
Igor> + uint partitions= key_cache->param_partitions;
Igor> + pthread_mutex_unlock(&LOCK_global_system_variables);
Igor> + DBUG_RETURN(!repartition_key_cache(key_cache, tmp_block_size,
Igor> + tmp_buff_size,
Igor> + division_limit, age_threshold,
Igor> + partitions));
Igor> + }
key_cache_inited may be 0 if we used a 0 size key cache.
In this case one can't reparttion this cache. Is this correct?
Assume on does the following:
- Set key cache size to 0
- changes partition numbers
- set key cache to 1G
In this case, will things work and the new key cache have the new
number of partitions ?
(It may work, just wanted to be sure that you have tested this)
<cut>
Igor> === modified file 'sql/sql_show.cc'
Igor> --- a/sql/sql_show.cc 2010-02-01 06:14:12 +0000
Igor> +++ b/sql/sql_show.cc 2010-02-16 16:41:11 +0000
Igor> @@ -2220,6 +2220,31 @@ void remove_status_vars(SHOW_VAR *list)
Igor> }
Igor> +
Igor> +static void update_key_cache_stat_var(KEY_CACHE *key_cache, size_t ofs)
Igor> +{
Igor> + uint var_no;
Igor> + switch (ofs) {
Igor> + case offsetof(KEY_CACHE, blocks_used):
Igor> + case offsetof(KEY_CACHE, blocks_unused):
Igor> + case offsetof(KEY_CACHE, global_blocks_changed):
Igor> + var_no= (ofs-offsetof(KEY_CACHE, blocks_used))/sizeof(ulong);
Igor> + *(ulong *)((char *) key_cache + ofs)=
Igor> + (ulong) get_key_cache_stat_value(key_cache, var_no);
Igor> + break;
Igor> + case offsetof(KEY_CACHE, global_cache_r_requests):
Igor> + case offsetof(KEY_CACHE, global_cache_read):
Igor> + case offsetof(KEY_CACHE, global_cache_w_requests):
Igor> + case offsetof(KEY_CACHE, global_cache_write):
Igor> + var_no= 3+(ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
Igor> + sizeof(ulonglong);
Change 3 to constant.
Igor> + *(ulonglong *)((char *) key_cache + ofs)=
Igor> + get_key_cache_stat_value(key_cache, var_no);
Igor> + break;
Igor> + }
Igor> +}
<cut>
Igor> +static
Igor> +int store_key_cache_table_record(THD *thd, TABLE *table,
Igor> + const char *name, uint name_length,
Igor> + KEY_CACHE *key_cache,
Igor> + uint partitions, uint partition_no)
Igor> +{
Igor> + KEY_CACHE_STATISTICS key_cache_stats;
Igor> + uint err;
Igor> + DBUG_ENTER("store_key_cache_table_record");
Igor> +
Igor> + get_key_cache_statistics(key_cache, partition_no, &key_cache_stats);
Igor> +
Igor> + if (key_cache_stats.mem_size == 0)
Igor> + DBUG_RETURN(0);
Shouldn't we also here test for keycache->key_cache_inited ?
Regards,
Monty
3
2

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2748)
by Igor Babaev 03 Apr '10
by Igor Babaev 03 Apr '10
03 Apr '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100401214240-7ee610nf0169tqy8
2748 Igor Babaev 2010-04-03 [merge]
Merge with the latest changes of 5.2
added:
mysql-test/suite/pbxt/r/pbxt_xa.result
mysql-test/suite/pbxt/t/pbxt_xa.test
mysql-test/suite/pbxt/t/suite.opt
modified:
BUILD/compile-solaris-sparc
CMakeLists.txt
cmd-line-utils/libedit/filecomplete.c
config/ac-macros/plugins.m4
configure.in
extra/comp_err.c
extra/libevent/evbuffer.c
extra/libevent/event.c
extra/libevent/kqueue.c
extra/libevent/signal.c
include/m_ctype.h
include/my_global.h
include/mysql/plugin.h
include/mysql/plugin_auth.h.pp
include/sql_common.h
libmysqld/CMakeLists.txt
mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test
mysql-test/include/default_mysqld.cnf
mysql-test/lib/My/SafeProcess/safe_process.cc
mysql-test/lib/mtr_cases.pm
mysql-test/lib/v1/mysql-test-run.pl
mysql-test/r/status_user.result
mysql-test/suite/funcs_1/r/is_columns_is.result
mysql-test/suite/parts/t/rpl_partition.test
mysql-test/suite/rpl/r/rpl_do_grant.result
mysql-test/suite/rpl/r/rpl_optimize.result
mysql-test/suite/rpl/t/rpl_do_grant.test
mysql-test/suite/rpl/t/rpl_name_const.test
mysql-test/suite/rpl/t/rpl_optimize.test
mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
mysql-test/suite/rpl/t/rpl_row_trig003.test
mysql-test/t/bug47671-master.opt
mysql-test/t/ctype_latin1_de-master.opt
mysql-test/t/ctype_ucs2_def-master.opt
mysys/mf_keycache.c
mysys/my_gethostbyname.c
plugin/auth/auth_socket.c
plugin/auth/dialog.c
plugin/daemon_example/daemon_example.cc
plugin/fulltext/plugin_example.c
server-tools/CMakeLists.txt
server-tools/instance-manager/CMakeLists.txt
sql-common/client.c
sql/client_settings.h
sql/ha_ndbcluster.cc
sql/ha_partition.cc
sql/handler.cc
sql/item.cc
sql/item.h
sql/item_cmpfunc.cc
sql/item_create.cc
sql/item_create.h
sql/item_sum.cc
sql/item_sum.h
sql/log.cc
sql/log_event.cc
sql/mysqld.cc
sql/net_serv.cc
sql/set_var.cc
sql/sp_head.cc
sql/sql_acl.cc
sql/sql_builtin.cc.in
sql/sql_class.cc
sql/sql_class.h
sql/sql_plugin.cc
sql/sql_plugin.h
sql/sql_show.cc
sql/sql_table.cc
sql/sql_view.cc
sql/sql_yacc.yy
storage/archive/ha_archive.cc
storage/blackhole/ha_blackhole.cc
storage/csv/ha_tina.cc
storage/example/ha_example.cc
storage/example/ha_example.h
storage/federated/ha_federated.cc
storage/federatedx/ha_federatedx.cc
storage/heap/ha_heap.cc
storage/ibmdb2i/ha_ibmdb2i.cc
storage/innobase/handler/ha_innodb.cc
storage/innodb_plugin/handler/i_s.cc
storage/maria/ha_maria.cc
storage/maria/ma_loghandler.c
storage/maria/ma_search.c
storage/maria/maria_def.h
storage/myisam/ft_stopwords.c
storage/myisam/ha_myisam.cc
storage/myisammrg/ha_myisammrg.cc
storage/myisammrg/myrg_open.c
storage/pbxt/src/ha_pbxt.cc
storage/xtradb/handler/ha_innodb.cc
storage/xtradb/handler/i_s.cc
storage/xtradb/handler/i_s.h
storage/xtradb/include/page0page.h
storage/xtradb/include/page0page.ic
storage/xtradb/include/ut0lst.h
storage/xtradb/log/log0recv.c
strings/ctype-ucs2.c
strings/ctype-utf8.c
strings/my_vsnprintf.c
support-files/compiler_warnings.supp
unittest/mysys/waiting_threads-t.c
=== modified file 'BUILD/compile-solaris-sparc'
--- a/BUILD/compile-solaris-sparc 2008-09-30 20:57:48 +0000
+++ b/BUILD/compile-solaris-sparc 2010-03-31 19:12:21 +0000
@@ -9,6 +9,6 @@ PATH=$PATH:/usr/ccs/bin:/usr/local/bin
path=`dirname $0`
. "$path/autorun.sh"
-CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" LIBS="-lmtmalloc" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa $EXTRA_FLAGS $EXTRA_CFLAGS" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g $EXTRA_FLAGS $EXTRA_CXXFLAGS" LIBS="-lmtmalloc" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
make -j 4
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt 2010-03-15 11:51:23 +0000
+++ b/CMakeLists.txt 2010-04-02 09:20:09 +0000
@@ -38,6 +38,7 @@ ADD_DEFINITIONS(-DMYSQL_DATADIR="c:/Prog
ADD_DEFINITIONS(-DDEFAULT_CHARSET_HOME="c:/Program Files/MySQL/MySQL Server ${MYSQL_BASE_VERSION}/")
ADD_DEFINITIONS(-DPACKAGE=mysql)
ADD_DEFINITIONS(-DSHAREDIR="share")
+ADD_DEFINITIONS(-DPLUGINDIR="lib/plugin")
# Set debug options
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS")
@@ -260,7 +261,7 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${PLUGIN_NAME}_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin")
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
@@ -279,7 +280,7 @@ ENDFOREACH(SUBDIR ${STORAGE_SUBDIRS})
# Special handling for partition(not really pluggable)
IF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_PARTITION_STORAGE_ENGINE")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_partition_plugin")
ENDIF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
# Special handling for tmp tables with the maria engine
=== modified file 'cmd-line-utils/libedit/filecomplete.c'
--- a/cmd-line-utils/libedit/filecomplete.c 2009-04-30 11:53:30 +0000
+++ b/cmd-line-utils/libedit/filecomplete.c 2010-03-31 19:12:21 +0000
@@ -95,10 +95,9 @@ static char break_chars[] = { ' ', '\t',
char *
fn_tilde_expand(const char *txt)
{
- struct passwd pwres, *pass;
+ struct passwd *pass;
char *temp;
size_t len = 0;
- char pwbuf[1024];
if (txt[0] != '~')
return (strdup(txt));
=== modified file 'config/ac-macros/plugins.m4'
--- a/config/ac-macros/plugins.m4 2010-03-29 15:14:28 +0000
+++ b/config/ac-macros/plugins.m4 2010-04-01 14:34:51 +0000
@@ -460,7 +460,7 @@ dnl Although this is "pretty", it breaks
])
])
])
- mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ maria_plugin_defs="$maria_plugin_defs, [builtin_maria_]$2[_plugin]"
[with_plugin_]$2=yes
AC_MSG_RESULT([yes])
m4_ifdef([$11], [
=== modified file 'configure.in'
--- a/configure.in 2010-03-29 15:13:53 +0000
+++ b/configure.in 2010-04-01 14:34:51 +0000
@@ -2872,7 +2872,7 @@ AC_SUBST(server_scripts)
AC_SUBST(mysql_plugin_dirs)
AC_SUBST(mysql_plugin_libs)
-AC_SUBST(mysql_plugin_defs)
+AC_SUBST(maria_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
=== modified file 'extra/comp_err.c'
--- a/extra/comp_err.c 2009-11-20 10:11:31 +0000
+++ b/extra/comp_err.c 2010-03-30 12:36:49 +0000
@@ -660,7 +660,7 @@ static ha_checksum checksum_format_speci
case 'u':
case 'x':
case 's':
- chksum= my_checksum(chksum, start, (uint) (p + 1 - start));
+ chksum= my_checksum(chksum, (uchar*) start, (uint) (p + 1 - start));
start= 0; /* Not in format specifier anymore */
break;
=== modified file 'extra/libevent/evbuffer.c'
--- a/extra/libevent/evbuffer.c 2010-02-01 06:14:12 +0000
+++ b/extra/libevent/evbuffer.c 2010-04-02 09:20:09 +0000
@@ -75,8 +75,7 @@ bufferevent_add(struct event *ev, int ti
*/
void
-bufferevent_read_pressure_cb(struct evbuffer *buf,
- size_t old __attribute__((unused)), size_t now,
+bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
void *arg) {
struct bufferevent *bufev = arg;
/*
=== modified file 'extra/libevent/event.c'
--- a/extra/libevent/event.c 2010-01-06 19:20:16 +0000
+++ b/extra/libevent/event.c 2010-04-02 09:20:09 +0000
@@ -394,8 +394,7 @@ event_base_get_method(struct event_base
}
static void
-event_loopexit_cb(int fd __attribute__((unused)),
- short what __attribute__((unused)), void *arg)
+event_loopexit_cb(int fd, short what, void *arg)
{
struct event_base *base = arg;
base->event_gotterm = 1;
=== modified file 'extra/libevent/kqueue.c'
--- a/extra/libevent/kqueue.c 2009-03-12 22:27:35 +0000
+++ b/extra/libevent/kqueue.c 2010-03-30 12:36:49 +0000
@@ -144,7 +144,7 @@ kq_init(struct event_base *base)
*/
if (kevent(kq,
kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
- kqueueop->events[0].ident != -1 ||
+ ((int) kqueueop->events[0].ident) != -1 ||
kqueueop->events[0].flags != EV_ERROR) {
event_warn("%s: detected broken kqueue; not using.", __func__);
free(kqueueop->changes);
=== modified file 'extra/libevent/signal.c'
--- a/extra/libevent/signal.c 2010-01-06 19:20:16 +0000
+++ b/extra/libevent/signal.c 2010-04-02 09:20:09 +0000
@@ -69,7 +69,7 @@ static void evsignal_handler(int sig);
/* Callback for when the signal handler write a byte to our signaling socket */
static void
-evsignal_cb(int fd, short what __attribute((unused)), void *arg __attribute((unused)))
+evsignal_cb(int fd, short what, void *arg)
{
static char signals[100];
#ifdef WIN32
=== modified file 'include/m_ctype.h'
--- a/include/m_ctype.h 2010-03-31 18:37:45 +0000
+++ b/include/m_ctype.h 2010-04-02 09:20:09 +0000
@@ -311,7 +311,9 @@ struct charset_info_st
#define ILLEGAL_CHARSET_INFO_NUMBER (~0U)
extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_bin;
-extern struct charset_info_st my_charset_bin;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_latin1;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_filename;
+
extern struct charset_info_st my_charset_big5_chinese_ci;
extern struct charset_info_st my_charset_big5_bin;
extern struct charset_info_st my_charset_cp932_japanese_ci;
@@ -324,7 +326,6 @@ extern struct charset_info_st my_charset
extern struct charset_info_st my_charset_gb2312_bin;
extern struct charset_info_st my_charset_gbk_chinese_ci;
extern struct charset_info_st my_charset_gbk_bin;
-extern struct charset_info_st my_charset_latin1;
extern struct charset_info_st my_charset_latin1_german2_ci;
extern struct charset_info_st my_charset_latin1_bin;
extern struct charset_info_st my_charset_latin2_czech_ci;
@@ -341,7 +342,6 @@ extern struct charset_info_st my_charset
extern struct charset_info_st my_charset_utf8_unicode_ci;
extern struct charset_info_st my_charset_utf8_bin;
extern struct charset_info_st my_charset_cp1250_czech_ci;
-extern struct charset_info_st my_charset_filename;
/* declarations for simple charsets */
extern size_t my_strnxfrm_simple(CHARSET_INFO *, uchar *, size_t,
=== modified file 'include/my_global.h'
--- a/include/my_global.h 2010-03-29 15:13:53 +0000
+++ b/include/my_global.h 2010-04-02 09:20:09 +0000
@@ -1522,6 +1522,9 @@ do { doubleget_union _tmp; \
#elif defined(HAVE_DLFCN_H)
#include <dlfcn.h>
#endif
+#ifndef HAVE_DLERROR
+#define dlerror() ""
+#endif
#endif
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
@@ -1529,7 +1532,7 @@ do { doubleget_union _tmp; \
#define RTLD_NOW 1
#endif
-#ifndef HAVE_DLERROR
+#ifndef HAVE_DLOPEN
#define dlerror() "No support for dynamic loading (static build?)"
#define dlopen(A,B) 0
#define dlsym(A,B) 0
=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin.h 2010-04-01 14:34:51 +0000
@@ -57,7 +57,10 @@ typedef struct st_mysql_xid MYSQL_XID;
Plugin API. Common for all plugin types.
*/
+/* MySQL plugin interface version */
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
+/* MariaDB plugin interface version */
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x0100
/*
The allowable types of plugins
@@ -81,6 +84,14 @@ typedef struct st_mysql_xid MYSQL_XID;
#define PLUGIN_LICENSE_GPL_STRING "GPL"
#define PLUGIN_LICENSE_BSD_STRING "BSD"
+/* definitions of code maturity for plugins */
+#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0
+#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1
+#define MariaDB_PLUGIN_MATURITY_ALPHA 2
+#define MariaDB_PLUGIN_MATURITY_BETA 3
+#define MariaDB_PLUGIN_MATURITY_GAMMA 4
+#define MariaDB_PLUGIN_MATURITY_STABLE 5
+
/*
Macros for beginning and ending plugin declarations. Between
mysql_declare_plugin and mysql_declare_plugin_end there should
@@ -93,11 +104,24 @@ typedef struct st_mysql_xid MYSQL_XID;
int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
int PSIZE= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin DECLS[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_maria_plugin); \
+struct st_maria_plugin DECLS[]= {
+
#else
+
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \
+MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \
+MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]= {
+
#endif
#define mysql_declare_plugin(NAME) \
@@ -106,7 +130,14 @@ __MYSQL_DECLARE_PLUGIN(NAME, \
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
builtin_ ## NAME ## _plugin)
+#define maria_declare_plugin(NAME) \
+MARIA_DECLARE_PLUGIN__(NAME, \
+ builtin_maria_ ## NAME ## _plugin_interface_version, \
+ builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_maria_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}
+#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}}
/*
declarations for SHOW STATUS support in plugins
@@ -403,6 +434,30 @@ struct st_mysql_plugin
void * __reserved1; /* reserved for dependency checking */
};
+/*
+ MariaDB extension for plugins declaration structure.
+
+ It also copy current MySQL plugin fields to have more independency
+ in plugins extension
+*/
+
+struct st_maria_plugin
+{
+ int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ void *info; /* pointer to type-specific plugin descriptor */
+ const char *name; /* plugin name */
+ const char *author; /* plugin author (for SHOW PLUGINS) */
+ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
+ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
+ int (*init)(void *); /* the function to invoke when plugin is loaded */
+ int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
+ unsigned int version; /* plugin version (for SHOW PLUGINS) */
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info; /* plugin version string */
+ int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */
+};
+
/*************************************************************************
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
*/
=== modified file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin_auth.h.pp 2010-04-01 14:34:51 +0000
@@ -77,6 +77,22 @@ struct st_mysql_plugin
struct st_mysql_sys_var **system_vars;
void * __reserved1;
};
+struct st_maria_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info;
+ int maturity;
+};
enum enum_ftparser_mode
{
MYSQL_FTPARSER_SIMPLE_MODE= 0,
=== modified file 'include/sql_common.h'
--- a/include/sql_common.h 2010-03-29 15:13:53 +0000
+++ b/include/sql_common.h 2010-04-01 09:04:26 +0000
@@ -96,7 +96,7 @@ void set_mysql_extended_error(MYSQL *mys
struct st_plugin_vio_info;
void mpvio_info(Vio *vio, struct st_plugin_vio_info *info);
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
- char *data_plugin, const char *db);
+ const char *data_plugin, const char *db);
int mysql_client_plugin_init();
void mysql_client_plugin_deinit();
struct st_mysql_client_plugin;
=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt 2010-01-31 09:13:21 +0000
+++ b/libmysqld/CMakeLists.txt 2010-04-02 18:51:02 +0000
@@ -104,7 +104,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libm
../sql-common/client.c ../sql-common/my_time.c
../sql-common/my_user.c ../sql-common/pack.c
../sql/password.c ../sql/discover.cc ../sql/derror.cc
- ../sql/field.cc ../sql/field_conv.cc
+ ../sql/field.cc ../sql/field_conv.cc ../sql-common/client_plugin.c
../sql/filesort.cc ../sql/gstream.cc ../sql/ha_partition.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
=== modified file 'mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test'
--- a/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test 2010-01-22 09:38:21 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test 2010-03-28 18:10:00 +0000
@@ -157,3 +157,4 @@ INSERT INTO t1 VALUES (1);
DROP TEMPORARY TABLE t1;
+--sync_slave_with_master
=== modified file 'mysql-test/include/default_mysqld.cnf'
--- a/mysql-test/include/default_mysqld.cnf 2008-04-08 14:51:26 +0000
+++ b/mysql-test/include/default_mysqld.cnf 2010-03-28 18:10:00 +0000
@@ -2,7 +2,7 @@
[mysqld]
open-files-limit= 1024
local-infile
-default-character-set= latin1
+character-set-server= latin1
# Increase default connect_timeout to avoid intermittent
# disconnects when test servers are put under load see BUG#28359
=== modified file 'mysql-test/lib/My/SafeProcess/safe_process.cc'
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc 2009-07-08 12:31:22 +0000
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-03-28 18:10:00 +0000
@@ -159,7 +159,7 @@ int main(int argc, char* const argv[] )
signal(SIGCHLD, handle_signal);
signal(SIGABRT, handle_abort);
- sprintf(safe_process_name, "safe_process[%d]", own_pid);
+ sprintf(safe_process_name, "safe_process[%d]", (int) own_pid);
message("Started");
=== modified file 'mysql-test/lib/mtr_cases.pm'
--- a/mysql-test/lib/mtr_cases.pm 2010-01-15 15:27:55 +0000
+++ b/mysql-test/lib/mtr_cases.pm 2010-03-30 12:36:49 +0000
@@ -681,6 +681,8 @@ sub optimize_cases {
if ( $default_engine =~ /^ndb/i );
$tinfo->{'innodb_test'}= 1
if ( $default_engine =~ /^innodb/i );
+ $tinfo->{'pbxt_test'}= 1
+ if ( $default_engine =~ /^pbxt/i );
}
}
@@ -778,6 +780,8 @@ sub collect_one_test_case {
my $disabled= shift;
my $suite_opts= shift;
+ my $local_default_storage_engine= $default_storage_engine;
+
#print "collect_one_test_case\n";
#print " suitedir: $suitedir\n";
#print " testdir: $testdir\n";
@@ -932,15 +936,26 @@ sub collect_one_test_case {
tags_from_test_file($tinfo,"$testdir/${tname}.test");
- if ( defined $default_storage_engine )
+ # Get default storage engine from suite.opt file
+
+ if (defined $suite_opts &&
+ "@$suite_opts" =~ "default-storage-engine=\s*([^\s]*)")
+ {
+ $local_default_storage_engine= $1;
+ }
+
+ if ( defined $local_default_storage_engine )
{
# Different default engine is used
# tag test to require that engine
$tinfo->{'ndb_test'}= 1
- if ( $default_storage_engine =~ /^ndb/i );
+ if ( $local_default_storage_engine =~ /^ndb/i );
$tinfo->{'innodb_test'}= 1
- if ( $default_storage_engine =~ /^innodb/i );
+ if ( $local_default_storage_engine =~ /^innodb/i );
+
+ $tinfo->{'pbxt_test'}= 1
+ if ( $local_default_storage_engine =~ /^pbxt/i );
}
@@ -1103,6 +1118,28 @@ sub collect_one_test_case {
$tinfo->{template_path}= $config;
}
+ if ( $tinfo->{'pbxt_test'} )
+ {
+ # This is a test that needs pbxt
+ if ( $::mysqld_variables{'pbxt'} eq "OFF" ||
+ ! exists $::mysqld_variables{'pbxt'} )
+ {
+ # Engine is not supported, skip it
+ $tinfo->{'skip'}= 1;
+ return $tinfo;
+ }
+ }
+ else
+ {
+ # Only disable engine if it's on by default (to avoid warnings about
+ # not existing loose options
+ if ( $::mysqld_variables{'pbxt'} eq "ON")
+ {
+ push(@{$tinfo->{'master_opt'}}, "--loose-skip-pbxt");
+ push(@{$tinfo->{'slave_opt'}}, "--loose-skip-pbxt");
+ }
+ }
+
if ( $tinfo->{'example_plugin_test'} )
{
if ( !$ENV{'EXAMPLE_PLUGIN'} )
@@ -1156,6 +1193,7 @@ my @tags=
["include/have_log_bin.inc", "need_binlog", 1],
["include/have_innodb.inc", "innodb_test", 1],
+ ["include/have_pbxt.inc", "pbxt_test", 1],
["include/big_test.inc", "big_test", 1],
["include/have_debug.inc", "need_debug", 1],
["include/have_ndb.inc", "ndb_test", 1],
=== modified file 'mysql-test/lib/v1/mysql-test-run.pl'
--- a/mysql-test/lib/v1/mysql-test-run.pl 2010-03-04 08:03:07 +0000
+++ b/mysql-test/lib/v1/mysql-test-run.pl 2010-03-28 18:10:00 +0000
@@ -3965,7 +3965,7 @@ sub mysqld_arguments ($$$$) {
}
}
- mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
+ mtr_add_arg($args, "%s--character-set-server-set=latin1", $prefix);
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
=== modified file 'mysql-test/r/status_user.result'
--- a/mysql-test/r/status_user.result 2010-03-21 20:58:19 +0000
+++ b/mysql-test/r/status_user.result 2010-04-02 18:51:02 +0000
@@ -137,7 +137,7 @@ ROWS_INSERTED 8
ROWS_UPDATED 5
SELECT_COMMANDS 3
UPDATE_COMMANDS 11
-OTHER_COMMANDS 9
+OTHER_COMMANDS 7
COMMIT_TRANSACTIONS 19
ROLLBACK_TRANSACTIONS 2
DENIED_CONNECTIONS 0
@@ -154,7 +154,7 @@ ROWS_INSERTED 8
ROWS_UPDATED 5
SELECT_COMMANDS 3
UPDATE_COMMANDS 11
-OTHER_COMMANDS 9
+OTHER_COMMANDS 7
COMMIT_TRANSACTIONS 19
ROLLBACK_TRANSACTIONS 2
DENIED_CONNECTIONS 0
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_is.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-04-02 10:03:39 +0000
@@ -271,10 +271,12 @@ NULL information_schema PBXT_STATISTICS
NULL information_schema PBXT_STATISTICS Name 2 NO varchar 40 120 NULL NULL utf8 utf8_general_ci varchar(40) select
NULL information_schema PBXT_STATISTICS Value 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(8) select
NULL information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
+NULL information_schema PLUGINS PLUGIN_AUTH_VERSION 12 NULL YES varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
NULL information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
NULL information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL utf8 utf8_general_ci varchar(20) select
NULL information_schema PLUGINS PLUGIN_LICENSE 10 NULL YES varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
+NULL information_schema PLUGINS PLUGIN_MATURITY 11 NULL YES varchar 12 36 NULL NULL utf8 utf8_general_ci varchar(12) select
NULL information_schema PLUGINS PLUGIN_NAME 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema PLUGINS PLUGIN_STATUS 3 NO varchar 10 30 NULL NULL utf8 utf8_general_ci varchar(10) select
NULL information_schema PLUGINS PLUGIN_TYPE 4 NO varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
@@ -791,6 +793,8 @@ NULL information_schema PBXT_STATISTICS
3.0000 information_schema PLUGINS PLUGIN_AUTHOR varchar 64 192 utf8 utf8_general_ci varchar(64)
1.0000 information_schema PLUGINS PLUGIN_DESCRIPTION longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
3.0000 information_schema PLUGINS PLUGIN_LICENSE varchar 80 240 utf8 utf8_general_ci varchar(80)
+3.0000 information_schema PLUGINS PLUGIN_MATURITY varchar 12 36 utf8 utf8_general_ci varchar(12)
+3.0000 information_schema PLUGINS PLUGIN_AUTH_VERSION varchar 80 240 utf8 utf8_general_ci varchar(80)
NULL information_schema PROCESSLIST ID bigint NULL NULL NULL NULL bigint(4)
3.0000 information_schema PROCESSLIST USER varchar 16 48 utf8 utf8_general_ci varchar(16)
3.0000 information_schema PROCESSLIST HOST varchar 64 192 utf8 utf8_general_ci varchar(64)
=== modified file 'mysql-test/suite/parts/t/rpl_partition.test'
--- a/mysql-test/suite/parts/t/rpl_partition.test 2009-02-01 12:00:48 +0000
+++ b/mysql-test/suite/parts/t/rpl_partition.test 2010-03-29 19:07:45 +0000
@@ -1,6 +1,7 @@
--source include/have_partition.inc
--source include/have_innodb.inc
--source include/master-slave.inc
+--source include/big_test.inc
--vertical_results
=== added file 'mysql-test/suite/pbxt/r/pbxt_xa.result'
--- a/mysql-test/suite/pbxt/r/pbxt_xa.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/r/pbxt_xa.result 2010-03-24 22:12:39 +0000
@@ -0,0 +1,18 @@
+drop table if exists t1, t2;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
+CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=pbxt;
+BEGIN;
+SELECT @@log_bin;
+@@log_bin
+0
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+COMMIT;
+select * from t1;
+a
+1
+select * from t2;
+b
+2
+drop table t1, t2;
+drop database pbxt;
=== added file 'mysql-test/suite/pbxt/t/pbxt_xa.test'
--- a/mysql-test/suite/pbxt/t/pbxt_xa.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/pbxt_xa.test 2010-03-24 22:12:39 +0000
@@ -0,0 +1,23 @@
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+#
+# bug lp:544173, xa crash with two 2pc-capable storage engines without binlog
+#
+
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
+CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=pbxt;
+BEGIN;
+# verify that binlog is off
+SELECT @@log_bin;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+COMMIT;
+select * from t1;
+select * from t2;
+drop table t1, t2;
+drop database pbxt;
+
=== added file 'mysql-test/suite/pbxt/t/suite.opt'
--- a/mysql-test/suite/pbxt/t/suite.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/suite.opt 2010-03-30 12:36:49 +0000
@@ -0,0 +1 @@
+--default-storage-engine=pbxt
=== modified file 'mysql-test/suite/rpl/r/rpl_do_grant.result'
--- a/mysql-test/suite/rpl/r/rpl_do_grant.result 2010-03-16 12:38:35 +0000
+++ b/mysql-test/suite/rpl/r/rpl_do_grant.result 2010-04-01 09:04:26 +0000
@@ -165,10 +165,9 @@ USE test;
DROP FUNCTION bug42217_db.upgrade_del_func;
DROP FUNCTION bug42217_db.upgrade_alter_func;
DROP DATABASE bug42217_db;
-DROP USER 'create_rout_db'@'localhost';
-call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
-USE mtr;
call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
+stop slave;
+DROP USER 'create_rout_db'@'localhost';
######## BUG#49119 #######
### i) test case from the 'how to repeat section'
stop slave;
=== modified file 'mysql-test/suite/rpl/r/rpl_optimize.result'
--- a/mysql-test/suite/rpl/r/rpl_optimize.result 2010-01-13 09:00:03 +0000
+++ b/mysql-test/suite/rpl/r/rpl_optimize.result 2010-03-31 19:12:21 +0000
@@ -4,6 +4,7 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+drop tables if exists t1;
CALL mtr.add_suppression('Statement may not be safe to log in statement format.');
create table t1 (a int not null auto_increment primary key, b int, key(b));
INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
=== modified file 'mysql-test/suite/rpl/t/rpl_do_grant.test'
--- a/mysql-test/suite/rpl/t/rpl_do_grant.test 2010-03-16 12:38:35 +0000
+++ b/mysql-test/suite/rpl/t/rpl_do_grant.test 2010-04-01 09:04:26 +0000
@@ -209,12 +209,18 @@ USE test;
DROP FUNCTION bug42217_db.upgrade_del_func;
DROP FUNCTION bug42217_db.upgrade_alter_func;
DROP DATABASE bug42217_db;
-DROP USER 'create_rout_db'@'localhost';
call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
+
+sync_slave_with_master;
+
+# Drop the user that was already dropped on the slave
connection slave;
-USE mtr;
-call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
+--disable_warnings
+stop slave;
+connection master;
+DROP USER 'create_rout_db'@'localhost';
+--enable_warnings
# BUG#49119: Master crashes when executing 'REVOKE ... ON
# {PROCEDURE|FUNCTION} FROM ...'
=== modified file 'mysql-test/suite/rpl/t/rpl_name_const.test'
--- a/mysql-test/suite/rpl/t/rpl_name_const.test 2009-04-08 23:42:51 +0000
+++ b/mysql-test/suite/rpl/t/rpl_name_const.test 2010-03-28 18:10:00 +0000
@@ -45,3 +45,4 @@ select * from t1 order by id;
connection master;
drop table t1;
drop procedure test_procedure;
+--sync_slave_with_master
=== modified file 'mysql-test/suite/rpl/t/rpl_optimize.test'
--- a/mysql-test/suite/rpl/t/rpl_optimize.test 2010-03-04 08:03:07 +0000
+++ b/mysql-test/suite/rpl/t/rpl_optimize.test 2010-03-31 19:12:21 +0000
@@ -15,6 +15,10 @@
-- source include/not_staging.inc
-- source include/master-slave.inc
+--disable_warnings
+drop tables if exists t1;
+--enable_warnings
+
CALL mtr.add_suppression('Statement may not be safe to log in statement format.');
create table t1 (a int not null auto_increment primary key, b int, key(b));
@@ -51,10 +55,9 @@ sync_with_master; # won't work if slave
connection master; # cleanup
drop table t1;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
# If the machine is so fast that slave syncs before OPTIMIZE
-# starts, this test wil demonstrate nothing but will pass.
+# starts, this test will demonstrate nothing but will pass.
# End of 4.1 tests
=== modified file 'mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test'
--- a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test 2007-12-12 10:14:59 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test 2010-03-28 18:10:00 +0000
@@ -53,6 +53,7 @@ UPDATE t1 SET a=99 WHERE a = 0;
SHOW BINLOG EVENTS;
DROP TABLE t1;
+--sync_slave_with_master
# BUG#17620: Replicate (Row Based) Fails when Query Cache enabled on
# slave
=== modified file 'mysql-test/suite/rpl/t/rpl_row_trig003.test'
--- a/mysql-test/suite/rpl/t/rpl_row_trig003.test 2007-12-06 15:27:10 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_trig003.test 2010-03-29 19:07:45 +0000
@@ -149,6 +149,8 @@ DROP TABLE IF EXISTS test.t2;
DROP TABLE IF EXISTS test.t3;
--enable_warnings
+sync_slave_with_master;
+
diff_files $MYSQLTEST_VARDIR/tmp/trg003_master.sql $MYSQLTEST_VARDIR/tmp/trg003_slave.sql;
# End of 5.0 test case
=== modified file 'mysql-test/t/bug47671-master.opt'
--- a/mysql-test/t/bug47671-master.opt 2009-11-25 06:55:49 +0000
+++ b/mysql-test/t/bug47671-master.opt 2010-03-28 18:10:00 +0000
@@ -1 +1 @@
---default-character-set=utf8 --skip-character-set-client-handshake
+--character-set-server=utf8 --skip-character-set-client-handshake
=== modified file 'mysql-test/t/ctype_latin1_de-master.opt'
--- a/mysql-test/t/ctype_latin1_de-master.opt 2003-05-21 23:57:27 +0000
+++ b/mysql-test/t/ctype_latin1_de-master.opt 2010-03-28 18:10:00 +0000
@@ -1 +1 @@
---default-character-set=latin1 --default-collation=latin1_german2_ci
+--character-set-server=latin1 --default-collation=latin1_german2_ci
=== modified file 'mysql-test/t/ctype_ucs2_def-master.opt'
--- a/mysql-test/t/ctype_ucs2_def-master.opt 2007-02-19 11:04:38 +0000
+++ b/mysql-test/t/ctype_ucs2_def-master.opt 2010-03-28 18:10:00 +0000
@@ -1 +1 @@
---default-collation=ucs2_unicode_ci --default-character-set=ucs2,latin1
+--default-collation=ucs2_unicode_ci --character-set-server=ucs2,latin1
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2010-04-01 21:42:40 +0000
+++ b/mysys/mf_keycache.c 2010-04-03 20:19:35 +0000
@@ -4222,6 +4222,12 @@ restart:
uint next_status;
uint hash_requests;
+ LINT_INIT(next_hash_link);
+ LINT_INIT(next_diskpos);
+ LINT_INIT(next_file);
+ LINT_INIT(next_status);
+ LINT_INIT(hash_requests);
+
total_found++;
found++;
KEYCACHE_DBUG_ASSERT(found <= keycache->blocks_used);
=== modified file 'mysys/my_gethostbyname.c'
--- a/mysys/my_gethostbyname.c 2006-12-31 00:32:21 +0000
+++ b/mysys/my_gethostbyname.c 2010-03-31 20:50:54 +0000
@@ -91,9 +91,12 @@ extern pthread_mutex_t LOCK_gethostbynam
is finished with the structure.
*/
-struct hostent *my_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- int buflen, int *h_errnop)
+struct hostent *
+my_gethostbyname_r(const char *name,
+ struct hostent *result __attribute__((unused)),
+ char *buffer __attribute__((unused)),
+ int buflen __attribute__((unused)),
+ int *h_errnop)
{
struct hostent *hp;
pthread_mutex_lock(&LOCK_gethostbyname_r);
=== modified file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/auth_socket.c 2010-04-01 14:34:51 +0000
@@ -99,4 +99,21 @@ mysql_declare_plugin(socket_auth)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+mysql_declare_plugin_end;
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-03-31 18:37:45 +0000
+++ b/plugin/auth/dialog.c 2010-04-01 14:34:51 +0000
@@ -171,6 +171,38 @@ mysql_declare_plugin(dialog)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+maria_declare_plugin_end;
/********************* CLIENT SIDE ***************************************/
/*
=== modified file 'plugin/daemon_example/daemon_example.cc'
--- a/plugin/daemon_example/daemon_example.cc 2007-06-27 14:49:12 +0000
+++ b/plugin/daemon_example/daemon_example.cc 2010-04-01 14:34:51 +0000
@@ -200,3 +200,20 @@ mysql_declare_plugin(daemon_example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(daemon_example)
+{
+ MYSQL_DAEMON_PLUGIN,
+ &daemon_example_plugin,
+ "daemon_example",
+ "Brian Aker",
+ "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",
+ PLUGIN_LICENSE_GPL,
+ daemon_example_plugin_init, /* Plugin Init */
+ daemon_example_plugin_deinit, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'plugin/fulltext/plugin_example.c'
--- a/plugin/fulltext/plugin_example.c 2010-01-04 17:54:42 +0000
+++ b/plugin/fulltext/plugin_example.c 2010-04-01 14:34:51 +0000
@@ -270,4 +270,21 @@ mysql_declare_plugin(ftexample)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(ftexample)
+{
+ MYSQL_FTPARSER_PLUGIN, /* type */
+ &simple_parser_descriptor, /* descriptor */
+ "simple_parser", /* name */
+ "MySQL AB", /* author */
+ "Simple Full-Text Parser", /* description */
+ PLUGIN_LICENSE_GPL,
+ simple_parser_plugin_init, /* init function (when loaded) */
+ simple_parser_plugin_deinit,/* deinit function (when unloaded) */
+ 0x0001, /* version */
+ simple_status, /* status variables */
+ simple_system_variables, /* system variables */
+ "0.01", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'server-tools/CMakeLists.txt'
--- a/server-tools/CMakeLists.txt 2007-02-14 11:42:11 +0000
+++ b/server-tools/CMakeLists.txt 2010-04-02 09:20:09 +0000
@@ -27,7 +27,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc co
user_management_commands.cc
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
- ../../libmysql/errmsg.c)
+ ../../libmysql/errmsg.c ../../sql-common/client_plugin.c)
ADD_DEPENDENCIES(mysqlmanager GenError)
TARGET_LINK_LIBRARIES(mysqlmanager dbug mysys strings taocrypt vio yassl zlib wsock32)
=== modified file 'server-tools/instance-manager/CMakeLists.txt'
--- a/server-tools/instance-manager/CMakeLists.txt 2007-12-27 17:16:02 +0000
+++ b/server-tools/instance-manager/CMakeLists.txt 2010-04-02 09:20:09 +0000
@@ -28,7 +28,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc co
user_management_commands.cc ../../mysys/my_rnd.c
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
- ../../libmysql/errmsg.c)
+ ../../libmysql/errmsg.c ../../sql-common/client_plugin.c)
ADD_DEPENDENCIES(mysqlmanager GenError)
TARGET_LINK_LIBRARIES(mysqlmanager debug dbug mysys strings taocrypt vio yassl zlib wsock32)
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2010-03-29 15:13:53 +0000
+++ b/sql-common/client.c 2010-04-02 09:20:09 +0000
@@ -2345,7 +2345,7 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_V
case VIO_TYPE_SSL:
{
struct sockaddr addr;
- socklen_t addrlen= sizeof(addr);
+ SOCKET_SIZE_TYPE addrlen= sizeof(addr);
if (getsockname(vio->sd, &addr, &addrlen))
return;
info->protocol= addr.sa_family == AF_UNIX ?
@@ -2360,7 +2360,7 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_V
return;
case VIO_TYPE_SHARED_MEMORY:
info->protocol= MYSQL_VIO_MEMORY;
- info->handle= vio->handle_client_file_map; /* or what ? */
+ info->handle= vio->handle_file_map; /* or what ? */
return;
#endif
default: DBUG_ASSERT(0);
@@ -2394,7 +2394,7 @@ static void client_mpvio_info(MYSQL_PLUG
*/
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
- char *data_plugin, const char *db)
+ const char *data_plugin, const char *db)
{
const char *auth_plugin_name;
auth_plugin_t *auth_plugin;
@@ -2540,7 +2540,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
char buff[NAME_LEN+USERNAME_LENGTH+100];
int scramble_data_len, pkt_scramble_len;
char *end, *host_info=0, *server_version_end, *pkt_end;
- char *scramble_data, *scramble_plugin;
+ char *scramble_data;
+ const char *scramble_plugin;
my_socket sock;
in_addr_t ip_addr;
struct sockaddr_in sock_addr;
=== modified file 'sql/client_settings.h'
--- a/sql/client_settings.h 2010-03-29 15:13:53 +0000
+++ b/sql/client_settings.h 2010-04-02 09:20:09 +0000
@@ -29,7 +29,6 @@
#define mysql_master_send_query(A, B, C) 1
#define mysql_slave_send_query(A, B, C) 1
#define mysql_rpl_probe(mysql) 0
-#undef HAVE_SMEM
#undef _CUSTOMCONFIG_
#define mysql_server_init(a,b,c) mysql_client_plugin_init()
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-03-29 15:13:53 +0000
+++ b/sql/ha_ndbcluster.cc 2010-04-01 14:34:51 +0000
@@ -10564,6 +10564,23 @@ mysql_declare_plugin(ndbcluster)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_storage_engine,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ "Clustered, fault-tolerant tables",
+ PLUGIN_LICENSE_GPL,
+ ndbcluster_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ ndb_status_variables_export,/* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
#else
int Sun_ar_require_a_symbol_here= 0;
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc 2010-04-01 14:34:51 +0000
@@ -6715,5 +6715,22 @@ mysql_declare_plugin(partition)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_storage_engine,
+ "partition",
+ "Mikael Ronstrom, MySQL AB",
+ "Partition Storage Engine Helper",
+ PLUGIN_LICENSE_GPL,
+ partition_initialize, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#endif
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-03-29 21:16:12 +0000
+++ b/sql/handler.cc 2010-04-03 20:19:35 +0000
@@ -4282,7 +4282,7 @@ int handler::read_multi_range_first(KEY_
*/
int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
{
- int result;
+ int result= 0;
DBUG_ENTER("handler::read_multi_range_next");
/* We should not be called after the last call returned EOF. */
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2010-03-15 11:51:23 +0000
+++ b/sql/item.cc 2010-04-01 09:04:26 +0000
@@ -7040,7 +7040,7 @@ bool Item_cache_int::cache_value()
}
-void Item_cache_int::store(Item *item, longlong val_arg)
+void Item_cache_int::store_longlong(Item *item, longlong val_arg)
{
/* An explicit values is given, save it. */
value_cached= TRUE;
=== modified file 'sql/item.h'
--- a/sql/item.h 2010-03-15 11:51:23 +0000
+++ b/sql/item.h 2010-04-01 09:04:26 +0000
@@ -1132,7 +1132,8 @@ class Field_enumerator
{
public:
virtual void visit_field(Field *field)= 0;
- virtual ~Field_enumerator() {}; /* purecov: inspected */
+ virtual ~Field_enumerator() {}; /* purecov: inspected */
+ Field_enumerator() {} /* Remove gcc warning */
};
@@ -3148,7 +3149,7 @@ public:
Item_cache_int(enum_field_types field_type_arg):
Item_cache(field_type_arg), value(0) {}
- void store(Item *item, longlong val_arg);
+ void store_longlong(Item *item, longlong val_arg);
double val_real();
longlong val_int();
String* val_str(String *str);
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2010-03-04 08:03:07 +0000
+++ b/sql/item_cmpfunc.cc 2010-03-28 18:10:00 +0000
@@ -879,7 +879,7 @@ get_time_value(THD *thd, Item ***item_ar
Item_cache_int *cache= new Item_cache_int();
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
- cache->store(item, value);
+ cache->store_longlong(item, value);
*cache_arg= cache;
*item_arg= cache_arg;
}
@@ -917,13 +917,13 @@ int Arg_comparator::set_cmp_func(Item_re
cache->set_used_tables(1);
if (!(*a)->is_datetime())
{
- cache->store((*a), const_value);
+ cache->store_longlong((*a), const_value);
a_cache= cache;
a= (Item **)&a_cache;
}
else
{
- cache->store((*b), const_value);
+ cache->store_longlong((*b), const_value);
b_cache= cache;
b= (Item **)&b_cache;
}
@@ -1145,7 +1145,7 @@ get_datetime_value(THD *thd, Item ***ite
Item_cache_int *cache= new Item_cache_int(MYSQL_TYPE_DATETIME);
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
- cache->store(item, value);
+ cache->store_longlong(item, value);
*cache_arg= cache;
*item_arg= cache_arg;
}
=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc 2010-03-04 08:03:07 +0000
+++ b/sql/item_create.cc 2010-03-29 19:07:45 +0000
@@ -76,7 +76,7 @@ public:
@param thd The current thread
@return An item representing the function call
*/
- virtual Item *create(THD *thd) = 0;
+ virtual Item *create_builder(THD *thd) = 0;
protected:
/** Constructor. */
@@ -101,7 +101,7 @@ public:
@param arg1 The first argument of the function
@return An item representing the function call
*/
- virtual Item *create(THD *thd, Item *arg1) = 0;
+ virtual Item *create_1_arg(THD *thd, Item *arg1) = 0;
protected:
/** Constructor. */
@@ -127,7 +127,7 @@ public:
@param arg2 The second argument of the function
@return An item representing the function call
*/
- virtual Item *create(THD *thd, Item *arg1, Item *arg2) = 0;
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) = 0;
protected:
/** Constructor. */
@@ -154,7 +154,7 @@ public:
@param arg3 The third argument of the function
@return An item representing the function call
*/
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0;
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0;
protected:
/** Constructor. */
@@ -171,8 +171,8 @@ protected:
class Create_sp_func : public Create_qfunc
{
public:
- virtual Item *create(THD *thd, LEX_STRING db, LEX_STRING name,
- bool use_explicit_name, List<Item> *item_list);
+ virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ bool use_explicit_name, List<Item> *item_list);
static Create_sp_func s_singleton;
@@ -217,7 +217,7 @@ protected:
class Create_func_abs : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_abs s_singleton;
@@ -230,7 +230,7 @@ protected:
class Create_func_acos : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_acos s_singleton;
@@ -243,7 +243,7 @@ protected:
class Create_func_addtime : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_addtime s_singleton;
@@ -256,7 +256,7 @@ protected:
class Create_func_aes_encrypt : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_aes_encrypt s_singleton;
@@ -269,7 +269,7 @@ protected:
class Create_func_aes_decrypt : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_aes_decrypt s_singleton;
@@ -283,7 +283,7 @@ protected:
class Create_func_area : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_area s_singleton;
@@ -298,7 +298,7 @@ protected:
class Create_func_as_wkb : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_as_wkb s_singleton;
@@ -313,7 +313,7 @@ protected:
class Create_func_as_wkt : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_as_wkt s_singleton;
@@ -327,7 +327,7 @@ protected:
class Create_func_asin : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_asin s_singleton;
@@ -353,7 +353,7 @@ protected:
class Create_func_benchmark : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_benchmark s_singleton;
@@ -366,7 +366,7 @@ protected:
class Create_func_bin : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_bin s_singleton;
@@ -379,7 +379,7 @@ protected:
class Create_func_bit_count : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_bit_count s_singleton;
@@ -392,7 +392,7 @@ protected:
class Create_func_bit_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_bit_length s_singleton;
@@ -405,7 +405,7 @@ protected:
class Create_func_ceiling : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ceiling s_singleton;
@@ -419,7 +419,7 @@ protected:
class Create_func_centroid : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_centroid s_singleton;
@@ -433,7 +433,7 @@ protected:
class Create_func_char_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_char_length s_singleton;
@@ -446,7 +446,7 @@ protected:
class Create_func_coercibility : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_coercibility s_singleton;
@@ -459,7 +459,7 @@ protected:
class Create_func_compress : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_compress s_singleton;
@@ -498,7 +498,7 @@ protected:
class Create_func_connection_id : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_connection_id s_singleton;
@@ -512,7 +512,7 @@ protected:
class Create_func_contains : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_contains s_singleton;
@@ -526,7 +526,7 @@ protected:
class Create_func_conv : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_conv s_singleton;
@@ -539,7 +539,7 @@ protected:
class Create_func_convert_tz : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_convert_tz s_singleton;
@@ -552,7 +552,7 @@ protected:
class Create_func_cos : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_cos s_singleton;
@@ -565,7 +565,7 @@ protected:
class Create_func_cot : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_cot s_singleton;
@@ -578,7 +578,7 @@ protected:
class Create_func_crc32 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_crc32 s_singleton;
@@ -592,7 +592,7 @@ protected:
class Create_func_crosses : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_crosses s_singleton;
@@ -606,7 +606,7 @@ protected:
class Create_func_date_format : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_date_format s_singleton;
@@ -619,7 +619,7 @@ protected:
class Create_func_datediff : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_datediff s_singleton;
@@ -632,7 +632,7 @@ protected:
class Create_func_dayname : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayname s_singleton;
@@ -645,7 +645,7 @@ protected:
class Create_func_dayofmonth : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayofmonth s_singleton;
@@ -658,7 +658,7 @@ protected:
class Create_func_dayofweek : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayofweek s_singleton;
@@ -671,7 +671,7 @@ protected:
class Create_func_dayofyear : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayofyear s_singleton;
@@ -684,7 +684,7 @@ protected:
class Create_func_decode : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_decode s_singleton;
@@ -697,7 +697,7 @@ protected:
class Create_func_degrees : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_degrees s_singleton;
@@ -737,7 +737,7 @@ protected:
class Create_func_dimension : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dimension s_singleton;
@@ -752,7 +752,7 @@ protected:
class Create_func_disjoint : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_disjoint s_singleton;
@@ -779,7 +779,7 @@ protected:
class Create_func_encode : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_encode s_singleton;
@@ -806,7 +806,7 @@ protected:
class Create_func_endpoint : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_endpoint s_singleton;
@@ -821,7 +821,7 @@ protected:
class Create_func_envelope : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_envelope s_singleton;
@@ -836,7 +836,7 @@ protected:
class Create_func_equals : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_equals s_singleton;
@@ -850,7 +850,7 @@ protected:
class Create_func_exp : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_exp s_singleton;
@@ -877,7 +877,7 @@ protected:
class Create_func_exteriorring : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_exteriorring s_singleton;
@@ -904,7 +904,7 @@ protected:
class Create_func_find_in_set : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_find_in_set s_singleton;
@@ -917,7 +917,7 @@ protected:
class Create_func_floor : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_floor s_singleton;
@@ -930,7 +930,7 @@ protected:
class Create_func_format : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_format s_singleton;
@@ -943,7 +943,7 @@ protected:
class Create_func_found_rows : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_found_rows s_singleton;
@@ -956,7 +956,7 @@ protected:
class Create_func_from_days : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_from_days s_singleton;
@@ -1013,7 +1013,7 @@ protected:
class Create_func_geometry_type : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_geometry_type s_singleton;
@@ -1028,7 +1028,7 @@ protected:
class Create_func_geometryn : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_geometryn s_singleton;
@@ -1042,7 +1042,7 @@ protected:
class Create_func_get_lock : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_get_lock s_singleton;
@@ -1056,7 +1056,7 @@ protected:
class Create_func_glength : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_glength s_singleton;
@@ -1083,7 +1083,7 @@ protected:
class Create_func_hex : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_hex s_singleton;
@@ -1096,7 +1096,7 @@ protected:
class Create_func_ifnull : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_ifnull s_singleton;
@@ -1109,7 +1109,7 @@ protected:
class Create_func_inet_ntoa : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_inet_ntoa s_singleton;
@@ -1122,7 +1122,7 @@ protected:
class Create_func_inet_aton : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_inet_aton s_singleton;
@@ -1135,7 +1135,7 @@ protected:
class Create_func_instr : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_instr s_singleton;
@@ -1149,7 +1149,7 @@ protected:
class Create_func_interiorringn : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_interiorringn s_singleton;
@@ -1164,7 +1164,7 @@ protected:
class Create_func_intersects : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_intersects s_singleton;
@@ -1178,7 +1178,7 @@ protected:
class Create_func_is_free_lock : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_is_free_lock s_singleton;
@@ -1191,7 +1191,7 @@ protected:
class Create_func_is_used_lock : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_is_used_lock s_singleton;
@@ -1205,7 +1205,7 @@ protected:
class Create_func_isclosed : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_isclosed s_singleton;
@@ -1220,7 +1220,7 @@ protected:
class Create_func_isempty : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_isempty s_singleton;
@@ -1234,7 +1234,7 @@ protected:
class Create_func_isnull : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_isnull s_singleton;
@@ -1248,7 +1248,7 @@ protected:
class Create_func_issimple : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_issimple s_singleton;
@@ -1262,7 +1262,7 @@ protected:
class Create_func_last_day : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_last_day s_singleton;
@@ -1288,7 +1288,7 @@ protected:
class Create_func_lcase : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_lcase s_singleton;
@@ -1314,7 +1314,7 @@ protected:
class Create_func_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_length s_singleton;
@@ -1327,7 +1327,7 @@ protected:
class Create_func_ln : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ln s_singleton;
@@ -1340,7 +1340,7 @@ protected:
class Create_func_load_file : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_load_file s_singleton;
@@ -1379,7 +1379,7 @@ protected:
class Create_func_log10 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_log10 s_singleton;
@@ -1392,7 +1392,7 @@ protected:
class Create_func_log2 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_log2 s_singleton;
@@ -1405,7 +1405,7 @@ protected:
class Create_func_lpad : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_lpad s_singleton;
@@ -1418,7 +1418,7 @@ protected:
class Create_func_ltrim : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ltrim s_singleton;
@@ -1431,7 +1431,7 @@ protected:
class Create_func_makedate : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_makedate s_singleton;
@@ -1444,7 +1444,7 @@ protected:
class Create_func_maketime : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_maketime s_singleton;
@@ -1483,7 +1483,7 @@ protected:
class Create_func_md5 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_md5 s_singleton;
@@ -1496,7 +1496,7 @@ protected:
class Create_func_monthname : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_monthname s_singleton;
@@ -1509,7 +1509,7 @@ protected:
class Create_func_name_const : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_name_const s_singleton;
@@ -1522,7 +1522,7 @@ protected:
class Create_func_nullif : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_nullif s_singleton;
@@ -1536,7 +1536,7 @@ protected:
class Create_func_numgeometries : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_numgeometries s_singleton;
@@ -1551,7 +1551,7 @@ protected:
class Create_func_numinteriorring : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_numinteriorring s_singleton;
@@ -1566,7 +1566,7 @@ protected:
class Create_func_numpoints : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_numpoints s_singleton;
@@ -1580,7 +1580,7 @@ protected:
class Create_func_oct : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_oct s_singleton;
@@ -1593,7 +1593,7 @@ protected:
class Create_func_ord : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ord s_singleton;
@@ -1607,7 +1607,7 @@ protected:
class Create_func_overlaps : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_overlaps s_singleton;
@@ -1621,7 +1621,7 @@ protected:
class Create_func_period_add : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_period_add s_singleton;
@@ -1634,7 +1634,7 @@ protected:
class Create_func_period_diff : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_period_diff s_singleton;
@@ -1647,7 +1647,7 @@ protected:
class Create_func_pi : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_pi s_singleton;
@@ -1661,7 +1661,7 @@ protected:
class Create_func_pointn : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_pointn s_singleton;
@@ -1675,7 +1675,7 @@ protected:
class Create_func_pow : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_pow s_singleton;
@@ -1688,7 +1688,7 @@ protected:
class Create_func_quote : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_quote s_singleton;
@@ -1701,7 +1701,7 @@ protected:
class Create_func_radians : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_radians s_singleton;
@@ -1727,7 +1727,7 @@ protected:
class Create_func_release_lock : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_release_lock s_singleton;
@@ -1740,7 +1740,7 @@ protected:
class Create_func_reverse : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_reverse s_singleton;
@@ -1766,7 +1766,7 @@ protected:
class Create_func_row_count : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_row_count s_singleton;
@@ -1779,7 +1779,7 @@ protected:
class Create_func_rpad : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_rpad s_singleton;
@@ -1792,7 +1792,7 @@ protected:
class Create_func_rtrim : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_rtrim s_singleton;
@@ -1805,7 +1805,7 @@ protected:
class Create_func_sec_to_time : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sec_to_time s_singleton;
@@ -1818,7 +1818,7 @@ protected:
class Create_func_sha : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sha s_singleton;
@@ -1831,7 +1831,7 @@ protected:
class Create_func_sign : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sign s_singleton;
@@ -1844,7 +1844,7 @@ protected:
class Create_func_sin : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sin s_singleton;
@@ -1857,7 +1857,7 @@ protected:
class Create_func_sleep : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sleep s_singleton;
@@ -1870,7 +1870,7 @@ protected:
class Create_func_soundex : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_soundex s_singleton;
@@ -1883,7 +1883,7 @@ protected:
class Create_func_space : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_space s_singleton;
@@ -1896,7 +1896,7 @@ protected:
class Create_func_sqrt : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sqrt s_singleton;
@@ -1910,7 +1910,7 @@ protected:
class Create_func_srid : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_srid s_singleton;
@@ -1925,7 +1925,7 @@ protected:
class Create_func_startpoint : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_startpoint s_singleton;
@@ -1939,7 +1939,7 @@ protected:
class Create_func_str_to_date : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_str_to_date s_singleton;
@@ -1952,7 +1952,7 @@ protected:
class Create_func_strcmp : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_strcmp s_singleton;
@@ -1965,7 +1965,7 @@ protected:
class Create_func_substr_index : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_substr_index s_singleton;
@@ -1978,7 +1978,7 @@ protected:
class Create_func_subtime : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_subtime s_singleton;
@@ -1991,7 +1991,7 @@ protected:
class Create_func_tan : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_tan s_singleton;
@@ -2004,7 +2004,7 @@ protected:
class Create_func_time_format : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_time_format s_singleton;
@@ -2017,7 +2017,7 @@ protected:
class Create_func_time_to_sec : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_time_to_sec s_singleton;
@@ -2030,7 +2030,7 @@ protected:
class Create_func_timediff : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_timediff s_singleton;
@@ -2043,7 +2043,7 @@ protected:
class Create_func_to_days : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_to_days s_singleton;
@@ -2057,7 +2057,7 @@ protected:
class Create_func_touches : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_touches s_singleton;
@@ -2071,7 +2071,7 @@ protected:
class Create_func_ucase : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ucase s_singleton;
@@ -2084,7 +2084,7 @@ protected:
class Create_func_uncompress : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_uncompress s_singleton;
@@ -2097,7 +2097,7 @@ protected:
class Create_func_uncompressed_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_uncompressed_length s_singleton;
@@ -2110,7 +2110,7 @@ protected:
class Create_func_unhex : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_unhex s_singleton;
@@ -2136,7 +2136,7 @@ protected:
class Create_func_uuid : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_uuid s_singleton;
@@ -2149,7 +2149,7 @@ protected:
class Create_func_uuid_short : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_uuid_short s_singleton;
@@ -2162,7 +2162,7 @@ protected:
class Create_func_version : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_version s_singleton;
@@ -2175,7 +2175,7 @@ protected:
class Create_func_weekday : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_weekday s_singleton;
@@ -2188,7 +2188,7 @@ protected:
class Create_func_weekofyear : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_weekofyear s_singleton;
@@ -2202,7 +2202,7 @@ protected:
class Create_func_within : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_within s_singleton;
@@ -2217,7 +2217,7 @@ protected:
class Create_func_x : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_x s_singleton;
@@ -2231,7 +2231,7 @@ protected:
class Create_func_xml_extractvalue : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_xml_extractvalue s_singleton;
@@ -2244,7 +2244,7 @@ protected:
class Create_func_xml_update : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_xml_update s_singleton;
@@ -2258,7 +2258,7 @@ protected:
class Create_func_y : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_y s_singleton;
@@ -2353,7 +2353,7 @@ Create_qfunc::create(THD *thd, LEX_STRIN
if (thd->lex->copy_db_to(&db.str, &db.length))
return NULL;
- return create(thd, db, name, false, item_list);
+ return create_with_db(thd, db, name, false, item_list);
}
@@ -2470,8 +2470,8 @@ Create_udf_func::create(THD *thd, udf_fu
Create_sp_func Create_sp_func::s_singleton;
Item*
-Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
- bool use_explicit_name, List<Item> *item_list)
+Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ bool use_explicit_name, List<Item> *item_list)
{
int arg_count= 0;
Item *func= NULL;
@@ -2538,7 +2538,7 @@ Create_func_arg0::create(THD *thd, LEX_S
return NULL;
}
- return create(thd);
+ return create_builder(thd);
}
@@ -2564,7 +2564,7 @@ Create_func_arg1::create(THD *thd, LEX_S
return NULL;
}
- return create(thd, param_1);
+ return create_1_arg(thd, param_1);
}
@@ -2592,7 +2592,7 @@ Create_func_arg2::create(THD *thd, LEX_S
return NULL;
}
- return create(thd, param_1, param_2);
+ return create_2_arg(thd, param_1, param_2);
}
@@ -2622,14 +2622,14 @@ Create_func_arg3::create(THD *thd, LEX_S
return NULL;
}
- return create(thd, param_1, param_2, param_3);
+ return create_3_arg(thd, param_1, param_2, param_3);
}
Create_func_abs Create_func_abs::s_singleton;
Item*
-Create_func_abs::create(THD *thd, Item *arg1)
+Create_func_abs::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_abs(arg1);
}
@@ -2638,7 +2638,7 @@ Create_func_abs::create(THD *thd, Item *
Create_func_acos Create_func_acos::s_singleton;
Item*
-Create_func_acos::create(THD *thd, Item *arg1)
+Create_func_acos::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_acos(arg1);
}
@@ -2647,7 +2647,7 @@ Create_func_acos::create(THD *thd, Item
Create_func_addtime Create_func_addtime::s_singleton;
Item*
-Create_func_addtime::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_addtime::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 0);
}
@@ -2656,7 +2656,7 @@ Create_func_addtime::create(THD *thd, It
Create_func_aes_encrypt Create_func_aes_encrypt::s_singleton;
Item*
-Create_func_aes_encrypt::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_aes_encrypt::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_aes_encrypt(arg1, arg2);
}
@@ -2665,7 +2665,7 @@ Create_func_aes_encrypt::create(THD *thd
Create_func_aes_decrypt Create_func_aes_decrypt::s_singleton;
Item*
-Create_func_aes_decrypt::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_aes_decrypt::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_aes_decrypt(arg1, arg2);
}
@@ -2675,7 +2675,7 @@ Create_func_aes_decrypt::create(THD *thd
Create_func_area Create_func_area::s_singleton;
Item*
-Create_func_area::create(THD *thd, Item *arg1)
+Create_func_area::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_area(arg1);
}
@@ -2686,7 +2686,7 @@ Create_func_area::create(THD *thd, Item
Create_func_as_wkb Create_func_as_wkb::s_singleton;
Item*
-Create_func_as_wkb::create(THD *thd, Item *arg1)
+Create_func_as_wkb::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_as_wkb(arg1);
}
@@ -2697,7 +2697,7 @@ Create_func_as_wkb::create(THD *thd, Ite
Create_func_as_wkt Create_func_as_wkt::s_singleton;
Item*
-Create_func_as_wkt::create(THD *thd, Item *arg1)
+Create_func_as_wkt::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_as_wkt(arg1);
}
@@ -2707,7 +2707,7 @@ Create_func_as_wkt::create(THD *thd, Ite
Create_func_asin Create_func_asin::s_singleton;
Item*
-Create_func_asin::create(THD *thd, Item *arg1)
+Create_func_asin::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_asin(arg1);
}
@@ -2753,7 +2753,7 @@ Create_func_atan::create_native(THD *thd
Create_func_benchmark Create_func_benchmark::s_singleton;
Item*
-Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_benchmark::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
return new (thd->mem_root) Item_func_benchmark(arg1, arg2);
@@ -2763,7 +2763,7 @@ Create_func_benchmark::create(THD *thd,
Create_func_bin Create_func_bin::s_singleton;
Item*
-Create_func_bin::create(THD *thd, Item *arg1)
+Create_func_bin::create_1_arg(THD *thd, Item *arg1)
{
Item *i10= new (thd->mem_root) Item_int((int32) 10,2);
Item *i2= new (thd->mem_root) Item_int((int32) 2,1);
@@ -2774,7 +2774,7 @@ Create_func_bin::create(THD *thd, Item *
Create_func_bit_count Create_func_bit_count::s_singleton;
Item*
-Create_func_bit_count::create(THD *thd, Item *arg1)
+Create_func_bit_count::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_bit_count(arg1);
}
@@ -2783,7 +2783,7 @@ Create_func_bit_count::create(THD *thd,
Create_func_bit_length Create_func_bit_length::s_singleton;
Item*
-Create_func_bit_length::create(THD *thd, Item *arg1)
+Create_func_bit_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_bit_length(arg1);
}
@@ -2792,7 +2792,7 @@ Create_func_bit_length::create(THD *thd,
Create_func_ceiling Create_func_ceiling::s_singleton;
Item*
-Create_func_ceiling::create(THD *thd, Item *arg1)
+Create_func_ceiling::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ceiling(arg1);
}
@@ -2802,7 +2802,7 @@ Create_func_ceiling::create(THD *thd, It
Create_func_centroid Create_func_centroid::s_singleton;
Item*
-Create_func_centroid::create(THD *thd, Item *arg1)
+Create_func_centroid::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_centroid(arg1);
}
@@ -2812,7 +2812,7 @@ Create_func_centroid::create(THD *thd, I
Create_func_char_length Create_func_char_length::s_singleton;
Item*
-Create_func_char_length::create(THD *thd, Item *arg1)
+Create_func_char_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_char_length(arg1);
}
@@ -2821,7 +2821,7 @@ Create_func_char_length::create(THD *thd
Create_func_coercibility Create_func_coercibility::s_singleton;
Item*
-Create_func_coercibility::create(THD *thd, Item *arg1)
+Create_func_coercibility::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_coercibility(arg1);
}
@@ -2873,7 +2873,7 @@ Create_func_concat_ws::create_native(THD
Create_func_compress Create_func_compress::s_singleton;
Item*
-Create_func_compress::create(THD *thd, Item *arg1)
+Create_func_compress::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_compress(arg1);
}
@@ -2882,7 +2882,7 @@ Create_func_compress::create(THD *thd, I
Create_func_connection_id Create_func_connection_id::s_singleton;
Item*
-Create_func_connection_id::create(THD *thd)
+Create_func_connection_id::create_builder(THD *thd)
{
thd->lex->safe_to_cache_query= 0;
return new (thd->mem_root) Item_func_connection_id();
@@ -2893,7 +2893,7 @@ Create_func_connection_id::create(THD *t
Create_func_contains Create_func_contains::s_singleton;
Item*
-Create_func_contains::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_contains::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_CONTAINS_FUNC);
@@ -2904,7 +2904,7 @@ Create_func_contains::create(THD *thd, I
Create_func_conv Create_func_conv::s_singleton;
Item*
-Create_func_conv::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_conv::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_conv(arg1, arg2, arg3);
}
@@ -2913,7 +2913,7 @@ Create_func_conv::create(THD *thd, Item
Create_func_convert_tz Create_func_convert_tz::s_singleton;
Item*
-Create_func_convert_tz::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_convert_tz::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_convert_tz(arg1, arg2, arg3);
}
@@ -2922,7 +2922,7 @@ Create_func_convert_tz::create(THD *thd,
Create_func_cos Create_func_cos::s_singleton;
Item*
-Create_func_cos::create(THD *thd, Item *arg1)
+Create_func_cos::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_cos(arg1);
}
@@ -2931,7 +2931,7 @@ Create_func_cos::create(THD *thd, Item *
Create_func_cot Create_func_cot::s_singleton;
Item*
-Create_func_cot::create(THD *thd, Item *arg1)
+Create_func_cot::create_1_arg(THD *thd, Item *arg1)
{
Item *i1= new (thd->mem_root) Item_int((char*) "1", 1, 1);
Item *i2= new (thd->mem_root) Item_func_tan(arg1);
@@ -2942,7 +2942,7 @@ Create_func_cot::create(THD *thd, Item *
Create_func_crc32 Create_func_crc32::s_singleton;
Item*
-Create_func_crc32::create(THD *thd, Item *arg1)
+Create_func_crc32::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_crc32(arg1);
}
@@ -2952,7 +2952,7 @@ Create_func_crc32::create(THD *thd, Item
Create_func_crosses Create_func_crosses::s_singleton;
Item*
-Create_func_crosses::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_crosses::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_CROSSES_FUNC);
@@ -2963,7 +2963,7 @@ Create_func_crosses::create(THD *thd, It
Create_func_date_format Create_func_date_format::s_singleton;
Item*
-Create_func_date_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_date_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_date_format(arg1, arg2, 0);
}
@@ -2972,7 +2972,7 @@ Create_func_date_format::create(THD *thd
Create_func_datediff Create_func_datediff::s_singleton;
Item*
-Create_func_datediff::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_datediff::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
Item *i1= new (thd->mem_root) Item_func_to_days(arg1);
Item *i2= new (thd->mem_root) Item_func_to_days(arg2);
@@ -2984,7 +2984,7 @@ Create_func_datediff::create(THD *thd, I
Create_func_dayname Create_func_dayname::s_singleton;
Item*
-Create_func_dayname::create(THD *thd, Item *arg1)
+Create_func_dayname::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dayname(arg1);
}
@@ -2993,7 +2993,7 @@ Create_func_dayname::create(THD *thd, It
Create_func_dayofmonth Create_func_dayofmonth::s_singleton;
Item*
-Create_func_dayofmonth::create(THD *thd, Item *arg1)
+Create_func_dayofmonth::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dayofmonth(arg1);
}
@@ -3002,7 +3002,7 @@ Create_func_dayofmonth::create(THD *thd,
Create_func_dayofweek Create_func_dayofweek::s_singleton;
Item*
-Create_func_dayofweek::create(THD *thd, Item *arg1)
+Create_func_dayofweek::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_weekday(arg1, 1);
}
@@ -3011,7 +3011,7 @@ Create_func_dayofweek::create(THD *thd,
Create_func_dayofyear Create_func_dayofyear::s_singleton;
Item*
-Create_func_dayofyear::create(THD *thd, Item *arg1)
+Create_func_dayofyear::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dayofyear(arg1);
}
@@ -3020,7 +3020,7 @@ Create_func_dayofyear::create(THD *thd,
Create_func_decode Create_func_decode::s_singleton;
Item*
-Create_func_decode::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_decode::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_decode(arg1, arg2);
}
@@ -3029,7 +3029,7 @@ Create_func_decode::create(THD *thd, Ite
Create_func_degrees Create_func_degrees::s_singleton;
Item*
-Create_func_degrees::create(THD *thd, Item *arg1)
+Create_func_degrees::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_units((char*) "degrees", arg1,
180/M_PI, 0.0);
@@ -3114,7 +3114,7 @@ Create_func_des_encrypt::create_native(T
Create_func_dimension Create_func_dimension::s_singleton;
Item*
-Create_func_dimension::create(THD *thd, Item *arg1)
+Create_func_dimension::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dimension(arg1);
}
@@ -3125,7 +3125,7 @@ Create_func_dimension::create(THD *thd,
Create_func_disjoint Create_func_disjoint::s_singleton;
Item*
-Create_func_disjoint::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_DISJOINT_FUNC);
@@ -3157,7 +3157,7 @@ Create_func_elt::create_native(THD *thd,
Create_func_encode Create_func_encode::s_singleton;
Item*
-Create_func_encode::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_encode::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_encode(arg1, arg2);
}
@@ -3205,7 +3205,7 @@ Create_func_encrypt::create_native(THD *
Create_func_endpoint Create_func_endpoint::s_singleton;
Item*
-Create_func_endpoint::create(THD *thd, Item *arg1)
+Create_func_endpoint::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_spatial_decomp(arg1,
Item_func::SP_ENDPOINT);
@@ -3217,7 +3217,7 @@ Create_func_endpoint::create(THD *thd, I
Create_func_envelope Create_func_envelope::s_singleton;
Item*
-Create_func_envelope::create(THD *thd, Item *arg1)
+Create_func_envelope::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_envelope(arg1);
}
@@ -3228,7 +3228,7 @@ Create_func_envelope::create(THD *thd, I
Create_func_equals Create_func_equals::s_singleton;
Item*
-Create_func_equals::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_equals::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_EQUALS_FUNC);
@@ -3239,7 +3239,7 @@ Create_func_equals::create(THD *thd, Ite
Create_func_exp Create_func_exp::s_singleton;
Item*
-Create_func_exp::create(THD *thd, Item *arg1)
+Create_func_exp::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_exp(arg1);
}
@@ -3302,7 +3302,7 @@ Create_func_export_set::create_native(TH
Create_func_exteriorring Create_func_exteriorring::s_singleton;
Item*
-Create_func_exteriorring::create(THD *thd, Item *arg1)
+Create_func_exteriorring::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_spatial_decomp(arg1,
Item_func::SP_EXTERIORRING);
@@ -3334,7 +3334,7 @@ Create_func_field::create_native(THD *th
Create_func_find_in_set Create_func_find_in_set::s_singleton;
Item*
-Create_func_find_in_set::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_find_in_set::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_find_in_set(arg1, arg2);
}
@@ -3343,7 +3343,7 @@ Create_func_find_in_set::create(THD *thd
Create_func_floor Create_func_floor::s_singleton;
Item*
-Create_func_floor::create(THD *thd, Item *arg1)
+Create_func_floor::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_floor(arg1);
}
@@ -3352,7 +3352,7 @@ Create_func_floor::create(THD *thd, Item
Create_func_format Create_func_format::s_singleton;
Item*
-Create_func_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_format(arg1, arg2);
}
@@ -3361,7 +3361,7 @@ Create_func_format::create(THD *thd, Ite
Create_func_found_rows Create_func_found_rows::s_singleton;
Item*
-Create_func_found_rows::create(THD *thd)
+Create_func_found_rows::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -3372,7 +3372,7 @@ Create_func_found_rows::create(THD *thd)
Create_func_from_days Create_func_from_days::s_singleton;
Item*
-Create_func_from_days::create(THD *thd, Item *arg1)
+Create_func_from_days::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_from_days(arg1);
}
@@ -3500,7 +3500,7 @@ Create_func_geometry_from_wkb::create_na
Create_func_geometry_type Create_func_geometry_type::s_singleton;
Item*
-Create_func_geometry_type::create(THD *thd, Item *arg1)
+Create_func_geometry_type::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_geometry_type(arg1);
}
@@ -3511,7 +3511,7 @@ Create_func_geometry_type::create(THD *t
Create_func_geometryn Create_func_geometryn::s_singleton;
Item*
-Create_func_geometryn::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_geometryn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2,
Item_func::SP_GEOMETRYN);
@@ -3522,7 +3522,7 @@ Create_func_geometryn::create(THD *thd,
Create_func_get_lock Create_func_get_lock::s_singleton;
Item*
-Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_get_lock::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3534,7 +3534,7 @@ Create_func_get_lock::create(THD *thd, I
Create_func_glength Create_func_glength::s_singleton;
Item*
-Create_func_glength::create(THD *thd, Item *arg1)
+Create_func_glength::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_glength(arg1);
}
@@ -3565,7 +3565,7 @@ Create_func_greatest::create_native(THD
Create_func_hex Create_func_hex::s_singleton;
Item*
-Create_func_hex::create(THD *thd, Item *arg1)
+Create_func_hex::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_hex(arg1);
}
@@ -3574,7 +3574,7 @@ Create_func_hex::create(THD *thd, Item *
Create_func_ifnull Create_func_ifnull::s_singleton;
Item*
-Create_func_ifnull::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_ifnull::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_ifnull(arg1, arg2);
}
@@ -3583,7 +3583,7 @@ Create_func_ifnull::create(THD *thd, Ite
Create_func_inet_ntoa Create_func_inet_ntoa::s_singleton;
Item*
-Create_func_inet_ntoa::create(THD *thd, Item *arg1)
+Create_func_inet_ntoa::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_inet_ntoa(arg1);
}
@@ -3592,7 +3592,7 @@ Create_func_inet_ntoa::create(THD *thd,
Create_func_inet_aton Create_func_inet_aton::s_singleton;
Item*
-Create_func_inet_aton::create(THD *thd, Item *arg1)
+Create_func_inet_aton::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_inet_aton(arg1);
}
@@ -3601,7 +3601,7 @@ Create_func_inet_aton::create(THD *thd,
Create_func_instr Create_func_instr::s_singleton;
Item*
-Create_func_instr::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_instr::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_locate(arg1, arg2);
}
@@ -3611,7 +3611,7 @@ Create_func_instr::create(THD *thd, Item
Create_func_interiorringn Create_func_interiorringn::s_singleton;
Item*
-Create_func_interiorringn::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_interiorringn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2,
Item_func::SP_INTERIORRINGN);
@@ -3623,7 +3623,7 @@ Create_func_interiorringn::create(THD *t
Create_func_intersects Create_func_intersects::s_singleton;
Item*
-Create_func_intersects::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_INTERSECTS_FUNC);
@@ -3634,7 +3634,7 @@ Create_func_intersects::create(THD *thd,
Create_func_is_free_lock Create_func_is_free_lock::s_singleton;
Item*
-Create_func_is_free_lock::create(THD *thd, Item *arg1)
+Create_func_is_free_lock::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3645,7 +3645,7 @@ Create_func_is_free_lock::create(THD *th
Create_func_is_used_lock Create_func_is_used_lock::s_singleton;
Item*
-Create_func_is_used_lock::create(THD *thd, Item *arg1)
+Create_func_is_used_lock::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3657,7 +3657,7 @@ Create_func_is_used_lock::create(THD *th
Create_func_isclosed Create_func_isclosed::s_singleton;
Item*
-Create_func_isclosed::create(THD *thd, Item *arg1)
+Create_func_isclosed::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_isclosed(arg1);
}
@@ -3668,7 +3668,7 @@ Create_func_isclosed::create(THD *thd, I
Create_func_isempty Create_func_isempty::s_singleton;
Item*
-Create_func_isempty::create(THD *thd, Item *arg1)
+Create_func_isempty::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_isempty(arg1);
}
@@ -3678,7 +3678,7 @@ Create_func_isempty::create(THD *thd, It
Create_func_isnull Create_func_isnull::s_singleton;
Item*
-Create_func_isnull::create(THD *thd, Item *arg1)
+Create_func_isnull::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_isnull(arg1);
}
@@ -3688,7 +3688,7 @@ Create_func_isnull::create(THD *thd, Ite
Create_func_issimple Create_func_issimple::s_singleton;
Item*
-Create_func_issimple::create(THD *thd, Item *arg1)
+Create_func_issimple::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_issimple(arg1);
}
@@ -3698,7 +3698,7 @@ Create_func_issimple::create(THD *thd, I
Create_func_last_day Create_func_last_day::s_singleton;
Item*
-Create_func_last_day::create(THD *thd, Item *arg1)
+Create_func_last_day::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_last_day(arg1);
}
@@ -3744,7 +3744,7 @@ Create_func_last_insert_id::create_nativ
Create_func_lcase Create_func_lcase::s_singleton;
Item*
-Create_func_lcase::create(THD *thd, Item *arg1)
+Create_func_lcase::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_lcase(arg1);
}
@@ -3774,7 +3774,7 @@ Create_func_least::create_native(THD *th
Create_func_length Create_func_length::s_singleton;
Item*
-Create_func_length::create(THD *thd, Item *arg1)
+Create_func_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_length(arg1);
}
@@ -3783,7 +3783,7 @@ Create_func_length::create(THD *thd, Ite
Create_func_ln Create_func_ln::s_singleton;
Item*
-Create_func_ln::create(THD *thd, Item *arg1)
+Create_func_ln::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ln(arg1);
}
@@ -3792,7 +3792,7 @@ Create_func_ln::create(THD *thd, Item *a
Create_func_load_file Create_func_load_file::s_singleton;
Item*
-Create_func_load_file::create(THD *thd, Item *arg1)
+Create_func_load_file::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3881,7 +3881,7 @@ Create_func_log::create_native(THD *thd,
Create_func_log10 Create_func_log10::s_singleton;
Item*
-Create_func_log10::create(THD *thd, Item *arg1)
+Create_func_log10::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_log10(arg1);
}
@@ -3890,7 +3890,7 @@ Create_func_log10::create(THD *thd, Item
Create_func_log2 Create_func_log2::s_singleton;
Item*
-Create_func_log2::create(THD *thd, Item *arg1)
+Create_func_log2::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_log2(arg1);
}
@@ -3899,7 +3899,7 @@ Create_func_log2::create(THD *thd, Item
Create_func_lpad Create_func_lpad::s_singleton;
Item*
-Create_func_lpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_lpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_lpad(arg1, arg2, arg3);
}
@@ -3908,7 +3908,7 @@ Create_func_lpad::create(THD *thd, Item
Create_func_ltrim Create_func_ltrim::s_singleton;
Item*
-Create_func_ltrim::create(THD *thd, Item *arg1)
+Create_func_ltrim::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ltrim(arg1);
}
@@ -3917,7 +3917,7 @@ Create_func_ltrim::create(THD *thd, Item
Create_func_makedate Create_func_makedate::s_singleton;
Item*
-Create_func_makedate::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_makedate::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_makedate(arg1, arg2);
}
@@ -3926,7 +3926,7 @@ Create_func_makedate::create(THD *thd, I
Create_func_maketime Create_func_maketime::s_singleton;
Item*
-Create_func_maketime::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_maketime::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_maketime(arg1, arg2, arg3);
}
@@ -4001,7 +4001,7 @@ Create_func_master_pos_wait::create_nati
Create_func_md5 Create_func_md5::s_singleton;
Item*
-Create_func_md5::create(THD *thd, Item *arg1)
+Create_func_md5::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_md5(arg1);
}
@@ -4010,7 +4010,7 @@ Create_func_md5::create(THD *thd, Item *
Create_func_monthname Create_func_monthname::s_singleton;
Item*
-Create_func_monthname::create(THD *thd, Item *arg1)
+Create_func_monthname::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_monthname(arg1);
}
@@ -4019,7 +4019,7 @@ Create_func_monthname::create(THD *thd,
Create_func_name_const Create_func_name_const::s_singleton;
Item*
-Create_func_name_const::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_name_const::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_name_const(arg1, arg2);
}
@@ -4028,7 +4028,7 @@ Create_func_name_const::create(THD *thd,
Create_func_nullif Create_func_nullif::s_singleton;
Item*
-Create_func_nullif::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_nullif::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_nullif(arg1, arg2);
}
@@ -4038,7 +4038,7 @@ Create_func_nullif::create(THD *thd, Ite
Create_func_numgeometries Create_func_numgeometries::s_singleton;
Item*
-Create_func_numgeometries::create(THD *thd, Item *arg1)
+Create_func_numgeometries::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_numgeometries(arg1);
}
@@ -4049,7 +4049,7 @@ Create_func_numgeometries::create(THD *t
Create_func_numinteriorring Create_func_numinteriorring::s_singleton;
Item*
-Create_func_numinteriorring::create(THD *thd, Item *arg1)
+Create_func_numinteriorring::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_numinteriorring(arg1);
}
@@ -4060,7 +4060,7 @@ Create_func_numinteriorring::create(THD
Create_func_numpoints Create_func_numpoints::s_singleton;
Item*
-Create_func_numpoints::create(THD *thd, Item *arg1)
+Create_func_numpoints::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_numpoints(arg1);
}
@@ -4070,7 +4070,7 @@ Create_func_numpoints::create(THD *thd,
Create_func_oct Create_func_oct::s_singleton;
Item*
-Create_func_oct::create(THD *thd, Item *arg1)
+Create_func_oct::create_1_arg(THD *thd, Item *arg1)
{
Item *i10= new (thd->mem_root) Item_int((int32) 10,2);
Item *i8= new (thd->mem_root) Item_int((int32) 8,1);
@@ -4081,7 +4081,7 @@ Create_func_oct::create(THD *thd, Item *
Create_func_ord Create_func_ord::s_singleton;
Item*
-Create_func_ord::create(THD *thd, Item *arg1)
+Create_func_ord::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ord(arg1);
}
@@ -4091,7 +4091,7 @@ Create_func_ord::create(THD *thd, Item *
Create_func_overlaps Create_func_overlaps::s_singleton;
Item*
-Create_func_overlaps::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_overlaps::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_OVERLAPS_FUNC);
@@ -4102,7 +4102,7 @@ Create_func_overlaps::create(THD *thd, I
Create_func_period_add Create_func_period_add::s_singleton;
Item*
-Create_func_period_add::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_period_add::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_period_add(arg1, arg2);
}
@@ -4111,7 +4111,7 @@ Create_func_period_add::create(THD *thd,
Create_func_period_diff Create_func_period_diff::s_singleton;
Item*
-Create_func_period_diff::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_period_diff::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_period_diff(arg1, arg2);
}
@@ -4120,7 +4120,7 @@ Create_func_period_diff::create(THD *thd
Create_func_pi Create_func_pi::s_singleton;
Item*
-Create_func_pi::create(THD *thd)
+Create_func_pi::create_builder(THD *thd)
{
return new (thd->mem_root) Item_static_float_func("pi()", M_PI, 6, 8);
}
@@ -4130,7 +4130,7 @@ Create_func_pi::create(THD *thd)
Create_func_pointn Create_func_pointn::s_singleton;
Item*
-Create_func_pointn::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_pointn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2,
Item_func::SP_POINTN);
@@ -4141,7 +4141,7 @@ Create_func_pointn::create(THD *thd, Ite
Create_func_pow Create_func_pow::s_singleton;
Item*
-Create_func_pow::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_pow::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_pow(arg1, arg2);
}
@@ -4150,7 +4150,7 @@ Create_func_pow::create(THD *thd, Item *
Create_func_quote Create_func_quote::s_singleton;
Item*
-Create_func_quote::create(THD *thd, Item *arg1)
+Create_func_quote::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_quote(arg1);
}
@@ -4159,7 +4159,7 @@ Create_func_quote::create(THD *thd, Item
Create_func_radians Create_func_radians::s_singleton;
Item*
-Create_func_radians::create(THD *thd, Item *arg1)
+Create_func_radians::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_units((char*) "radians", arg1,
M_PI/180, 0.0);
@@ -4216,7 +4216,7 @@ Create_func_rand::create_native(THD *thd
Create_func_release_lock Create_func_release_lock::s_singleton;
Item*
-Create_func_release_lock::create(THD *thd, Item *arg1)
+Create_func_release_lock::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -4227,7 +4227,7 @@ Create_func_release_lock::create(THD *th
Create_func_reverse Create_func_reverse::s_singleton;
Item*
-Create_func_reverse::create(THD *thd, Item *arg1)
+Create_func_reverse::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_reverse(arg1);
}
@@ -4274,7 +4274,7 @@ Create_func_round::create_native(THD *th
Create_func_row_count Create_func_row_count::s_singleton;
Item*
-Create_func_row_count::create(THD *thd)
+Create_func_row_count::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -4285,7 +4285,7 @@ Create_func_row_count::create(THD *thd)
Create_func_rpad Create_func_rpad::s_singleton;
Item*
-Create_func_rpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_rpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_rpad(arg1, arg2, arg3);
}
@@ -4294,7 +4294,7 @@ Create_func_rpad::create(THD *thd, Item
Create_func_rtrim Create_func_rtrim::s_singleton;
Item*
-Create_func_rtrim::create(THD *thd, Item *arg1)
+Create_func_rtrim::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_rtrim(arg1);
}
@@ -4303,7 +4303,7 @@ Create_func_rtrim::create(THD *thd, Item
Create_func_sec_to_time Create_func_sec_to_time::s_singleton;
Item*
-Create_func_sec_to_time::create(THD *thd, Item *arg1)
+Create_func_sec_to_time::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sec_to_time(arg1);
}
@@ -4312,7 +4312,7 @@ Create_func_sec_to_time::create(THD *thd
Create_func_sha Create_func_sha::s_singleton;
Item*
-Create_func_sha::create(THD *thd, Item *arg1)
+Create_func_sha::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sha(arg1);
}
@@ -4321,7 +4321,7 @@ Create_func_sha::create(THD *thd, Item *
Create_func_sign Create_func_sign::s_singleton;
Item*
-Create_func_sign::create(THD *thd, Item *arg1)
+Create_func_sign::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sign(arg1);
}
@@ -4330,7 +4330,7 @@ Create_func_sign::create(THD *thd, Item
Create_func_sin Create_func_sin::s_singleton;
Item*
-Create_func_sin::create(THD *thd, Item *arg1)
+Create_func_sin::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sin(arg1);
}
@@ -4339,7 +4339,7 @@ Create_func_sin::create(THD *thd, Item *
Create_func_sleep Create_func_sleep::s_singleton;
Item*
-Create_func_sleep::create(THD *thd, Item *arg1)
+Create_func_sleep::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -4350,7 +4350,7 @@ Create_func_sleep::create(THD *thd, Item
Create_func_soundex Create_func_soundex::s_singleton;
Item*
-Create_func_soundex::create(THD *thd, Item *arg1)
+Create_func_soundex::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_soundex(arg1);
}
@@ -4359,7 +4359,7 @@ Create_func_soundex::create(THD *thd, It
Create_func_space Create_func_space::s_singleton;
Item*
-Create_func_space::create(THD *thd, Item *arg1)
+Create_func_space::create_1_arg(THD *thd, Item *arg1)
{
/**
TODO: Fix Bug#23637
@@ -4387,7 +4387,7 @@ Create_func_space::create(THD *thd, Item
Create_func_sqrt Create_func_sqrt::s_singleton;
Item*
-Create_func_sqrt::create(THD *thd, Item *arg1)
+Create_func_sqrt::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sqrt(arg1);
}
@@ -4397,7 +4397,7 @@ Create_func_sqrt::create(THD *thd, Item
Create_func_srid Create_func_srid::s_singleton;
Item*
-Create_func_srid::create(THD *thd, Item *arg1)
+Create_func_srid::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_srid(arg1);
}
@@ -4408,7 +4408,7 @@ Create_func_srid::create(THD *thd, Item
Create_func_startpoint Create_func_startpoint::s_singleton;
Item*
-Create_func_startpoint::create(THD *thd, Item *arg1)
+Create_func_startpoint::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_spatial_decomp(arg1,
Item_func::SP_STARTPOINT);
@@ -4419,7 +4419,7 @@ Create_func_startpoint::create(THD *thd,
Create_func_str_to_date Create_func_str_to_date::s_singleton;
Item*
-Create_func_str_to_date::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_str_to_date::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_str_to_date(arg1, arg2);
}
@@ -4428,7 +4428,7 @@ Create_func_str_to_date::create(THD *thd
Create_func_strcmp Create_func_strcmp::s_singleton;
Item*
-Create_func_strcmp::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_strcmp::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_strcmp(arg1, arg2);
}
@@ -4437,7 +4437,7 @@ Create_func_strcmp::create(THD *thd, Ite
Create_func_substr_index Create_func_substr_index::s_singleton;
Item*
-Create_func_substr_index::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_substr_index::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_substr_index(arg1, arg2, arg3);
}
@@ -4446,7 +4446,7 @@ Create_func_substr_index::create(THD *th
Create_func_subtime Create_func_subtime::s_singleton;
Item*
-Create_func_subtime::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_subtime::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 1);
}
@@ -4455,7 +4455,7 @@ Create_func_subtime::create(THD *thd, It
Create_func_tan Create_func_tan::s_singleton;
Item*
-Create_func_tan::create(THD *thd, Item *arg1)
+Create_func_tan::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_tan(arg1);
}
@@ -4464,7 +4464,7 @@ Create_func_tan::create(THD *thd, Item *
Create_func_time_format Create_func_time_format::s_singleton;
Item*
-Create_func_time_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_time_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_date_format(arg1, arg2, 1);
}
@@ -4473,7 +4473,7 @@ Create_func_time_format::create(THD *thd
Create_func_time_to_sec Create_func_time_to_sec::s_singleton;
Item*
-Create_func_time_to_sec::create(THD *thd, Item *arg1)
+Create_func_time_to_sec::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_time_to_sec(arg1);
}
@@ -4482,7 +4482,7 @@ Create_func_time_to_sec::create(THD *thd
Create_func_timediff Create_func_timediff::s_singleton;
Item*
-Create_func_timediff::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_timediff::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_timediff(arg1, arg2);
}
@@ -4491,7 +4491,7 @@ Create_func_timediff::create(THD *thd, I
Create_func_to_days Create_func_to_days::s_singleton;
Item*
-Create_func_to_days::create(THD *thd, Item *arg1)
+Create_func_to_days::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_to_days(arg1);
}
@@ -4501,7 +4501,7 @@ Create_func_to_days::create(THD *thd, It
Create_func_touches Create_func_touches::s_singleton;
Item*
-Create_func_touches::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_touches::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_TOUCHES_FUNC);
@@ -4512,7 +4512,7 @@ Create_func_touches::create(THD *thd, It
Create_func_ucase Create_func_ucase::s_singleton;
Item*
-Create_func_ucase::create(THD *thd, Item *arg1)
+Create_func_ucase::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ucase(arg1);
}
@@ -4521,7 +4521,7 @@ Create_func_ucase::create(THD *thd, Item
Create_func_uncompress Create_func_uncompress::s_singleton;
Item*
-Create_func_uncompress::create(THD *thd, Item *arg1)
+Create_func_uncompress::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_uncompress(arg1);
}
@@ -4530,7 +4530,7 @@ Create_func_uncompress::create(THD *thd,
Create_func_uncompressed_length Create_func_uncompressed_length::s_singleton;
Item*
-Create_func_uncompressed_length::create(THD *thd, Item *arg1)
+Create_func_uncompressed_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_uncompressed_length(arg1);
}
@@ -4539,7 +4539,7 @@ Create_func_uncompressed_length::create(
Create_func_unhex Create_func_unhex::s_singleton;
Item*
-Create_func_unhex::create(THD *thd, Item *arg1)
+Create_func_unhex::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_unhex(arg1);
}
@@ -4584,7 +4584,7 @@ Create_func_unix_timestamp::create_nativ
Create_func_uuid Create_func_uuid::s_singleton;
Item*
-Create_func_uuid::create(THD *thd)
+Create_func_uuid::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -4595,7 +4595,7 @@ Create_func_uuid::create(THD *thd)
Create_func_uuid_short Create_func_uuid_short::s_singleton;
Item*
-Create_func_uuid_short::create(THD *thd)
+Create_func_uuid_short::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -4606,7 +4606,7 @@ Create_func_uuid_short::create(THD *thd)
Create_func_version Create_func_version::s_singleton;
Item*
-Create_func_version::create(THD *thd)
+Create_func_version::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
return new (thd->mem_root) Item_static_string_func("version()",
@@ -4620,7 +4620,7 @@ Create_func_version::create(THD *thd)
Create_func_weekday Create_func_weekday::s_singleton;
Item*
-Create_func_weekday::create(THD *thd, Item *arg1)
+Create_func_weekday::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_weekday(arg1, 0);
}
@@ -4629,7 +4629,7 @@ Create_func_weekday::create(THD *thd, It
Create_func_weekofyear Create_func_weekofyear::s_singleton;
Item*
-Create_func_weekofyear::create(THD *thd, Item *arg1)
+Create_func_weekofyear::create_1_arg(THD *thd, Item *arg1)
{
Item *i1= new (thd->mem_root) Item_int((char*) "0", 3, 1);
return new (thd->mem_root) Item_func_week(arg1, i1);
@@ -4640,7 +4640,7 @@ Create_func_weekofyear::create(THD *thd,
Create_func_within Create_func_within::s_singleton;
Item*
-Create_func_within::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_within::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_WITHIN_FUNC);
@@ -4652,7 +4652,7 @@ Create_func_within::create(THD *thd, Ite
Create_func_x Create_func_x::s_singleton;
Item*
-Create_func_x::create(THD *thd, Item *arg1)
+Create_func_x::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_x(arg1);
}
@@ -4662,7 +4662,7 @@ Create_func_x::create(THD *thd, Item *ar
Create_func_xml_extractvalue Create_func_xml_extractvalue::s_singleton;
Item*
-Create_func_xml_extractvalue::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_xml_extractvalue::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_xml_extractvalue(arg1, arg2);
}
@@ -4671,7 +4671,7 @@ Create_func_xml_extractvalue::create(THD
Create_func_xml_update Create_func_xml_update::s_singleton;
Item*
-Create_func_xml_update::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_xml_update::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_xml_update(arg1, arg2, arg3);
}
@@ -4681,7 +4681,7 @@ Create_func_xml_update::create(THD *thd,
Create_func_y Create_func_y::s_singleton;
Item*
-Create_func_y::create(THD *thd, Item *arg1)
+Create_func_y::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_y(arg1);
}
=== modified file 'sql/item_create.h'
--- a/sql/item_create.h 2007-08-15 13:43:08 +0000
+++ b/sql/item_create.h 2010-03-28 18:10:00 +0000
@@ -91,8 +91,9 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call
*/
- virtual Item* create(THD *thd, LEX_STRING db, LEX_STRING name,
- bool use_explicit_name, List<Item> *item_list) = 0;
+ virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ bool use_explicit_name,
+ List<Item> *item_list) = 0;
protected:
/** Constructor. */
=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc 2010-01-15 15:27:55 +0000
+++ b/sql/item_sum.cc 2010-03-28 18:10:00 +0000
@@ -642,7 +642,7 @@ Item_sum_hybrid::fix_fields(THD *thd, It
default:
DBUG_ASSERT(0);
};
- setup(args[0], NULL);
+ setup_item(args[0], NULL);
/* MIN/MAX can return NULL for empty set indepedent of the used column */
maybe_null= 1;
unsigned_flag=item->unsigned_flag;
@@ -676,7 +676,7 @@ Item_sum_hybrid::fix_fields(THD *thd, It
of the original MIN/MAX object and it is saved in this object's cache.
*/
-void Item_sum_hybrid::setup(Item *item, Item *value_arg)
+void Item_sum_hybrid::setup_item(Item *item, Item *value_arg)
{
value= Item_cache::get_cache(item);
value->setup(item);
@@ -1646,7 +1646,7 @@ void Item_sum_hybrid::no_rows_in_result(
Item *Item_sum_min::copy_or_same(THD* thd)
{
Item_sum_min *item= new (thd->mem_root) Item_sum_min(thd, this);
- item->setup(args[0], value);
+ item->setup_item(args[0], value);
return item;
}
@@ -1669,7 +1669,7 @@ bool Item_sum_min::add()
Item *Item_sum_max::copy_or_same(THD* thd)
{
Item_sum_max *item= new (thd->mem_root) Item_sum_max(thd, this);
- item->setup(args[0], value);
+ item->setup_item(args[0], value);
return item;
}
=== modified file 'sql/item_sum.h'
--- a/sql/item_sum.h 2010-02-01 06:14:12 +0000
+++ b/sql/item_sum.h 2010-04-01 09:04:26 +0000
@@ -870,7 +870,7 @@ protected:
was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
- void setup(Item *item, Item *value_arg);
+ void setup_item(Item *item, Item *value_arg);
void clear();
double val_real();
longlong val_int();
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-03-15 11:51:23 +0000
+++ b/sql/log.cc 2010-04-01 14:34:51 +0000
@@ -5424,7 +5424,7 @@ int TC_LOG_MMAP::open(const char *opt_na
pg->state=POOL;
pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST);
pthread_cond_init (&pg->cond, 0);
- pg->start=(my_xid *)(data + i*tc_log_page_size);
+ pg->ptr= pg->start=(my_xid *)(data + i*tc_log_page_size);
pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
pg->end=pg->start + pg->size;
}
@@ -5659,7 +5659,15 @@ int TC_LOG_MMAP::sync()
/* marking 'syncing' slot free */
pthread_mutex_lock(&LOCK_sync);
syncing=0;
- pthread_cond_signal(&active->cond); // wake up a new syncer
+ /*
+ we check the "active" pointer without LOCK_active. Still, it's safe -
+ "active" can change from NULL to not NULL any time, but it
+ will take LOCK_sync before waiting on active->cond. That is, it can never
+ miss a signal.
+ And "active" can change to NULL only after LOCK_sync, so this is safe too.
+ */
+ if (active)
+ pthread_cond_signal(&active->cond); // wake up a new syncer
pthread_mutex_unlock(&LOCK_sync);
return err;
}
@@ -6028,3 +6036,20 @@ mysql_declare_plugin(binlog)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_storage_engine,
+ "binlog",
+ "MySQL AB",
+ "This is a pseudo storage engine to represent the binlog in a transaction",
+ PLUGIN_LICENSE_GPL,
+ binlog_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2010-03-15 11:51:23 +0000
+++ b/sql/log_event.cc 2010-04-02 09:20:09 +0000
@@ -1716,8 +1716,7 @@ beg:
case MYSQL_TYPE_DATETIME:
{
- size_t d, t;
- uint64 i64= uint8korr(ptr); /* YYYYMMDDhhmmss */
+ uint64 d, t, i64= uint8korr(ptr); /* YYYYMMDDhhmmss */
d= i64 / 1000000;
t= i64 % 1000000;
my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-31 23:10:03 +0000
+++ b/sql/mysqld.cc 2010-04-03 20:19:35 +0000
@@ -6646,8 +6646,6 @@ Can't be set to 1 if --log-slave-updates
{"shared-memory", OPT_ENABLE_SHARED_MEMORY,
"Enable the shared memory.",(uchar**) &opt_enable_shared_memory, (uchar**) &opt_enable_shared_memory,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
-#ifdef HAVE_SMEM
{"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME,
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -8378,6 +8376,8 @@ mysqld_get_one_option(int optid,
case (int) OPT_INIT_RPL_ROLE:
{
int role;
+ LINT_INIT(role);
+
if (!find_opt_type(argument, &rpl_role_typelib, opt->name, &role))
{
rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
@@ -8434,6 +8434,8 @@ mysqld_get_one_option(int optid,
case OPT_BINLOG_FORMAT:
{
int id;
+ LINT_INIT(id);
+
if (!find_opt_type(argument, &binlog_format_typelib, opt->name, &id))
{
global_system_variables.binlog_format= opt_binlog_format_id= id - 1;
@@ -8684,6 +8686,8 @@ mysqld_get_one_option(int optid,
else
{
int type;
+ LINT_INIT(type);
+
if (!find_opt_type(argument, &delay_key_write_typelib, opt->name, &type))
delay_key_write_options= (uint) type-1;
}
@@ -8695,6 +8699,8 @@ mysqld_get_one_option(int optid,
case OPT_TX_ISOLATION:
{
int type;
+ LINT_INIT(type);
+
if (!find_opt_type(argument, &tx_isolation_typelib, opt->name, &type))
global_system_variables.tx_isolation= (type-1);
break;
@@ -8782,6 +8788,7 @@ mysqld_get_one_option(int optid,
ulong method_conv;
int method;
LINT_INIT(method_conv);
+ LINT_INIT(method);
myisam_stats_method_str= argument;
if (!find_opt_type(argument, &myisam_stats_method_typelib,
@@ -8844,6 +8851,7 @@ mysqld_get_one_option(int optid,
case OPT_THREAD_HANDLING:
{
int id;
+ LINT_INIT(id);
if (!find_opt_type(argument, &thread_handling_typelib, opt->name, &id))
global_system_variables.thread_handling= id - 1;
opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling];
=== modified file 'sql/net_serv.cc'
--- a/sql/net_serv.cc 2010-02-23 12:04:58 +0000
+++ b/sql/net_serv.cc 2010-03-29 19:07:45 +0000
@@ -279,7 +279,7 @@ static int net_data_is_ready(my_socket s
@param clear_buffer if <> 0, then clear all data from comm buff
*/
-void net_clear(NET *net, my_bool clear_buffer)
+void net_clear(NET *net, my_bool clear_buffer __attribute__((unused)))
{
#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)
size_t count;
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-03-29 21:16:12 +0000
+++ b/sql/set_var.cc 2010-04-03 20:19:35 +0000
@@ -1269,16 +1269,16 @@ uchar *sys_var_set::value_ptr(THD *thd,
void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type)
{
- slave_exec_mode_options= 0;
- bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
+ slave_exec_mode_options= (ULL(1) << SLAVE_EXEC_MODE_STRICT);
}
bool sys_var_set_slave_mode::check(THD *thd, set_var *var)
{
bool rc= sys_var_set::check(thd, var);
if (!rc &&
- bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_STRICT) == 1 &&
- bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
+ test_all_bits(var->save_result.ulong_value,
+ ((ULL(1) << SLAVE_EXEC_MODE_STRICT) |
+ (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))))
{
rc= true;
my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), "");
@@ -1300,15 +1300,16 @@ void fix_slave_exec_mode(enum_var_type t
DBUG_ENTER("fix_slave_exec_mode");
compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT
> SLAVE_EXEC_MODE_LAST_BIT - 1);
- if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT) == 1 &&
- bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
+ if (test_all_bits(slave_exec_mode_options,
+ ((ULL(1) << SLAVE_EXEC_MODE_STRICT) |
+ (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))))
{
sql_print_error("Ambiguous slave modes combination."
" STRICT will be used");
- bit_do_clear(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT);
+ slave_exec_mode_options&= ~(ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT);
}
- if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 0)
- bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
+ if (!(slave_exec_mode_options & (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT)))
+ slave_exec_mode_options|= (ULL(1)<< SLAVE_EXEC_MODE_STRICT);
DBUG_VOID_RETURN;
}
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp_head.cc 2010-04-01 09:04:26 +0000
@@ -2089,6 +2089,8 @@ sp_head::reset_lex(THD *thd)
sublex->dec= NULL;
sublex->interval_list.empty();
sublex->type= 0;
+ sublex->uint_geom_type= 0;
+ sublex->vcol_info= 0;
DBUG_RETURN(FALSE);
}
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-31 18:37:45 +0000
+++ b/sql/sql_acl.cc 2010-04-02 20:08:40 +0000
@@ -536,6 +536,9 @@ static my_bool acl_load(THD *thd, TABLE_
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
+ char *password;
+ uint password_len;
+
bzero(&user, sizeof(user));
update_hostname(&user.host, get_field(&mem, table->field[0]));
user.user= get_field(&mem, table->field[1]);
@@ -548,8 +551,8 @@ static my_bool acl_load(THD *thd, TABLE_
continue;
}
- char *password= get_field(thd->mem_root, table->field[2]);
- uint password_len= password ? strlen(password) : 0;
+ password= get_field(&mem, table->field[2]);
+ password_len= password ? strlen(password) : 0;
user.auth_string.str= password ? password : const_cast<char*>("");
user.auth_string.length= password_len;
set_user_salt(&user, password, password_len);
@@ -6846,6 +6849,7 @@ bool check_routine_level_acl(THD *thd, c
#define initialized 0
#define decrease_user_connections(X) /* nothing */
#define check_for_max_user_connections(X,Y) 0
+#define get_or_create_user_conn(A,B,C,D) 0
#endif
#endif
#ifndef HAVE_OPENSSL
@@ -7826,15 +7830,15 @@ static int do_auth_once(THD *thd, LEX_ST
bool unlock_plugin= false;
plugin_ref plugin;
+#ifdef EMBEDDED_LIBRARY
+ plugin= native_password_plugin;
+#else
if (auth_plugin_name->str == native_password_plugin_name.str)
plugin= native_password_plugin;
- else
-#ifndef EMBEDDED_LIBRARY
- if (auth_plugin_name->str == old_password_plugin_name.str)
+ else if (auth_plugin_name->str == old_password_plugin_name.str)
plugin= old_password_plugin;
- else
- if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
- MYSQL_AUTHENTICATION_PLUGIN)))
+ else if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
+ MYSQL_AUTHENTICATION_PLUGIN)))
unlock_plugin= true;
#endif
@@ -8257,3 +8261,35 @@ mysql_declare_plugin(mysql_password)
}
mysql_declare_plugin_end;
+maria_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_builtin.cc.in'
--- a/sql/sql_builtin.cc.in 2010-03-29 15:13:53 +0000
+++ b/sql/sql_builtin.cc.in 2010-04-01 14:34:51 +0000
@@ -16,13 +16,12 @@
#include <my_global.h>
#include <mysql/plugin.h>
-typedef struct st_mysql_plugin builtin_plugin[];
+typedef struct st_maria_plugin builtin_maria_plugin[];
-extern builtin_plugin
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@;
+extern builtin_maria_plugin
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@;
-struct st_mysql_plugin *mysqld_builtins[]=
+struct st_maria_plugin *mariadb_builtins[]=
{
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@,(struct st_maria_plugin *)0
};
-
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_class.cc 2010-04-02 18:51:02 +0000
@@ -924,7 +924,7 @@ void THD::update_stats(void)
/* A SQL query. */
if (lex->sql_command == SQLCOM_SELECT)
select_commands++;
- else if (! sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
+ else if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
{
/* Ignore 'SHOW ' commands */
}
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-29 15:13:53 +0000
+++ b/sql/sql_class.h 2010-04-01 09:04:26 +0000
@@ -63,6 +63,7 @@ public:
bool report_error(THD *thd);
bool is_invalidated() const { return m_invalidated; }
void reset_reprepare_observer() { m_invalidated= FALSE; }
+ Reprepare_observer() {} /* Remove gcc warning */
private:
bool m_invalidated;
};
@@ -1117,6 +1118,7 @@ public:
/* Ignore error */
return TRUE;
}
+ Dummy_error_handler() {} /* Remove gcc warning */
};
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_plugin.cc 2010-04-01 20:05:09 +0000
@@ -20,7 +20,7 @@
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
-extern struct st_mysql_plugin *mysqld_builtins[];
+extern struct st_maria_plugin *mariadb_builtins[];
/**
@note The order of the enumeration is critical.
@@ -78,6 +78,14 @@ static const char *sizeof_st_plugin_sym=
"_mysql_sizeof_struct_st_plugin_";
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
static int min_plugin_interface_version= MYSQL_PLUGIN_INTERFACE_VERSION & ~0xFF;
+static const char *maria_plugin_interface_version_sym=
+ "_maria_plugin_interface_version_";
+static const char *maria_sizeof_st_plugin_sym=
+ "_maria_sizeof_struct_st_plugin_";
+static const char *maria_plugin_declarations_sym=
+ "_maria_plugin_declarations_";
+static int min_maria_plugin_interface_version=
+ MARIA_PLUGIN_INTERFACE_VERSION & ~0xFF;
#endif
/* Note that 'int version' must be the first field of every plugin
@@ -211,7 +219,7 @@ static bool plugin_load_list(MEM_ROOT *t
const char *list);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
int *, char **);
-static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
+static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(THD *thd, struct system_variables *vars);
@@ -368,6 +376,225 @@ static inline void free_plugin_mem(struc
}
+/**
+ Reads data from mysql plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report What errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+#ifdef HAVE_DLOPEN
+static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+ /* Determine interface version */
+ if (!sym)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= 0;
+ plugin_dl->mysqlversion= *(int *)sym;
+ /* Versioning */
+ if (plugin_dl->mysqlversion < min_plugin_interface_version ||
+ (plugin_dl->mysqlversion >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ /* convert mysql declaration to maria one */
+ {
+ int i;
+ uint sizeof_st_plugin;
+ struct st_mysql_plugin *old;
+ struct st_maria_plugin *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ DBUG_ASSERT(min_plugin_interface_version == 0);
+ sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
+ }
+
+ for (i= 0;
+ ((struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ {
+
+ cur->type= old->type;
+ cur->info= old->info;
+ cur->name= old->name;
+ cur->author= old->author;
+ cur->descr= old->descr;
+ cur->license= old->license;
+ cur->init= old->init;
+ cur->deinit= old->deinit;
+ cur->version= old->version;
+ cur->status_vars= old->status_vars;
+ cur->system_vars= old->system_vars;
+ /*
+ Something like this should be added to process
+ new mysql plugin versions:
+ if (plugin_dl->mysqlversion > 0x0101)
+ {
+ cur->newfield= CONSTANT_MEANS_UNKNOWN;
+ }
+ else
+ {
+ cur->newfield= old->newfield;
+ }
+ */
+ /* Maria only fields */
+ cur->version_info= "Unknown";
+ cur->maturity= MariaDB_PLUGIN_MATURITY_UNKNOWN;
+ }
+ plugin_dl->allocated= true;
+ plugin_dl->plugins= (struct st_maria_plugin *)cur;
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Reads data from maria plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report what errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+
+ /* Determine interface version */
+ if (!(sym))
+ {
+ /*
+ Actually this branch impossible because in case of absence of maria
+ version we try mysql version.
+ */
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY,
+ maria_plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= *(int *)sym;
+ plugin_dl->mysqlversion= 0;
+ /* Versioning */
+ if (plugin_dl->mariaversion < min_maria_plugin_interface_version ||
+ (plugin_dl->mariaversion >> 8) > (MARIA_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, maria_plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+ if (plugin_dl->mariaversion != MARIA_PLUGIN_INTERFACE_VERSION)
+ {
+ uint sizeof_st_plugin;
+ struct st_maria_plugin *old, *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, maria_sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_sizeof_st_plugin_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (sizeof_st_plugin != sizeof(st_mysql_plugin))
+ {
+ int i;
+ for (i= 0;
+ ((struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ memcpy(cur + i, old, min(sizeof(cur[i]), sizeof_st_plugin));
+
+ sym= cur;
+ plugin_dl->allocated= true;
+ }
+ }
+ plugin_dl->plugins= (struct st_maria_plugin *)sym;
+
+ DBUG_RETURN(FALSE);
+}
+#endif HAVE_DLOPEN
+
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
#ifdef HAVE_DLOPEN
@@ -415,22 +642,21 @@ static st_plugin_dl *plugin_dl_add(const
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
DBUG_RETURN(0);
}
- /* Determine interface version */
- if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
+
+ /* Checks which plugin interface present and reads info */
+ if (!(sym= dlsym(plugin_dl.handle, maria_plugin_interface_version_sym)))
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
- DBUG_RETURN(0);
+ if (read_mysql_plugin_info(&plugin_dl,
+ dlsym(plugin_dl.handle,
+ plugin_interface_version_sym),
+ dlpath,
+ report))
+ DBUG_RETURN(0);
}
- plugin_dl.version= *(int *)sym;
- /* Versioning */
- if (plugin_dl.version < min_plugin_interface_version ||
- (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ else
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
- "plugin interface version mismatch");
- DBUG_RETURN(0);
+ if (read_maria_plugin_info(&plugin_dl, sym, dlpath, report))
+ DBUG_RETURN(0);
}
/* link the services in */
@@ -438,7 +664,7 @@ static st_plugin_dl *plugin_dl_add(const
{
if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
{
- uint ver= (uint)(intptr)*(void**)sym;
+ uint ver= (uint)(intptr) *(void **)sym;
if (ver > list_of_services[i].version ||
(ver >> 8) < (list_of_services[i].version >> 8))
{
@@ -449,72 +675,9 @@ static st_plugin_dl *plugin_dl_add(const
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
DBUG_RETURN(0);
}
- *(void**)sym= list_of_services[i].service;
- }
- }
-
- /* Find plugin declarations */
- if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
- DBUG_RETURN(0);
- }
-
- if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
- {
- uint sizeof_st_plugin;
- struct st_mysql_plugin *old, *cur;
- char *ptr= (char *)sym;
-
- if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
- sizeof_st_plugin= *(int *)sym;
- else
- {
-#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
- DBUG_RETURN(0);
-#else
- /*
- When the following assert starts failing, we'll have to switch
- to the upper branch of the #ifdef
- */
- DBUG_ASSERT(min_plugin_interface_version == 0);
- sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
-#endif
- }
-
- if (sizeof_st_plugin != sizeof(st_mysql_plugin))
- {
- for (i= 0;
- ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- /* no op */;
-
- cur= (struct st_mysql_plugin*)
- my_malloc((i+1)*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
- if (!cur)
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
- DBUG_RETURN(0);
- }
- /*
- All st_plugin fields not initialized in the plugin explicitly, are
- set to 0. It matches C standard behaviour for struct initializers that
- have less values than the struct definition.
- */
- for (i=0;
- (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
-
- sym= cur;
- plugin_dl.allocated= true;
+ *(void **)sym= list_of_services[i].service;
}
}
- plugin_dl.plugins= (struct st_mysql_plugin *)sym;
/* Duplicate and convert dll name */
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
@@ -756,7 +919,7 @@ static bool plugin_add(MEM_ROOT *tmp_roo
int *argc, char **argv, int report)
{
struct st_plugin_int tmp;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
DBUG_ENTER("plugin_add");
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
{
@@ -1161,8 +1324,8 @@ int plugin_init(int *argc, char **argv,
{
uint i;
bool is_myisam;
- struct st_mysql_plugin **builtins;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin **builtins;
+ struct st_maria_plugin *plugin;
struct st_plugin_int tmp, *plugin_ptr, **reap;
MEM_ROOT tmp_root;
bool reaped_mandatory_plugin= FALSE;
@@ -1201,7 +1364,7 @@ int plugin_init(int *argc, char **argv,
/*
First we register builtin plugins
*/
- for (builtins= mysqld_builtins; *builtins; builtins++)
+ for (builtins= mariadb_builtins; *builtins; builtins++)
{
for (plugin= *builtins; plugin->info; plugin++)
{
@@ -1316,7 +1479,7 @@ err:
}
-static bool register_builtin(struct st_mysql_plugin *plugin,
+static bool register_builtin(struct st_maria_plugin *plugin,
struct st_plugin_int *tmp,
struct st_plugin_int **ptr)
{
@@ -1352,7 +1515,7 @@ static bool register_builtin(struct st_m
RETURN
false - plugin registered successfully
*/
-bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
+bool plugin_register_builtin(THD *thd, struct st_maria_plugin *plugin)
{
struct st_plugin_int tmp, *ptr;
bool result= true;
@@ -1481,7 +1644,7 @@ static bool plugin_load_list(MEM_ROOT *t
char buffer[FN_REFLEN];
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
struct st_plugin_dl *plugin_dl;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
char *p= buffer;
DBUG_ENTER("plugin_load_list");
while (list)
=== modified file 'sql/sql_plugin.h'
--- a/sql/sql_plugin.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_plugin.h 2010-04-01 14:34:51 +0000
@@ -52,8 +52,9 @@ struct st_plugin_dl
{
LEX_STRING dl;
void *handle;
- struct st_mysql_plugin *plugins;
- int version;
+ struct st_maria_plugin *plugins;
+ int mysqlversion;
+ int mariaversion;
bool allocated;
uint ref_count; /* number of plugins loaded from the library */
};
@@ -63,7 +64,7 @@ struct st_plugin_dl
struct st_plugin_int
{
LEX_STRING name;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
struct st_plugin_dl *plugin_dl;
uint state;
uint ref_count; /* number of threads using the plugin */
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-04-01 21:42:40 +0000
+++ b/sql/sql_show.cc 2010-04-03 20:19:35 +0000
@@ -94,11 +94,21 @@ static int make_version_string(char *buf
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
}
+
+static const LEX_STRING maturity_name[]={
+ { C_STRING_WITH_LEN("Unknown") },
+ { C_STRING_WITH_LEN("Experimental") },
+ { C_STRING_WITH_LEN("Alpha") },
+ { C_STRING_WITH_LEN("Beta") },
+ { C_STRING_WITH_LEN("Gamma") },
+ { C_STRING_WITH_LEN("Stable") }};
+
+
static my_bool show_plugins(THD *thd, plugin_ref plugin,
void *arg)
{
TABLE *table= (TABLE*) arg;
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
CHARSET_INFO *cs= system_charset_info;
char version_buf[20];
@@ -143,7 +153,7 @@ static my_bool show_plugins(THD *thd, pl
table->field[5]->set_notnull();
table->field[6]->store(version_buf,
make_version_string(version_buf, sizeof(version_buf),
- plugin_dl->version),
+ plugin_dl->mariaversion),
cs);
table->field[6]->set_notnull();
}
@@ -186,6 +196,26 @@ static my_bool show_plugins(THD *thd, pl
}
table->field[9]->set_notnull();
+ if ((uint) plug->maturity <= MariaDB_PLUGIN_MATURITY_STABLE)
+ table->field[10]->store(maturity_name[plug->maturity].str,
+ maturity_name[plug->maturity].length,
+ cs);
+ else
+ {
+ DBUG_ASSERT(0);
+ table->field[10]->store("Unknown", 7, cs);
+ }
+ table->field[10]->set_notnull();
+
+ if (plug->version_info)
+ {
+ table->field[11]->store(plug->version_info,
+ strlen(plug->version_info), cs);
+ table->field[11]->set_notnull();
+ }
+ else
+ table->field[11]->set_null();
+
return schema_table_store_record(thd, table);
}
@@ -2527,8 +2557,8 @@ int send_user_stats(THD* thd, HASH *all_
table->field[j++]->store(user_stats->user, user_stats->user_name_length,
system_charset_info);
table->field[j++]->store((longlong)user_stats->total_connections,TRUE);
- table->field[j++]->store((longlong)user_stats->concurrent_connections);
- table->field[j++]->store((longlong)user_stats->connected_time);
+ table->field[j++]->store((longlong)user_stats->concurrent_connections, TRUE);
+ table->field[j++]->store((longlong)user_stats->connected_time, TRUE);
table->field[j++]->store((double)user_stats->busy_time);
table->field[j++]->store((double)user_stats->cpu_time);
table->field[j++]->store((longlong)user_stats->bytes_received, TRUE);
@@ -4426,7 +4456,7 @@ static my_bool iter_schema_engines(THD *
if (plugin_state(plugin) != PLUGIN_IS_READY)
{
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
if (!(wild && wild[0] &&
wild_case_compare(scs, plug->name,wild)))
{
@@ -7207,6 +7237,8 @@ ST_FIELD_INFO plugin_fields_info[]=
{"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
+ {"PLUGIN_MATURITY", 12, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
+ {"PLUGIN_AUTH_VERSION", 80, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_table.cc 2010-04-01 09:04:26 +0000
@@ -5704,6 +5704,10 @@ compare_tables(TABLE *table,
*/
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */
+
+ /* Set default value for return value (to ensure it's always set) */
+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
+
/* Create the prepared information. */
if (mysql_prepare_create_table(thd, create_info,
&tmp_alter_info,
@@ -5762,7 +5766,6 @@ compare_tables(TABLE *table,
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
{
DBUG_PRINT("info", ("Basic checks -> ALTER_TABLE_DATA_CHANGED"));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
@@ -5792,7 +5795,6 @@ compare_tables(TABLE *table,
{
DBUG_PRINT("info", ("NULL behaviour difference in field '%s' -> "
"ALTER_TABLE_DATA_CHANGED", new_field->field_name));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
@@ -5828,7 +5830,6 @@ compare_tables(TABLE *table,
{
DBUG_PRINT("info", ("!field_is_equal('%s') -> ALTER_TABLE_DATA_CHANGED",
new_field->field_name));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
// Clear indexed marker
@@ -5963,7 +5964,6 @@ compare_tables(TABLE *table,
{
DBUG_PRINT("info", ("check_if_incompatible_data() -> "
"ALTER_TABLE_DATA_CHANGED"));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2010-03-04 08:03:07 +0000
+++ b/sql/sql_view.cc 2010-03-30 12:36:49 +0000
@@ -1034,10 +1034,12 @@ bool mysql_make_view(THD *thd, File_pars
bool parse_status;
bool result, view_is_mergeable;
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));
+ LINT_INIT(parse_status);
+ LINT_INIT(view_select);
+
if (table->view)
{
/*
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-03-29 15:13:53 +0000
+++ b/sql/sql_yacc.yy 2010-04-01 09:04:26 +0000
@@ -2342,6 +2342,7 @@ sp_init_param:
lex->interval_list.empty();
lex->uint_geom_type= 0;
+ lex->vcol_info= 0;
}
;
@@ -8190,7 +8191,7 @@ function_call_generic:
builder= find_qualified_function_builder(thd);
DBUG_ASSERT(builder);
- item= builder->create(thd, $1, $3, true, $5);
+ item= builder->create_with_db(thd, $1, $3, true, $5);
if (! ($$= item))
{
=== modified file 'storage/archive/ha_archive.cc'
--- a/storage/archive/ha_archive.cc 2010-03-04 08:03:07 +0000
+++ b/storage/archive/ha_archive.cc 2010-04-01 14:34:51 +0000
@@ -1655,4 +1655,21 @@ mysql_declare_plugin(archive)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_storage_engine,
+ "ARCHIVE",
+ "Brian Aker, MySQL AB",
+ "Archive storage engine",
+ PLUGIN_LICENSE_GPL,
+ archive_db_init, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0300 /* 3.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/blackhole/ha_blackhole.cc'
--- a/storage/blackhole/ha_blackhole.cc 2009-10-16 10:29:42 +0000
+++ b/storage/blackhole/ha_blackhole.cc 2010-04-01 14:34:51 +0000
@@ -369,3 +369,20 @@ mysql_declare_plugin(blackhole)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_storage_engine,
+ "BLACKHOLE",
+ "MySQL AB",
+ "/dev/null storage engine (anything you write to it disappears)",
+ PLUGIN_LICENSE_GPL,
+ blackhole_init, /* Plugin Init */
+ blackhole_fini, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/csv/ha_tina.cc'
--- a/storage/csv/ha_tina.cc 2009-12-03 11:19:05 +0000
+++ b/storage/csv/ha_tina.cc 2010-04-01 14:34:51 +0000
@@ -1636,4 +1636,20 @@ mysql_declare_plugin(csv)
NULL /* config options */
}
mysql_declare_plugin_end;
-
+maria_declare_plugin(csv)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &csv_storage_engine,
+ "CSV",
+ "Brian Aker, MySQL AB",
+ "CSV storage engine",
+ PLUGIN_LICENSE_GPL,
+ tina_init_func, /* Plugin Init */
+ tina_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc 2010-04-01 14:34:51 +0000
@@ -924,3 +924,20 @@ mysql_declare_plugin(example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(example)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &example_storage_engine,
+ "EXAMPLE",
+ "Brian Aker, MySQL AB",
+ "Example storage engine",
+ PLUGIN_LICENSE_GPL,
+ example_init_func, /* Plugin Init */
+ example_done_func, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ func_status, /* status variables */
+ example_system_variables, /* system variables */
+ "0.1", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/example/ha_example.h'
--- a/storage/example/ha_example.h 2007-08-13 13:11:25 +0000
+++ b/storage/example/ha_example.h 2010-03-28 18:10:00 +0000
@@ -155,7 +155,8 @@ public:
/** @brief
This method will never be called if you do not implement indexes.
*/
- virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
+ virtual double read_time(uint index, uint ranges, ha_rows rows)
+ { return (double) rows / 20.0+1; }
/*
Everything below are methods that we implement in ha_example.cc.
=== modified file 'storage/federated/ha_federated.cc'
--- a/storage/federated/ha_federated.cc 2009-09-07 20:50:10 +0000
+++ b/storage/federated/ha_federated.cc 2010-04-01 14:34:51 +0000
@@ -3379,3 +3379,20 @@ mysql_declare_plugin(federated)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ "Federated MySQL storage engine",
+ PLUGIN_LICENSE_GPL,
+ federated_db_init, /* Plugin Init */
+ federated_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 2010-03-10 10:32:14 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2010-04-01 14:34:51 +0000
@@ -3505,9 +3505,26 @@ mysql_declare_plugin(federated)
PLUGIN_LICENSE_GPL,
federatedx_db_init, /* Plugin Init */
federatedx_done, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
+ 0x0200 /* 2.0 */,
NULL, /* status variables */
NULL, /* system variables */
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_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 */
+ 0x0200 /* 2.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "2.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/heap/ha_heap.cc'
--- a/storage/heap/ha_heap.cc 2009-09-07 20:50:10 +0000
+++ b/storage/heap/ha_heap.cc 2010-04-01 14:34:51 +0000
@@ -767,3 +767,20 @@ mysql_declare_plugin(heap)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_storage_engine,
+ "MEMORY",
+ "MySQL AB",
+ "Hash based, stored in memory, useful for temporary tables",
+ PLUGIN_LICENSE_GPL,
+ heap_init,
+ NULL,
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/ibmdb2i/ha_ibmdb2i.cc'
--- a/storage/ibmdb2i/ha_ibmdb2i.cc 2009-12-11 07:01:16 +0000
+++ b/storage/ibmdb2i/ha_ibmdb2i.cc 2010-04-01 14:34:51 +0000
@@ -3357,3 +3357,20 @@ mysql_declare_plugin(ibmdb2i)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ibmdb2i)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ibmdb2i_storage_engine,
+ "IBMDB2I",
+ "The IBM development team in Rochester, Minnesota",
+ "IBM DB2 for i Storage Engine",
+ PLUGIN_LICENSE_GPL,
+ ibmdb2i_init_func, /* Plugin Init */
+ ibmdb2i_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ ibmdb2i_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_UNKNOWN /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2010-03-15 11:51:23 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2010-04-01 14:34:51 +0000
@@ -8930,6 +8930,23 @@ mysql_declare_plugin(innobase)
NULL /* reserved */
}
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase OY",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ innodb_status_variables_export, /* status variables */
+ innobase_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE, /* maturity */
+}
+maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/innodb_plugin/handler/i_s.cc'
--- a/storage/innodb_plugin/handler/i_s.cc 2009-10-12 12:00:56 +0000
+++ b/storage/innodb_plugin/handler/i_s.cc 2010-04-01 14:34:51 +0000
@@ -455,6 +455,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -730,6 +783,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -913,6 +1019,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -1245,6 +1404,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1295,6 +1507,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -1511,6 +1777,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1561,6 +1880,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ha_maria.cc 2010-04-01 14:34:51 +0000
@@ -3471,9 +3471,26 @@ mysql_declare_plugin(maria)
PLUGIN_LICENSE_GPL,
ha_maria_init, /* Plugin Init */
NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
+ 0x0105, /* 1.5 */
status_variables, /* status variables */
system_variables, /* system variables */
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(maria)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &maria_storage_engine,
+ "MARIA",
+ "MySQL AB",
+ "Crash-safe tables with MyISAM heritage",
+ PLUGIN_LICENSE_GPL,
+ ha_maria_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0105, /* 1.5 */
+ status_variables, /* status variables */
+ system_variables, /* system variables */
+ "1.5", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-03-30 12:35:15 +0000
+++ b/storage/maria/ma_loghandler.c 2010-04-02 09:20:09 +0000
@@ -1275,7 +1275,10 @@ static my_bool translog_set_lsn_for_file
{
LOGHANDLER_FILE_INFO info;
File fd= open_logfile_by_number_no_cache(file);
+
LINT_INIT_STRUCT(info);
+ LINT_INIT(info.max_lsn);
+
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
@@ -3968,6 +3971,7 @@ my_bool translog_init_with_table(const c
{
LOGHANDLER_FILE_INFO info;
LINT_INIT_STRUCT(info);
+
/*
Accessing &log_descriptor.open_files without mutex is safe
because it is initialization
=== modified file 'storage/maria/ma_search.c'
--- a/storage/maria/ma_search.c 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ma_search.c 2010-04-01 09:04:26 +0000
@@ -76,8 +76,8 @@ int _ma_search(register MARIA_HA *info,
bmove512(info->keyread_buff, page_buff, info->s->block_size);
/* Save position for a possible read next / previous */
- info->int_keypos= info->keyread_buff + (ulonglong) info->int_keypos;
- info->int_maxpos= info->keyread_buff + (ulonglong) info->int_maxpos;
+ info->int_keypos= info->keyread_buff + info->keypos_offset;
+ info->int_maxpos= info->keyread_buff + info->maxpos_offset;
info->int_keytree_version= key->keyinfo->version;
info->last_search_keypage= info->last_keypage;
info->page_changed= 0;
@@ -214,8 +214,8 @@ static int _ma_search_no_save(register M
info->cur_row.trid= _ma_trid_from_key(&info->last_key);
/* Store offset to key */
- info->int_keypos= (uchar*) (keypos - page.buff);
- info->int_maxpos= (uchar*) (maxpos - page.buff);
+ info->keypos_offset= (uint) (keypos - page.buff);
+ info->maxpos_offset= (uint) (maxpos - page.buff);
info->int_nod_flag= nod_flag;
info->last_keypage= pos;
*res_page_link= page_link;
=== modified file 'storage/maria/maria_def.h'
--- a/storage/maria/maria_def.h 2010-03-09 19:22:24 +0000
+++ b/storage/maria/maria_def.h 2010-03-28 18:10:00 +0000
@@ -506,8 +506,10 @@ struct st_maria_handler
uchar *first_mbr_key; /* Searhed spatial key */
uchar *rec_buff; /* Temp buffer for recordpack */
uchar *blob_buff; /* Temp buffer for blobs */
- uchar *int_keypos, /* Save position for next/previous */
- *int_maxpos; /* -""- */
+ uchar *int_keypos; /* Save position for next/previous */
+ uchar *int_maxpos; /* -""- */
+ uint keypos_offset; /* Tmp storage for offset int_keypos */
+ uint maxpos_offset; /* Tmp storage for offset int_maxpos */
uchar *update_field_data; /* Used by update in rows-in-block */
uint int_nod_flag; /* -""- */
uint32 int_keytree_version; /* -""- */
=== modified file 'storage/myisam/ft_stopwords.c'
--- a/storage/myisam/ft_stopwords.c 2010-03-10 10:32:14 +0000
+++ b/storage/myisam/ft_stopwords.c 2010-03-28 18:10:00 +0000
@@ -44,9 +44,10 @@ static void FT_STOPWORD_free(FT_STOPWORD
static int ft_add_stopword(const char *w)
{
FT_STOPWORD sw;
- return !w ||
- (((sw.len= (uint) strlen(sw.pos=(const uchar *)w)) >= ft_min_word_len) &&
- (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL));
+ return (!w ||
+ (((sw.len= (uint) strlen((char*) (sw.pos=(const uchar *)w))) >=
+ ft_min_word_len) &&
+ (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL)));
}
int ft_init_stopwords()
=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc 2010-01-04 17:54:42 +0000
+++ b/storage/myisam/ha_myisam.cc 2010-04-01 14:34:51 +0000
@@ -2174,6 +2174,23 @@ mysql_declare_plugin(myisam)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_storage_engine,
+ "MyISAM",
+ "MySQL AB",
+ "Default engine as of MySQL 3.23 with great performance",
+ PLUGIN_LICENSE_GPL,
+ myisam_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#ifdef HAVE_QUERY_CACHE
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2010-03-04 08:03:07 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2010-04-01 14:34:51 +0000
@@ -382,7 +382,7 @@ static MI_INFO *myisammrg_attach_childre
my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
}
DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx my_errno: %d",
- my_errno ? NULL : (long) myisam, my_errno));
+ my_errno ? 0L : (long) myisam, my_errno));
err:
DBUG_RETURN(my_errno ? NULL : myisam);
@@ -1289,3 +1289,20 @@ mysql_declare_plugin(myisammrg)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_storage_engine,
+ "MRG_MYISAM",
+ "MySQL AB",
+ "Collection of identical MyISAM tables",
+ PLUGIN_LICENSE_GPL,
+ myisammrg_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/myisammrg/myrg_open.c'
--- a/storage/myisammrg/myrg_open.c 2009-09-23 13:21:29 +0000
+++ b/storage/myisammrg/myrg_open.c 2010-03-30 12:36:49 +0000
@@ -239,6 +239,7 @@ MYRG_INFO *myrg_parent_open(const char *
rc= 1;
errpos= 0;
bzero((char*) &file_cache, sizeof(file_cache));
+ LINT_INIT(m_info);
/* Open MERGE meta file. */
if ((fd= my_open(fn_format(parent_name_buff, parent_name, "", MYRG_NAME_EXT,
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-31 18:37:45 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-04-01 14:34:51 +0000
@@ -5919,6 +5919,40 @@ mysql_declare_plugin(pbxt)
drizzle_declare_plugin_end;
#else
mysql_declare_plugin_end;
+#ifdef MARIADB_BASE_VERSION
+maria_declare_plugin(pbxt)
+{ /* PBXT */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &pbxt_storage_engine,
+ "PBXT",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "High performance, multi-versioning transactional engine",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init, /* Plugin Init */
+ pbxt_end, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ NULL, /* status variables */
+ pbxt_system_variables, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+},
+{ /* PBXT_STATISTICS */
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &pbxt_statitics,
+ "PBXT_STATISTICS",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "PBXT internal system statitics",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init_statistics, /* plugin init */
+ pbxt_exit_statistics, /* plugin deinit */
+ 0x0005,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
+#endif
#endif
#if defined(XT_WIN) && defined(XT_COREDUMP)
=== modified file 'storage/xtradb/handler/ha_innodb.cc'
--- a/storage/xtradb/handler/ha_innodb.cc 2010-02-01 06:14:12 +0000
+++ b/storage/xtradb/handler/ha_innodb.cc 2010-04-01 14:34:51 +0000
@@ -10818,6 +10818,39 @@ i_s_innodb_index_stats,
i_s_innodb_admin_command,
i_s_innodb_patches
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{ /* InnoDB */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase Oy",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ INNODB_VERSION_SHORT,
+ innodb_status_variables_export,/* status variables */
+ innobase_system_variables, /* system variables */
+ INNODB_VERSION_STR, /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+},
+i_s_innodb_rseg_maria,
+i_s_innodb_buffer_pool_pages_maria,
+i_s_innodb_buffer_pool_pages_index_maria,
+i_s_innodb_buffer_pool_pages_blob_maria,
+i_s_innodb_trx_maria,
+i_s_innodb_locks_maria,
+i_s_innodb_lock_waits_maria,
+i_s_innodb_cmp_maria,
+i_s_innodb_cmp_reset_maria,
+i_s_innodb_cmpmem_maria,
+i_s_innodb_cmpmem_reset_maria,
+i_s_innodb_table_stats_maria,
+i_s_innodb_index_stats_maria,
+i_s_innodb_admin_command_maria,
+i_s_innodb_patches_maria
+maria_declare_plugin_end;
+
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/xtradb/handler/i_s.cc'
--- a/storage/xtradb/handler/i_s.cc 2010-01-28 11:35:10 +0000
+++ b/storage/xtradb/handler/i_s.cc 2010-04-01 14:34:51 +0000
@@ -393,6 +393,59 @@ UNIV_INTERN struct st_mysql_plugin
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_patches_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "XTRADB_ENHANCEMENTS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Enhancements applied to InnoDB plugin"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_patches_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
{
@@ -1040,6 +1093,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1089,6 +1195,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1138,6 +1297,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
@@ -1373,6 +1585,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -1648,6 +1914,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -1831,6 +2150,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -2163,6 +2535,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2213,6 +2638,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -2431,6 +2909,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2481,6 +3012,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
@@ -2660,6 +3245,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_RSEG"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB rollback segment information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_rseg_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
@@ -2940,6 +3578,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
@@ -2956,6 +3611,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
@@ -2988,7 +3660,6 @@ i_s_innodb_admin_command_fill(
COND* cond)
{
TABLE* i_s_table = (TABLE *) tables->table;
- CHARSET_INFO *cs= system_charset_info;
char** query_str;
char* ptr;
char quote = '\0';
@@ -3122,3 +3793,20 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
=== modified file 'storage/xtradb/handler/i_s.h'
--- a/storage/xtradb/handler/i_s.h 2009-11-04 20:11:12 +0000
+++ b/storage/xtradb/handler/i_s.h 2010-04-01 14:34:51 +0000
@@ -42,4 +42,20 @@ extern struct st_mysql_plugin i_s_innodb
extern struct st_mysql_plugin i_s_innodb_index_stats;
extern struct st_mysql_plugin i_s_innodb_admin_command;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria;
+extern struct st_maria_plugin i_s_innodb_trx_maria;
+extern struct st_maria_plugin i_s_innodb_locks_maria;
+extern struct st_maria_plugin i_s_innodb_lock_waits_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_reset_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_reset_maria;
+extern struct st_maria_plugin i_s_innodb_patches_maria;
+extern struct st_maria_plugin i_s_innodb_rseg_maria;
+extern struct st_maria_plugin i_s_innodb_table_stats_maria;
+extern struct st_maria_plugin i_s_innodb_index_stats_maria;
+extern struct st_maria_plugin i_s_innodb_admin_command_maria;
+
#endif /* i_s_h */
=== modified file 'storage/xtradb/include/page0page.h'
--- a/storage/xtradb/include/page0page.h 2010-01-06 12:00:14 +0000
+++ b/storage/xtradb/include/page0page.h 2010-03-28 18:10:00 +0000
@@ -517,7 +517,7 @@ UNIV_INLINE
rec_t*
page_rec_get_next(
/*==============*/
- rec_t* rec); /*!< in: pointer to record */
+ const rec_t* rec); /*!< in: pointer to record */
/************************************************************//**
Gets the pointer to the next record on the page.
@return pointer to next record */
=== modified file 'storage/xtradb/include/page0page.ic'
--- a/storage/xtradb/include/page0page.ic 2010-01-06 12:00:14 +0000
+++ b/storage/xtradb/include/page0page.ic 2010-03-28 18:10:00 +0000
@@ -731,7 +731,7 @@ UNIV_INLINE
rec_t*
page_rec_get_next(
/*==============*/
- rec_t* rec) /*!< in: pointer to record */
+ const rec_t* rec) /*!< in: pointer to record */
{
return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec)));
}
=== modified file 'storage/xtradb/include/ut0lst.h'
--- a/storage/xtradb/include/ut0lst.h 2009-09-07 10:22:53 +0000
+++ b/storage/xtradb/include/ut0lst.h 2010-03-30 12:36:49 +0000
@@ -158,7 +158,7 @@ Inserts a NODE2 after NODE1 in a list.
/** Invalidate the pointers in a list node.
@param NAME list name
@param N pointer to the node that was removed */
-# define UT_LIST_REMOVE_CLEAR(NAME, N) while (0)
+# define UT_LIST_REMOVE_CLEAR(NAME, N) {} while (0)
#endif
/*******************************************************************//**
=== modified file 'storage/xtradb/log/log0recv.c'
--- a/storage/xtradb/log/log0recv.c 2010-01-15 15:58:25 +0000
+++ b/storage/xtradb/log/log0recv.c 2010-03-31 20:50:54 +0000
@@ -3280,7 +3280,6 @@ recv_recovery_from_checkpoint_finish(voi
#endif /* UNIV_DEBUG */
if (recv_needed_recovery && srv_recovery_stats) {
- FILE* file = stderr;
ulint i;
fprintf(stderr,
=== modified file 'strings/ctype-ucs2.c'
--- a/strings/ctype-ucs2.c 2010-03-15 11:51:23 +0000
+++ b/strings/ctype-ucs2.c 2010-04-01 09:04:26 +0000
@@ -203,7 +203,7 @@ static int my_strnncoll_ucs2(CHARSET_INF
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
@@ -317,7 +317,7 @@ static int my_strncasecmp_ucs2(CHARSET_I
const char *s, const char *t, size_t len)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const char *se=s+len;
const char *te=t+len;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
@@ -1384,7 +1384,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
=== modified file 'strings/ctype-utf8.c'
--- a/strings/ctype-utf8.c 2010-01-06 19:20:16 +0000
+++ b/strings/ctype-utf8.c 2010-04-01 09:04:26 +0000
@@ -2308,7 +2308,7 @@ static int my_strnncoll_utf8(CHARSET_INF
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc), t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
@@ -2378,7 +2378,7 @@ static int my_strnncollsp_utf8(CHARSET_I
my_bool diff_if_only_endspace_difference)
{
int s_res, t_res, res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se= s+slen, *te= t+tlen;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
=== modified file 'strings/my_vsnprintf.c'
--- a/strings/my_vsnprintf.c 2010-03-03 14:44:14 +0000
+++ b/strings/my_vsnprintf.c 2010-04-01 09:04:26 +0000
@@ -400,16 +400,18 @@ start:
case 's':
{
char *par= args_arr[print_arr[i].arg_idx].str_arg;
- width= (print_arr[i].flags & WIDTH_ARG) ?
- args_arr[print_arr[i].width].longlong_arg : print_arr[i].width;
+ width= ((print_arr[i].flags & WIDTH_ARG) ?
+ (uint) args_arr[print_arr[i].width].longlong_arg :
+ (uint) print_arr[i].width);
to= process_str_arg(cs, to, end, width, par, print_arr[i].flags);
break;
}
case 'b':
{
char *par = args_arr[print_arr[i].arg_idx].str_arg;
- width= (print_arr[i].flags & WIDTH_ARG) ?
- args_arr[print_arr[i].width].longlong_arg : print_arr[i].width;
+ width= ((print_arr[i].flags & WIDTH_ARG) ?
+ (uint) args_arr[print_arr[i].width].longlong_arg :
+ (uint) print_arr[i].width);
to= process_bin_arg(to, end, width, par);
break;
}
@@ -428,8 +430,9 @@ start:
{
/* Integer parameter */
longlong larg;
- length= (print_arr[i].flags & LENGTH_ARG) ?
- args_arr[print_arr[i].length].longlong_arg : print_arr[i].length;
+ length= ((print_arr[i].flags & LENGTH_ARG) ?
+ args_arr[print_arr[i].length].longlong_arg :
+ (longlong) print_arr[i].length);
if (args_arr[print_arr[i].arg_idx].have_longlong)
larg = args_arr[print_arr[i].arg_idx].longlong_arg;
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-03-10 10:32:14 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-01 09:40:11 +0000
@@ -27,7 +27,7 @@ pars0grm.tab.c: .*'yyerrorlab' : unrefer
_flex_tmp.c: .*not enough actual parameters for macro 'yywrap'.*
pars0lex.l: .*conversion from 'ulint' to 'int', possible loss of data.*
btr/btr0cur\.c: .*value computed is not used.*: 3175-3375
-include/buf0buf\.ic: unused parameter ‘mtr’
+include/buf0buf\.ic: unused parameter .*mtr.*
fil/fil0fil\.c: pointer targets in passing argument.*differ in signedness
fil/fil0fil\.c: comparison between signed and unsigned : 3100-3199
fil/fil0fil\.c: unused parameter
@@ -39,6 +39,7 @@ sync/sync0rw\.c: unused parameter
sync/sync0sync\.c: unused parameter
sync/sync0sync\.c: unused variable
ut/ut0ut\.c: ignoring return value of
+srv/srv0srv\.c: value computed is not used
#
# bdb is not critical to keep up to date
@@ -53,6 +54,12 @@ db_vrfy.c : .*comparison is always false
# readline is not maintained by us
#
.*/cmd-line-utils/readline/.* : .*
+readline\.c : unused parameter
+term\.c : unused parameter
+vi\.c : unused parameter
+common\.c : unused parameter
+term\.c : .*
+
#
# Ignore some warnings in libevent, which is not maintained by us.
@@ -66,6 +73,16 @@ db_vrfy.c : .*comparison is always false
/usr/share/aclocal/audiofile.m4 : .*
#
+# Ignore strict-aliasing warnings (for now)
+#
+.*: break strict-aliasing rules
+
+#
+# Ignore not important declaration warnings
+#
+.*: only defines private constructors and has no friends
+
+#
# Ignore all conversion warnings on windows 64
# (Is safe as we are not yet supporting strings >= 2G)
#
@@ -100,6 +117,11 @@ db_vrfy.c : .*comparison is always false
storage/maria/ma_pagecache.c: .*'info_check_pin' defined but not used
#
+# Pbxt
+#
+xaction_xt\.cc: may be used uninitialized in this function
+
+#
# I think these are due to mix of C and C++.
#
storage/pbxt/ : typedef.*was ignored in this declaration
@@ -112,6 +134,7 @@ include/runtime.hpp: .*pure_error.*
.*/extra/yassl/taocrypt/src/blowfish\.cpp: array subscript is above array bounds
.*/extra/yassl/taocrypt/src/file\.cpp: ignoring return value
.*/extra/yassl/taocrypt/src/integer\.cpp: control reaches end of non-void function
+mySTL/algorithm\.hpp: is used uninitialized in this function
#
# Groff warnings on OpenSUSE.
@@ -123,18 +146,18 @@ include/runtime.hpp: .*pure_error.*
#
listener.cc : .*conversion from 'SOCKET' to 'int'.*
net_serv.cc : .*conversion from 'SOCKET' to 'int'.*
-set_var.cc: right-hand operand of comma has no effect : 1000-1400
-
# allow a little moving space for the warning below
-mi_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600
-ma_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 550-650
+mi_packrec\.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600
+ma_packrec\.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 550-650
#
# Wrong compiler warnings
#
.* : .*no matching operator delete found; memory will not be freed if initialization throws an exception.*
-ctype-simple.c : .*unary minus operator applied to unsigned type, result still unsigned.*
+ctype-simple\.c : .*unary minus operator applied to unsigned type, result still unsigned.*
# Wrong warning due to GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29478
-regexec\.c : .*passing argument 3 of.*matcher.* discards qualifiers from pointer target type.*
+regexec\.c : passing argument 3 of.*matcher.* discards qualifiers from pointer target type
+libmysql\.c: passing argument 2 of .*memcpy.* discards qualifiers from pointer target type : 3000-4000
+storage/xtradb/dict/dict0dict\.c : passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500
=== modified file 'unittest/mysys/waiting_threads-t.c'
--- a/unittest/mysys/waiting_threads-t.c 2010-01-28 14:49:14 +0000
+++ b/unittest/mysys/waiting_threads-t.c 2010-03-30 12:36:49 +0000
@@ -258,7 +258,7 @@ void do_tests()
#define test_kill_strategy(X) \
diag("kill strategy: " #X); \
DBUG_EXECUTE("reset_file", \
- { rewind(DBUG_FILE); (void) ftruncate(fileno(DBUG_FILE), 0); }); \
+ { rewind(DBUG_FILE); my_chsize(fileno(DBUG_FILE), 0, 0, MYF(MY_WME)); }); \
DBUG_PRINT("info", ("kill strategy: " #X)); \
kill_strategy=X; \
do_one_test();
1
0
Regarding comment from colincharles here:
http://www.bytebot.net/blog/archives/2010/04/02/mariadb-5-1-44-released
I am assuming that by 'resources' needed for creeating win32 builds, you
mean a buildbot slave.
I have an Athlon XP box under my desk, which used to be my primary
machine, but right now is being used mostly for backups, so most of the
time it does nothing but gathers dust. I could probably set it up with
another hard disk, install Windows XP/Vista on it and donate it for
MariaDB builds. It depends on a few factors though.
1. How autoamted is the process? Ideally all I would like to do is to
switch the power on, login and let the machine do its job with as little
interaction from my side as possible.
2. How often and for how long would it need to run? I can run it for
8-10 hours several times a week, but certainly not 24/7
3. How much upload/download bandwidth is required? While my download
bandwidth is pretty good, my upload is not. Still, as long as we are not
talking several tens of gigabytes per day, I should manage.
Also please take into consideration, that I've never done anything like
this before, so I might require a lot of help setting this up.
Please tell me what you think! ;)
Mchl
--
This message was sent from Launchpad by the user
Mchl (https://launchpad.net/~mchlpl)
using the "Contact this team" link on the Maria Discuss
team page to each member directly.
For more information see
https://help.launchpad.net/YourAccount/ContactingPeople
1
0

[Maria-developers] FYI Current stable subquery optimizations pushed to lp:~maria-captains/maria/5.3
by Sergey Petrunya 03 Apr '10
by Sergey Petrunya 03 Apr '10
03 Apr '10
Hello,
As requested, I've pushed the latest 'stable'(*) version of subquery optimizations
into lp:~maria-captains/maria/5.3.
(*) - stable here means:
= there are no subquery-optimizations related failures in buildbot
= there are no known "new" subquery issues (there are still some subquery
code issues that were inherited from buildbot, though).
BR
Sergey
--
Sergey Petrunia, Software Developer
Monty Program AB, http://askmonty.org
Blog: http://s.petrunia.net/blog
1
0

[Maria-developers] Rev 2771: embedded builds used to refer to undefined functions inside if(0) { } in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 02 Apr '10
by serg@askmonty.org 02 Apr '10
02 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2771
revision-id: sergii(a)pisem.net-20100402200840-0nctbdvalpetkkzp
parent: sergii(a)pisem.net-20100402185102-3jj9hj51tfjblsyu
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Fri 2010-04-02 22:08:40 +0200
message:
embedded builds used to refer to undefined functions inside if(0) { }
gcc optimized this dead code away, and does not notice that functions
were undefined. Other compilers are more picky
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-04-01 14:34:51 +0000
+++ b/sql/sql_acl.cc 2010-04-02 20:08:40 +0000
@@ -6849,6 +6849,7 @@ bool check_routine_level_acl(THD *thd, c
#define initialized 0
#define decrease_user_connections(X) /* nothing */
#define check_for_max_user_connections(X,Y) 0
+#define get_or_create_user_conn(A,B,C,D) 0
#endif
#endif
#ifndef HAVE_OPENSSL
1
0

[Maria-developers] Rev 2770: more fixes for windows and status_user.test in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 02 Apr '10
by serg@askmonty.org 02 Apr '10
02 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2770
revision-id: sergii(a)pisem.net-20100402185102-3jj9hj51tfjblsyu
parent: sergii(a)pisem.net-20100402092009-fsk3s46z6furxi1k
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Fri 2010-04-02 20:51:02 +0200
message:
more fixes for windows and status_user.test
=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt 2010-01-31 09:13:21 +0000
+++ b/libmysqld/CMakeLists.txt 2010-04-02 18:51:02 +0000
@@ -104,7 +104,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libm
../sql-common/client.c ../sql-common/my_time.c
../sql-common/my_user.c ../sql-common/pack.c
../sql/password.c ../sql/discover.cc ../sql/derror.cc
- ../sql/field.cc ../sql/field_conv.cc
+ ../sql/field.cc ../sql/field_conv.cc ../sql-common/client_plugin.c
../sql/filesort.cc ../sql/gstream.cc ../sql/ha_partition.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
=== modified file 'mysql-test/r/status_user.result'
--- a/mysql-test/r/status_user.result 2010-03-21 20:58:19 +0000
+++ b/mysql-test/r/status_user.result 2010-04-02 18:51:02 +0000
@@ -137,7 +137,7 @@ ROWS_INSERTED 8
ROWS_UPDATED 5
SELECT_COMMANDS 3
UPDATE_COMMANDS 11
-OTHER_COMMANDS 9
+OTHER_COMMANDS 7
COMMIT_TRANSACTIONS 19
ROLLBACK_TRANSACTIONS 2
DENIED_CONNECTIONS 0
@@ -154,7 +154,7 @@ ROWS_INSERTED 8
ROWS_UPDATED 5
SELECT_COMMANDS 3
UPDATE_COMMANDS 11
-OTHER_COMMANDS 9
+OTHER_COMMANDS 7
COMMIT_TRANSACTIONS 19
ROLLBACK_TRANSACTIONS 2
DENIED_CONNECTIONS 0
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-04-02 09:20:09 +0000
+++ b/sql/sql_class.cc 2010-04-02 18:51:02 +0000
@@ -924,7 +924,7 @@ void THD::update_stats(void)
/* A SQL query. */
if (lex->sql_command == SQLCOM_SELECT)
select_commands++;
- else if (! (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND))
+ else if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
{
/* Ignore 'SHOW ' commands */
}
1
0

[Maria-developers] bzr commit into file:///home/tsk/mprog/src/5.3-subqueries/ branch (timour:2788)
by timour@askmonty.org 02 Apr '10
by timour@askmonty.org 02 Apr '10
02 Apr '10
#At file:///home/tsk/mprog/src/5.3-subqueries/ based on revid:psergey@askmonty.org-20100329200940-9ikx6gpww0gtsx00
2788 timour(a)askmonty.org 2010-04-02
MWL#68: Subquery optimization: Efficient NOT IN execution with NULLs
Fixed an error where the priority queue for the indexes used for partial
matching was not emptied after each execution in all cases.
modified:
sql/item_subselect.cc
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2010-03-29 14:04:35 +0000
+++ b/sql/item_subselect.cc 2010-04-02 14:27:06 +0000
@@ -3882,8 +3882,9 @@ subselect_hash_sj_engine::make_unique_en
cur_ref_buff + test(maybe_null), we could
use that information instead.
*/
+
cur_ref_buff + null_count,
- null_count ? tab->ref.key_buff : 0,
+ null_count ? cur_ref_buff : 0,
cur_key_part->length, tab->ref.items[i]);
cur_ref_buff+= cur_key_part->store_length;
}
@@ -4908,6 +4909,8 @@ bool subselect_rowid_merge_engine::parti
/* If there is a non-NULL key, it must be the first key in the keys array. */
DBUG_ASSERT(!non_null_key || (non_null_key && merge_keys[0] == non_null_key));
+ /* The prioryty queue for keys must be empty. */
+ DBUG_ASSERT(!pq.elements);
/* All data accesses during execution are via handler::ha_rnd_pos() */
tmp_table->file->ha_rnd_init(0);
@@ -5031,6 +5034,7 @@ bool subselect_rowid_merge_engine::parti
DBUG_ASSERT(FALSE);
end:
+ queue_remove_all(&pq);
tmp_table->file->ha_rnd_end();
return res;
}
1
0

[Maria-developers] Rev 2769: fixes for windows builds in http://bazaar.launchpad.net/~maria-captains/maria/5.2/
by serg@askmonty.org 02 Apr '10
by serg@askmonty.org 02 Apr '10
02 Apr '10
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/
------------------------------------------------------------
revno: 2769
revision-id: sergii(a)pisem.net-20100402092009-fsk3s46z6furxi1k
parent: sanja(a)askmonty.org-20100402100339-oxwd8hcrstv3gs1o
committer: Sergei Golubchik <sergii(a)pisem.net>
branch nick: 5.2
timestamp: Fri 2010-04-02 11:20:09 +0200
message:
fixes for windows builds
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt 2010-04-01 14:34:51 +0000
+++ b/CMakeLists.txt 2010-04-02 09:20:09 +0000
@@ -38,6 +38,7 @@ ADD_DEFINITIONS(-DMYSQL_DATADIR="c:/Prog
ADD_DEFINITIONS(-DDEFAULT_CHARSET_HOME="c:/Program Files/MySQL/MySQL Server ${MYSQL_BASE_VERSION}/")
ADD_DEFINITIONS(-DPACKAGE=mysql)
ADD_DEFINITIONS(-DSHAREDIR="share")
+ADD_DEFINITIONS(-DPLUGINDIR="lib/plugin")
# Set debug options
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS")
=== modified file 'extra/libevent/evbuffer.c'
--- a/extra/libevent/evbuffer.c 2010-02-01 06:14:12 +0000
+++ b/extra/libevent/evbuffer.c 2010-04-02 09:20:09 +0000
@@ -75,8 +75,7 @@ bufferevent_add(struct event *ev, int ti
*/
void
-bufferevent_read_pressure_cb(struct evbuffer *buf,
- size_t old __attribute__((unused)), size_t now,
+bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
void *arg) {
struct bufferevent *bufev = arg;
/*
=== modified file 'extra/libevent/event.c'
--- a/extra/libevent/event.c 2010-01-06 19:20:16 +0000
+++ b/extra/libevent/event.c 2010-04-02 09:20:09 +0000
@@ -394,8 +394,7 @@ event_base_get_method(struct event_base
}
static void
-event_loopexit_cb(int fd __attribute__((unused)),
- short what __attribute__((unused)), void *arg)
+event_loopexit_cb(int fd, short what, void *arg)
{
struct event_base *base = arg;
base->event_gotterm = 1;
=== modified file 'extra/libevent/signal.c'
--- a/extra/libevent/signal.c 2010-01-06 19:20:16 +0000
+++ b/extra/libevent/signal.c 2010-04-02 09:20:09 +0000
@@ -69,7 +69,7 @@ static void evsignal_handler(int sig);
/* Callback for when the signal handler write a byte to our signaling socket */
static void
-evsignal_cb(int fd, short what __attribute((unused)), void *arg __attribute((unused)))
+evsignal_cb(int fd, short what, void *arg)
{
static char signals[100];
#ifdef WIN32
=== modified file 'include/m_ctype.h'
--- a/include/m_ctype.h 2010-03-31 18:37:45 +0000
+++ b/include/m_ctype.h 2010-04-02 09:20:09 +0000
@@ -311,7 +311,9 @@ struct charset_info_st
#define ILLEGAL_CHARSET_INFO_NUMBER (~0U)
extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_bin;
-extern struct charset_info_st my_charset_bin;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_latin1;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_filename;
+
extern struct charset_info_st my_charset_big5_chinese_ci;
extern struct charset_info_st my_charset_big5_bin;
extern struct charset_info_st my_charset_cp932_japanese_ci;
@@ -324,7 +326,6 @@ extern struct charset_info_st my_charset
extern struct charset_info_st my_charset_gb2312_bin;
extern struct charset_info_st my_charset_gbk_chinese_ci;
extern struct charset_info_st my_charset_gbk_bin;
-extern struct charset_info_st my_charset_latin1;
extern struct charset_info_st my_charset_latin1_german2_ci;
extern struct charset_info_st my_charset_latin1_bin;
extern struct charset_info_st my_charset_latin2_czech_ci;
@@ -341,7 +342,6 @@ extern struct charset_info_st my_charset
extern struct charset_info_st my_charset_utf8_unicode_ci;
extern struct charset_info_st my_charset_utf8_bin;
extern struct charset_info_st my_charset_cp1250_czech_ci;
-extern struct charset_info_st my_charset_filename;
/* declarations for simple charsets */
extern size_t my_strnxfrm_simple(CHARSET_INFO *, uchar *, size_t,
=== modified file 'include/my_global.h'
--- a/include/my_global.h 2010-03-29 15:13:53 +0000
+++ b/include/my_global.h 2010-04-02 09:20:09 +0000
@@ -1522,6 +1522,9 @@ do { doubleget_union _tmp; \
#elif defined(HAVE_DLFCN_H)
#include <dlfcn.h>
#endif
+#ifndef HAVE_DLERROR
+#define dlerror() ""
+#endif
#endif
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
@@ -1529,7 +1532,7 @@ do { doubleget_union _tmp; \
#define RTLD_NOW 1
#endif
-#ifndef HAVE_DLERROR
+#ifndef HAVE_DLOPEN
#define dlerror() "No support for dynamic loading (static build?)"
#define dlopen(A,B) 0
#define dlsym(A,B) 0
=== modified file 'server-tools/CMakeLists.txt'
--- a/server-tools/CMakeLists.txt 2007-02-14 11:42:11 +0000
+++ b/server-tools/CMakeLists.txt 2010-04-02 09:20:09 +0000
@@ -27,7 +27,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc co
user_management_commands.cc
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
- ../../libmysql/errmsg.c)
+ ../../libmysql/errmsg.c ../../sql-common/client_plugin.c)
ADD_DEPENDENCIES(mysqlmanager GenError)
TARGET_LINK_LIBRARIES(mysqlmanager dbug mysys strings taocrypt vio yassl zlib wsock32)
=== modified file 'server-tools/instance-manager/CMakeLists.txt'
--- a/server-tools/instance-manager/CMakeLists.txt 2007-12-27 17:16:02 +0000
+++ b/server-tools/instance-manager/CMakeLists.txt 2010-04-02 09:20:09 +0000
@@ -28,7 +28,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc co
user_management_commands.cc ../../mysys/my_rnd.c
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
- ../../libmysql/errmsg.c)
+ ../../libmysql/errmsg.c ../../sql-common/client_plugin.c)
ADD_DEPENDENCIES(mysqlmanager GenError)
TARGET_LINK_LIBRARIES(mysqlmanager debug dbug mysys strings taocrypt vio yassl zlib wsock32)
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2010-04-01 09:04:26 +0000
+++ b/sql-common/client.c 2010-04-02 09:20:09 +0000
@@ -2345,7 +2345,7 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_V
case VIO_TYPE_SSL:
{
struct sockaddr addr;
- socklen_t addrlen= sizeof(addr);
+ SOCKET_SIZE_TYPE addrlen= sizeof(addr);
if (getsockname(vio->sd, &addr, &addrlen))
return;
info->protocol= addr.sa_family == AF_UNIX ?
@@ -2360,7 +2360,7 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_V
return;
case VIO_TYPE_SHARED_MEMORY:
info->protocol= MYSQL_VIO_MEMORY;
- info->handle= vio->handle_client_file_map; /* or what ? */
+ info->handle= vio->handle_file_map; /* or what ? */
return;
#endif
default: DBUG_ASSERT(0);
=== modified file 'sql/client_settings.h'
--- a/sql/client_settings.h 2010-03-29 15:13:53 +0000
+++ b/sql/client_settings.h 2010-04-02 09:20:09 +0000
@@ -29,7 +29,6 @@
#define mysql_master_send_query(A, B, C) 1
#define mysql_slave_send_query(A, B, C) 1
#define mysql_rpl_probe(mysql) 0
-#undef HAVE_SMEM
#undef _CUSTOMCONFIG_
#define mysql_server_init(a,b,c) mysql_client_plugin_init()
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2010-03-15 11:51:23 +0000
+++ b/sql/log_event.cc 2010-04-02 09:20:09 +0000
@@ -1716,8 +1716,7 @@ beg:
case MYSQL_TYPE_DATETIME:
{
- size_t d, t;
- uint64 i64= uint8korr(ptr); /* YYYYMMDDhhmmss */
+ uint64 d, t, i64= uint8korr(ptr); /* YYYYMMDDhhmmss */
d= i64 / 1000000;
t= i64 % 1000000;
my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-04-01 09:04:26 +0000
+++ b/sql/mysqld.cc 2010-04-02 09:20:09 +0000
@@ -6645,8 +6645,6 @@ Can't be set to 1 if --log-slave-updates
{"shared-memory", OPT_ENABLE_SHARED_MEMORY,
"Enable the shared memory.",(uchar**) &opt_enable_shared_memory, (uchar**) &opt_enable_shared_memory,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
-#ifdef HAVE_SMEM
{"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME,
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_class.cc 2010-04-02 09:20:09 +0000
@@ -924,7 +924,7 @@ void THD::update_stats(void)
/* A SQL query. */
if (lex->sql_command == SQLCOM_SELECT)
select_commands++;
- else if (! sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
+ else if (! (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND))
{
/* Ignore 'SHOW ' commands */
}
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-04-01 14:34:51 +0000
+++ b/sql/sql_show.cc 2010-04-02 09:20:09 +0000
@@ -2529,8 +2529,8 @@ int send_user_stats(THD* thd, HASH *all_
table->field[j++]->store(user_stats->user, user_stats->user_name_length,
system_charset_info);
table->field[j++]->store((longlong)user_stats->total_connections,TRUE);
- table->field[j++]->store((longlong)user_stats->concurrent_connections);
- table->field[j++]->store((longlong)user_stats->connected_time);
+ table->field[j++]->store((longlong)user_stats->concurrent_connections, TRUE);
+ table->field[j++]->store((longlong)user_stats->connected_time, TRUE);
table->field[j++]->store((double)user_stats->busy_time);
table->field[j++]->store((double)user_stats->cpu_time);
table->field[j++]->store((longlong)user_stats->bytes_received, TRUE);
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-04-01 09:04:26 +0000
+++ b/storage/maria/ma_loghandler.c 2010-04-02 09:20:09 +0000
@@ -1274,10 +1274,11 @@ static my_bool translog_set_lsn_for_file
for (file= from_file; file <= to_file; file++)
{
LOGHANDLER_FILE_INFO info;
- LINT_INIT(info.max_lsn);
-
File fd= open_logfile_by_number_no_cache(file);
+
LINT_INIT_STRUCT(info);
+ LINT_INIT(info.max_lsn);
+
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
1
0

[Maria-developers] Rev 2768: Fixed the test according to the new plugin information in file:///Users/bell/maria/bzr/work-maria-5.2-plugin/
by sanja@askmonty.org 02 Apr '10
by sanja@askmonty.org 02 Apr '10
02 Apr '10
At file:///Users/bell/maria/bzr/work-maria-5.2-plugin/
------------------------------------------------------------
revno: 2768
revision-id: sanja(a)askmonty.org-20100402100339-oxwd8hcrstv3gs1o
parent: sanja(a)askmonty.org-20100401200509-o67qhkcgzv5s9oai
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-plugin
timestamp: Fri 2010-04-02 13:03:39 +0300
message:
Fixed the test according to the new plugin information
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_is.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result 2010-04-02 10:03:39 +0000
@@ -271,10 +271,12 @@ NULL information_schema PBXT_STATISTICS
NULL information_schema PBXT_STATISTICS Name 2 NO varchar 40 120 NULL NULL utf8 utf8_general_ci varchar(40) select
NULL information_schema PBXT_STATISTICS Value 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(8) select
NULL information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
+NULL information_schema PLUGINS PLUGIN_AUTH_VERSION 12 NULL YES varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
NULL information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
NULL information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL utf8 utf8_general_ci varchar(20) select
NULL information_schema PLUGINS PLUGIN_LICENSE 10 NULL YES varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
+NULL information_schema PLUGINS PLUGIN_MATURITY 11 NULL YES varchar 12 36 NULL NULL utf8 utf8_general_ci varchar(12) select
NULL information_schema PLUGINS PLUGIN_NAME 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema PLUGINS PLUGIN_STATUS 3 NO varchar 10 30 NULL NULL utf8 utf8_general_ci varchar(10) select
NULL information_schema PLUGINS PLUGIN_TYPE 4 NO varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
@@ -791,6 +793,8 @@ NULL information_schema PBXT_STATISTICS
3.0000 information_schema PLUGINS PLUGIN_AUTHOR varchar 64 192 utf8 utf8_general_ci varchar(64)
1.0000 information_schema PLUGINS PLUGIN_DESCRIPTION longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
3.0000 information_schema PLUGINS PLUGIN_LICENSE varchar 80 240 utf8 utf8_general_ci varchar(80)
+3.0000 information_schema PLUGINS PLUGIN_MATURITY varchar 12 36 utf8 utf8_general_ci varchar(12)
+3.0000 information_schema PLUGINS PLUGIN_AUTH_VERSION varchar 80 240 utf8 utf8_general_ci varchar(80)
NULL information_schema PROCESSLIST ID bigint NULL NULL NULL NULL bigint(4)
3.0000 information_schema PROCESSLIST USER varchar 16 48 utf8 utf8_general_ci varchar(16)
3.0000 information_schema PROCESSLIST HOST varchar 64 192 utf8 utf8_general_ci varchar(64)
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2747)
by Igor Babaev 01 Apr '10
by Igor Babaev 01 Apr '10
01 Apr '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100331233728-obczp1ecrffnaa2s
2747 Igor Babaev 2010-04-01
Post-review fixes.
modified:
include/keycache.h
mysql-test/r/key_cache.result
mysql-test/t/key_cache.test
mysys/mf_keycache.c
sql/sql_show.cc
=== modified file 'include/keycache.h'
--- a/include/keycache.h 2010-02-16 16:41:11 +0000
+++ b/include/keycache.h 2010-04-01 21:42:40 +0000
@@ -37,7 +37,6 @@ C_MODE_START
#define MAX_KEY_CACHE_PARTITIONS 64
-
/* The structure to get statistical data about a key cache */
typedef struct st_key_cache_statistics
@@ -53,6 +52,8 @@ typedef struct st_key_cache_statistics
ulonglong writes; /* number of actual writes from buffers into files */
} KEY_CACHE_STATISTICS;
+#define NO_LONG_KEY_CACHE_STAT_VARIABLES 3
+
/* The type of a key cache object */
typedef enum key_cache_type
{
@@ -61,6 +62,55 @@ typedef enum key_cache_type
} KEY_CACHE_TYPE;
+typedef
+ int (*INIT_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ int (*RESIZE_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ void (*CHANGE_KEY_CACHE_PARAM)
+ (void *keycache_cb,
+ uint division_limit, uint age_threshold);
+typedef
+ uchar* (*KEY_CACHE_READ)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int return_buffer);
+typedef
+ int (*KEY_CACHE_INSERT)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length);
+typedef
+ int (*KEY_CACHE_WRITE)
+ (void *keycache_cb,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int force_write);
+typedef
+ int (*FLUSH_KEY_BLOCKS)
+ (void *keycache_cb,
+ int file, void *file_extra,
+ enum flush_type type);
+typedef
+ int (*RESET_KEY_CACHE_COUNTERS)
+ (const char *name, void *keycache_cb);
+typedef
+ void (*END_KEY_CACHE)
+ (void *keycache_cb, my_bool cleanup);
+typedef
+ void (*GET_KEY_CACHE_STATISTICS)
+ (void *keycache_cb, uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats);
+typedef
+ ulonglong (*GET_KEY_CACHE_STAT_VALUE)
+ (void *keycache_cb, uint var_no);
+
/*
An object of the type KEY_CACHE_FUNCS contains pointers to all functions
from the key cache interface.
@@ -74,32 +124,17 @@ typedef enum key_cache_type
typedef struct st_key_cache_funcs
{
- int (*init) (void *, uint key_cache_block_size,
- size_t use_mem, uint division_limit, uint age_threshold);
- int (*resize) (void *, uint key_cache_block_size,
- size_t use_mem, uint division_limit, uint age_threshold);
- void (*change_param) (void *keycache_cb,
- uint division_limit, uint age_threshold);
- uchar* (*read) (void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length, int return_buffer);
- int (*insert) (void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length);
- int (*write) (void *keycache_cb,
- File file, void *file_extra,
- my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length, int force_write);
- int (*flush) (void *keycache_cb,
- int file, void *file_extra,
- enum flush_type type);
- int (*reset_counters) (const char *name, void *keycache_cb);
- void (*end) (void *keycache_cb, my_bool cleanup);
- void (*get_stats) (void *keycache_cb, uint partition_no,
- KEY_CACHE_STATISTICS *key_cache_stats);
- ulonglong (*get_stat_val) (void *keycache_cb, uint var_no);
+ INIT_KEY_CACHE init;
+ RESIZE_KEY_CACHE resize;
+ CHANGE_KEY_CACHE_PARAM change_param;
+ KEY_CACHE_READ read;
+ KEY_CACHE_INSERT insert;
+ KEY_CACHE_WRITE write;
+ FLUSH_KEY_BLOCKS flush;
+ RESET_KEY_CACHE_COUNTERS reset_counters;
+ END_KEY_CACHE end;
+ GET_KEY_CACHE_STATISTICS get_stats;
+ GET_KEY_CACHE_STAT_VALUE get_stat_val;
} KEY_CACHE_FUNCS;
=== modified file 'mysql-test/r/key_cache.result'
--- a/mysql-test/r/key_cache.result 2010-03-31 23:37:28 +0000
+++ b/mysql-test/r/key_cache.result 2010-04-01 21:42:40 +0000
@@ -672,12 +672,12 @@ insert into t2 values (2000, 3, 'yyyy');
select * from information_schema.key_caches where key_cache_name like "keycache2"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
select * from information_schema.key_caches where key_cache_name like "key%"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
-keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
@@ -718,7 +718,7 @@ KEY_CACHE_NAME PARTITIONS PARTITION_NUMB
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
@@ -726,66 +726,72 @@ KEY_CACHE_NAME PARTITIONS PARTITION_NUMB
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 262143 8192 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
insert into t2 values (8000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=64*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=128*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
drop table t1,t2;
set global keycache1.key_buffer_size=0;
set global keycache2.key_buffer_size=0;
=== modified file 'mysql-test/t/key_cache.test'
--- a/mysql-test/t/key_cache.test 2010-03-31 23:37:28 +0000
+++ b/mysql-test/t/key_cache.test 2010-04-01 21:42:40 +0000
@@ -469,6 +469,8 @@ insert into t2 values (7000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2010-02-16 16:41:11 +0000
+++ b/mysys/mf_keycache.c 2010-04-01 21:42:40 +0000
@@ -49,6 +49,7 @@
One cache can handle many files.
It must contain buffers of the same blocksize.
+
init_key_cache() should be used to init cache handler.
The free list (free_block_list) is a stack like structure.
@@ -151,7 +152,7 @@ typedef struct st_keycache_wqueue
/* Control block for a simple (non-partitioned) key cache */
-typedef struct st_s_key_cache_cb
+typedef struct st_simple_key_cache_cb
{
my_bool key_cache_inited; /* <=> control block is allocated */
my_bool in_resize; /* true during resize operation */
@@ -202,7 +203,7 @@ typedef struct st_s_key_cache_cb
int blocks; /* max number of blocks in the cache */
uint hash_factor; /* factor used to calculate hash function */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
-} S_KEY_CACHE_CB;
+} SIMPLE_KEY_CACHE_CB;
/*
Some compilation flags have been added specifically for this module
@@ -314,12 +315,8 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cac
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
-static int flush_all_key_blocks(S_KEY_CACHE_CB *keycache);
-/*
-static void s_change_key_cache_param(void *keycache_cb, uint division_limit,
- uint age_threshold);
-*/
-static void s_end_key_cache(void *keycache_cb, my_bool cleanup);
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache);
+static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup);
#ifdef THREAD
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
pthread_mutex_t *mutex);
@@ -328,9 +325,9 @@ static void release_whole_queue(KEYCACHE
#define wait_on_queue(wqueue, mutex) do {} while (0)
#define release_whole_queue(wqueue) do {} while (0)
#endif
-static void free_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
#if !defined(DBUG_OFF)
-static void test_key_cache(S_KEY_CACHE_CB *keycache,
+static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
const char *where, my_bool lock);
#endif
#define KEYCACHE_BASE_EXPR(f, pos) \
@@ -433,7 +430,7 @@ static int keycache_pthread_cond_signal(
#define inline /* disabled inline for easier debugging */
static int fail_block(BLOCK_LINK *block);
static int fail_hlink(HASH_LINK *hlink);
-static int cache_empty(S_KEY_CACHE_CB *keycache);
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache);
#endif
@@ -447,8 +444,8 @@ static inline uint next_power(uint value
Initialize a simple key cache
SYNOPSIS
- s_init_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ init_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
key_cache_block_size size of blocks to keep cached data
use_mem memory to use for the key cache buferrs/structures
division_limit division limit (may be zero)
@@ -458,8 +455,8 @@ static inline uint next_power(uint value
This function is the implementation of the init_key_cache interface
function that is employed by simple (non-partitioned) key caches.
The function builds a simple key cache and initializes the control block
- structure of the type S_KEY_CACHE_CB that is used for this key cache.
- The parameter keycache_cb is supposed to point to this structure.
+ structure of the type SIMPLE_KEY_CACHE_CB that is used for this key cache.
+ The parameter keycache is supposed to point to this structure.
The parameter key_cache_block_size specifies the size of the blocks in
the key cache to be built. The parameters division_limit and age_threshhold
determine the initial values of those characteristics of the key cache
@@ -478,19 +475,17 @@ static inline uint next_power(uint value
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
*/
static
-int s_init_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
ulong blocks, hash_links;
size_t length;
int error;
- DBUG_ENTER("init_key_cache");
+ DBUG_ENTER("init_simple_key_cache");
DBUG_ASSERT(key_cache_block_size >= 512);
KEYCACHE_DEBUG_OPEN;
@@ -653,16 +648,16 @@ err:
Prepare for resizing a simple key cache
SYNOPSIS
- s_prepare_resize_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ prepare_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
with_resize_queue <=> resize queue is used
release_lock <=> release the key cache lock before return
DESCRIPTION
This function flushes all dirty pages from a simple key cache and after
- this it destroys the key cache calling s_end_key_cache. The function
- considers the parameter keycache_cb as a pointer to the control block
- structure of the type S_KEY_CACHE_CB for this key cache.
+ this it destroys the key cache calling end_simple_key_cache. The function
+ takes the parameter keycache as a pointer to the control block
+ structure of the type SIMPLE_KEY_CACHE_CB for this key cache.
The parameter with_resize_queue determines weather the resize queue is
involved (MySQL server never uses this queue). The parameter release_lock
says weather the key cache lock must be released before return from
@@ -673,19 +668,18 @@ err:
1 - otherwise.
NOTES
- This function is the called by s_resize_key_cache and p_resize_key_cache
- that resize simple and partitioned key caches respectively.
-
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
*/
static
-int s_prepare_resize_key_cache(void *keycache_cb,
- my_bool with_resize_queue,
- my_bool release_lock)
+int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool release_lock)
{
int res= 0;
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_prepare_resize_key_cache");
+ DBUG_ENTER("prepare_resize_simple_key_cache");
keycache_pthread_mutex_lock(&keycache->cache_lock);
@@ -749,7 +743,7 @@ int s_prepare_resize_key_cache(void *key
KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0);
#endif
- s_end_key_cache(keycache_cb, 0);
+ end_simple_key_cache(keycache, 0);
finish:
if (release_lock)
@@ -762,16 +756,16 @@ finish:
Finalize resizing a simple key cache
SYNOPSIS
- s_finish_resize_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ finish_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
with_resize_queue <=> resize queue is used
acquire_lock <=> acquire the key cache lock at start
DESCRIPTION
This function performs finalizing actions for the operation of
- resizing a simple key cache. The function considers the parameter
- keycache_cb as a pointer to the control block structure of the type
- S_KEY_CACHE_CB for this key cache. The function sets the flag
+ resizing a simple key cache. The function takes the parameter
+ keycache as a pointer to the control block structure of the type
+ SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
in_resize in this structure to FALSE.
The parameter with_resize_queue determines weather the resize queue
is involved (MySQL server never uses this queue).
@@ -782,22 +776,23 @@ finish:
none
NOTES
- This function is the called by s_resize_key_cache and p_resize_key_cache
- that resize simple and partitioned key caches respectively.
-
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
*/
static
-void s_finish_resize_key_cache(void *keycache_cb,
- my_bool with_resize_queue,
- my_bool acquire_lock)
+void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool acquire_lock)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_finish_resize_key_cache");
+ DBUG_ENTER("finish_resize_simple_key_cache");
if (acquire_lock)
keycache_pthread_mutex_lock(&keycache->cache_lock);
-
+
+ safe_mutex_assert_owner(&keycache->cache_lock);
+
/*
Mark the resize finished. This allows other threads to start a
resize or to request new cache blocks.
@@ -820,8 +815,8 @@ void s_finish_resize_key_cache(void *key
Resize a simple key cache
SYNOPSIS
- s_resize_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
key_cache_block_size size of blocks to keep cached data
use_mem memory to use for the key cache buffers/structures
division_limit new division limit (if not zero)
@@ -830,8 +825,8 @@ void s_finish_resize_key_cache(void *key
DESCRIPTION
This function is the implementation of the resize_key_cache interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for the simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
cache to be resized.
The parameter key_cache_block_size specifies the new size of the blocks in
the key cache. The parameters division_limit and age_threshold
@@ -845,47 +840,45 @@ void s_finish_resize_key_cache(void *key
0 - otherwise.
NOTES.
- The function first calls the function s_prepare_resize_key_cache
+ The function first calls the function prepare_resize_simple_key_cache
to flush all dirty blocks from key cache, to free memory used
for key cache blocks and auxiliary structures. After this the
function builds a new key cache with new parameters.
This implementation doesn't block the calls and executions of other
functions from the key cache interface. However it assumes that the
- calls of s_resize_key_cache itself are serialized.
+ calls of resize_simple_key_cache itself are serialized.
The function starts the operation only when all other threads
performing operations with the key cache let her to proceed
(when cnt_for_resize=0).
-
*/
static
-int s_resize_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
int blocks= 0;
- DBUG_ENTER("s_resize_key_cache");
+ DBUG_ENTER("resize_simple_key_cache");
if (!keycache->key_cache_inited)
- DBUG_RETURN(keycache->disk_blocks);
+ DBUG_RETURN(blocks);
/*
Note that the cache_lock mutex and the resize_queue are left untouched.
We do not lose the cache_lock and will release it only at the end of
this function.
*/
- if (s_prepare_resize_key_cache(keycache_cb, 1, 0))
+ if (prepare_resize_simple_key_cache(keycache, 1, 0))
goto finish;
/* The following will work even if use_mem is 0 */
- blocks= s_init_key_cache(keycache, key_cache_block_size, use_mem,
- division_limit, age_threshold);
+ blocks= init_simple_key_cache(keycache, key_cache_block_size, use_mem,
+ division_limit, age_threshold);
finish:
- s_finish_resize_key_cache(keycache_cb, 1, 0);
+ finish_resize_simple_key_cache(keycache, 1, 0);
DBUG_RETURN(blocks);
}
@@ -894,7 +887,7 @@ finish:
/*
Increment counter blocking resize key cache operation
*/
-static inline void inc_counter_for_resize_op(S_KEY_CACHE_CB *keycache)
+static inline void inc_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
keycache->cnt_for_resize_op++;
}
@@ -904,7 +897,7 @@ static inline void inc_counter_for_resiz
Decrement counter blocking resize key cache operation;
Signal the operation to proceed when counter becomes equal zero
*/
-static inline void dec_counter_for_resize_op(S_KEY_CACHE_CB *keycache)
+static inline void dec_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
if (!--keycache->cnt_for_resize_op)
release_whole_queue(&keycache->waiting_for_resize_cnt);
@@ -915,16 +908,16 @@ static inline void dec_counter_for_resiz
Change key cache parameters of a simple key cache
SYNOPSIS
- s_change_key_cache_param()
- keycache_cb pointer to the control block of a simple key cache
+ change_simple_key_cache_param()
+ keycache pointer to the control block of a simple key cache
division_limit new division limit (if not zero)
age_threshold new age threshold (if not zero)
DESCRIPTION
This function is the implementation of the change_key_cache_param interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for the simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
cache where new values of the division limit and the age threshold used
for midpoint insertion strategy are to be set. The parameters
division_limit and age_threshold provide these new values.
@@ -938,15 +931,13 @@ static inline void dec_counter_for_resiz
This function changes some parameters of a given key cache without
reformatting it. The function does not touch the contents the key
cache blocks.
-
*/
static
-void s_change_key_cache_param(void *keycache_cb, uint division_limit,
- uint age_threshold)
+void change_simple_key_cache_param(SIMPLE_KEY_CACHE_CB *keycache, uint division_limit,
+ uint age_threshold)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_change_key_cache_param");
+ DBUG_ENTER("change_simple_key_cache_param");
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (division_limit)
keycache->min_warm_blocks= (keycache->disk_blocks *
@@ -963,15 +954,15 @@ void s_change_key_cache_param(void *keyc
Destroy a simple key cache
SYNOPSIS
- s_end_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ end_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
cleanup <=> complete free (free also mutex for key cache)
DESCRIPTION
This function is the implementation of the end_key_cache interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for the simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
cache to be destroyed.
The function frees the memory allocated for the key cache blocks and
auxiliary structures. If the value of the parameter cleanup is TRUE
@@ -982,10 +973,9 @@ void s_change_key_cache_param(void *keyc
*/
static
-void s_end_key_cache(void *keycache_cb, my_bool cleanup)
+void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_end_key_cache");
+ DBUG_ENTER("end_simple_key_cache");
DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
if (!keycache->key_cache_inited)
@@ -1276,7 +1266,7 @@ static inline void link_changed(BLOCK_LI
void
*/
-static void link_to_file_list(S_KEY_CACHE_CB *keycache,
+static void link_to_file_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int file,
my_bool unlink_block)
{
@@ -1317,7 +1307,7 @@ static void link_to_file_list(S_KEY_CACH
void
*/
-static void link_to_changed_list(S_KEY_CACHE_CB *keycache,
+static void link_to_changed_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
@@ -1372,8 +1362,8 @@ static void link_to_changed_list(S_KEY_C
not linked in the LRU ring.
*/
-static void link_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block, my_bool hot,
- my_bool at_end)
+static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block,
+ my_bool hot, my_bool at_end)
{
BLOCK_LINK *ins;
BLOCK_LINK **pins;
@@ -1493,7 +1483,7 @@ static void link_block(S_KEY_CACHE_CB *k
See NOTES for link_block
*/
-static void unlink_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
+static void unlink_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE));
DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/
@@ -1551,7 +1541,8 @@ static void unlink_block(S_KEY_CACHE_CB
RETURN
void
*/
-static void reg_requests(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block, int count)
+static void reg_requests(SIMPLE_KEY_CACHE_CB *keycache,
+ BLOCK_LINK *block, int count)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
DBUG_ASSERT(block->hash_link);
@@ -1594,7 +1585,7 @@ static void reg_requests(S_KEY_CACHE_CB
not linked in the LRU ring.
*/
-static void unreg_request(S_KEY_CACHE_CB *keycache,
+static void unreg_request(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int at_end)
{
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
@@ -1683,7 +1674,7 @@ static void remove_reader(BLOCK_LINK *bl
signals on its termination
*/
-static void wait_for_readers(S_KEY_CACHE_CB *keycache,
+static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
#ifdef THREAD
@@ -1732,7 +1723,7 @@ static inline void link_hash(HASH_LINK *
Remove a hash link from the hash table
*/
-static void unlink_hash(S_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
+static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
{
KEYCACHE_DBUG_PRINT("unlink_hash", ("fd: %u pos_ %lu #requests=%u",
(uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests));
@@ -1788,7 +1779,7 @@ static void unlink_hash(S_KEY_CACHE_CB *
Get the hash link for a page
*/
-static HASH_LINK *get_hash_link(S_KEY_CACHE_CB *keycache,
+static HASH_LINK *get_hash_link(SIMPLE_KEY_CACHE_CB *keycache,
int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
@@ -1909,7 +1900,7 @@ restart:
waits until first of this operations links any block back.
*/
-static BLOCK_LINK *find_key_block(S_KEY_CACHE_CB *keycache,
+static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache,
File file, my_off_t filepos,
int init_hits_left,
int wrmode, int *page_st)
@@ -2669,7 +2660,7 @@ restart:
portion is less than read_length, but not less than min_length.
*/
-static void read_block(S_KEY_CACHE_CB *keycache,
+static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, uint read_length,
uint min_length, my_bool primary)
{
@@ -2761,8 +2752,8 @@ static void read_block(S_KEY_CACHE_CB *k
SYNOPSIS
- s_key_cache_read()
- keycache_cb pointer to the control block of a simple key cache
+ simple_key_cache_read()
+ keycache pointer to the control block of a simple key cache
file handler for the file for the block of data to be read
filepos position of the block of data in the file
level determines the weight of the data
@@ -2774,8 +2765,8 @@ static void read_block(S_KEY_CACHE_CB *k
DESCRIPTION
This function is the implementation of the key_cache_read interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
cache.
In a general case the function reads a block of data from the key cache
into the buffer buff of the size specified by the parameter length. The
@@ -2799,20 +2790,18 @@ static void read_block(S_KEY_CACHE_CB *k
NOTES
Filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key_cache_block_size;
-
*/
-uchar *s_key_cache_read(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
my_bool locked_and_incremented= FALSE;
int error=0;
uchar *start= buff;
- DBUG_ENTER("s_key_cache_read");
+ DBUG_ENTER("simple_key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
@@ -3010,8 +2999,8 @@ end:
Insert a block of file data from a buffer into a simple key cache
SYNOPSIS
- s_key_cache_insert()
- keycache_cb pointer to the control block of a simple key cache
+ simple_key_cache_insert()
+ keycache pointer to the control block of a simple key cache
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
@@ -3021,8 +3010,8 @@ end:
DESCRIPTION
This function is the implementation of the key_cache_insert interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
cache.
The function writes a block of file data from a buffer into the key cache.
The buffer is specified with the parameters buff and length - the pointer
@@ -3045,11 +3034,10 @@ end:
*/
static
-int s_key_cache_insert(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length)
+int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
int error= 0;
DBUG_ENTER("key_cache_insert");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
@@ -3272,8 +3260,8 @@ int s_key_cache_insert(void *keycache_cb
SYNOPSIS
- s_key_cache_write()
- keycache_cb pointer to the control block of a simple key cache
+ simple_key_cache_write()
+ keycache pointer to the control block of a simple key cache
file handler for the file to write data to
file_extra maps of key cache partitions containing
dirty pages from file
@@ -3287,8 +3275,8 @@ int s_key_cache_insert(void *keycache_cb
DESCRIPTION
This function is the implementation of the key_cache_write interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
cache.
In a general case the function copies data from a buffer into the key
cache. The buffer is specified with the parameters buff and length -
@@ -3304,7 +3292,8 @@ int s_key_cache_insert(void *keycache_cb
The parameter file_extra currently makes sense only for simple key caches
that are elements of a partitioned key cache. It provides a pointer to the
shared bitmap of the partitions that may contains dirty pages for the file.
- This bitmap is used to optimize the function p_flush_key_blocks.
+ This bitmap is used to optimize the function
+ flush_partitioned_key_cache_blocks.
RETURN VALUE
0 if a success, 1 - otherwise.
@@ -3312,21 +3301,19 @@ int s_key_cache_insert(void *keycache_cb
NOTES
This implementation exploits the fact that the function is called only
when a thread has got an exclusive lock for the key file.
-
*/
static
-int s_key_cache_write(void *keycache_cb,
- File file, void *file_extra __attribute__((unused)),
- my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, void *file_extra __attribute__((unused)),
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
my_bool locked_and_incremented= FALSE;
int error=0;
- DBUG_ENTER("s_key_cache_write");
+ DBUG_ENTER("simple_key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu length: %u block_length: %u"
" key_block_length: %u",
@@ -3641,7 +3628,7 @@ end:
Block must have a request registered on it.
*/
-static void free_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
KEYCACHE_THREAD_TRACE("free block");
KEYCACHE_DBUG_PRINT("free_block",
@@ -3781,7 +3768,7 @@ static int cmp_sec_link(BLOCK_LINK **a,
free used blocks if requested
*/
-static int flush_cached_blocks(S_KEY_CACHE_CB *keycache,
+static int flush_cached_blocks(SIMPLE_KEY_CACHE_CB *keycache,
File file, BLOCK_LINK **cache,
BLOCK_LINK **end,
enum flush_type type)
@@ -3909,7 +3896,7 @@ static int flush_cached_blocks(S_KEY_CAC
1 error
*/
-static int flush_key_blocks_int(S_KEY_CACHE_CB *keycache,
+static int flush_key_blocks_int(SIMPLE_KEY_CACHE_CB *keycache,
File file, enum flush_type type)
{
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
@@ -4349,8 +4336,8 @@ err:
SYNOPSIS
- s_flush_key_blocks()
- keycache_cb pointer to the control block of a simple key cache
+ flush_simple_key_blocks()
+ keycache pointer to the control block of a simple key cache
file handler for the file to flush to
file_extra maps of key cache partitions containing
dirty pages from file (not used)
@@ -4359,7 +4346,7 @@ err:
DESCRIPTION
This function is the implementation of the flush_key_blocks interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
+ The function takes the parameter keycache as a pointer to the
control block structure of the type S_KEY_CACHE_CB for a simple key
cache.
In a general case the function flushes the data from all dirty key
@@ -4378,16 +4365,14 @@ err:
NOTES
This implementation exploits the fact that the function is called only
when a thread has got an exclusive lock for the key file.
-
*/
static
-int s_flush_key_blocks(void *keycache_cb,
- File file,
- void *file_extra __attribute__((unused)),
- enum flush_type type)
+int flush_simple_key_cache_blocks(SIMPLE_KEY_CACHE_CB *keycache,
+ File file,
+ void *file_extra __attribute__((unused)),
+ enum flush_type type)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
int res= 0;
DBUG_ENTER("flush_key_blocks");
DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
@@ -4440,7 +4425,7 @@ int s_flush_key_blocks(void *keycache_cb
!= 0 Error
*/
-static int flush_all_key_blocks(S_KEY_CACHE_CB *keycache)
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache)
{
BLOCK_LINK *block;
uint total_found;
@@ -4546,14 +4531,14 @@ static int flush_all_key_blocks(S_KEY_CA
Reset the counters of a simple key cache
SYNOPSIS
- s_reset_key_cache_counters()
+ reset_simple_key_cache_counters()
name the name of a key cache
- keycache_cb pointer to the control block of a simple key cache
+ keycache pointer to the control block of a simple key cache
DESCRIPTION
This function is the implementation of the reset_key_cache_counters
interface function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
+ The function takes the parameter keycache as a pointer to the
control block structure of the type S_KEY_CACHE_CB for a simple key cache.
This function resets the values of all statistical counters for the key
cache to 0.
@@ -4561,15 +4546,13 @@ static int flush_all_key_blocks(S_KEY_CA
RETURN
0 on success (always because it can't fail)
-
*/
static
-int s_reset_key_cache_counters(const char *name __attribute__((unused)),
- void *keycache_cb)
+int reset_simple_key_cache_counters(const char *name __attribute__((unused)),
+ SIMPLE_KEY_CACHE_CB *keycache)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_reset_key_cache_counters");
+ DBUG_ENTER("reset_simple_key_cache_counters");
if (!keycache->key_cache_inited)
{
DBUG_PRINT("info", ("Key cache %s not initialized.", name));
@@ -4590,9 +4573,10 @@ int s_reset_key_cache_counters(const cha
/*
Test if disk-cache is ok
*/
-static void test_key_cache(S_KEY_CACHE_CB *keycache __attribute__((unused)),
- const char *where __attribute__((unused)),
- my_bool lock __attribute__((unused)))
+static
+void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache __attribute__((unused)),
+ const char *where __attribute__((unused)),
+ my_bool lock __attribute__((unused)))
{
/* TODO */
}
@@ -4604,7 +4588,7 @@ static void test_key_cache(S_KEY_CACHE_C
#define MAX_QUEUE_LEN 100
-static void keycache_dump(S_KEY_CACHE_CB *keycache)
+static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache)
{
FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
struct st_my_thread_var *last;
@@ -4844,7 +4828,7 @@ static int fail_hlink(HASH_LINK *hlink)
return 0; /* Let the assert fail. */
}
-static int cache_empty(S_KEY_CACHE_CB *keycache)
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache)
{
int errcnt= 0;
int idx;
@@ -4887,54 +4871,57 @@ static int cache_empty(S_KEY_CACHE_CB *k
Get statistics for a simple key cache
SYNOPSIS
- get_key_cache_statistics()
- keycache_cb pointer to the control block of a simple key cache
+ get_simple_key_cache_statistics()
+ keycache pointer to the control block of a simple key cache
partition_no partition number (not used)
key_cache_stats OUT pointer to the structure for the returned statistics
DESCRIPTION
This function is the implementation of the get_key_cache_statistics
interface function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key cache.
- This function returns the statistical data for the key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the statistical data for the key cache.
The parameter partition_no is not used by this function.
RETURN
none
-
*/
static
-void s_get_key_cache_statistics(void *keycache_cb,
- uint partition_no __attribute__((unused)),
- KEY_CACHE_STATISTICS *key_cache_stats)
-{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_get_key_cache_statistics");
-
- key_cache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
- key_cache_stats->block_size= (longlong) keycache->key_cache_block_size;
- key_cache_stats->blocks_used= keycache->blocks_used;
- key_cache_stats->blocks_unused= keycache->blocks_unused;
- key_cache_stats->blocks_changed= keycache->global_blocks_changed;
- key_cache_stats->read_requests= keycache->global_cache_r_requests;
- key_cache_stats->reads= keycache->global_cache_read;
- key_cache_stats->write_requests= keycache->global_cache_w_requests;
- key_cache_stats->writes= keycache->global_cache_write;
+void get_simple_key_cache_statistics(SIMPLE_KEY_CACHE_CB *keycache,
+ uint partition_no __attribute__((unused)),
+ KEY_CACHE_STATISTICS *keycache_stats)
+{
+ DBUG_ENTER("simple_get_key_cache_statistics");
+
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ keycache_stats->blocks_used= keycache->blocks_used;
+ keycache_stats->blocks_unused= keycache->blocks_unused;
+ keycache_stats->blocks_changed= keycache->global_blocks_changed;
+ keycache_stats->read_requests= keycache->global_cache_r_requests;
+ keycache_stats->reads= keycache->global_cache_read;
+ keycache_stats->write_requests= keycache->global_cache_w_requests;
+ keycache_stats->writes= keycache->global_cache_write;
DBUG_VOID_RETURN;
}
-static size_t s_key_cache_stat_var_offsets[]=
+/*
+ Offsets of the statistical values in the control block for a simple key cache
+ The first NO_LONG_KEY_CACHE_STAT_VARIABLES=3 are of the ulong type while the
+ remaining are of the ulonglong type.
+ */
+static size_t simple_key_cache_stat_var_offsets[]=
{
- offsetof(S_KEY_CACHE_CB, blocks_used),
- offsetof(S_KEY_CACHE_CB, blocks_unused),
- offsetof(S_KEY_CACHE_CB, global_blocks_changed),
- offsetof(S_KEY_CACHE_CB, global_cache_w_requests),
- offsetof(S_KEY_CACHE_CB, global_cache_write),
- offsetof(S_KEY_CACHE_CB, global_cache_r_requests),
- offsetof(S_KEY_CACHE_CB, global_cache_read)
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_used),
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_unused),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_blocks_changed),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_w_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_write),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_r_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_read)
};
@@ -4942,16 +4929,16 @@ static size_t s_key_cache_stat_var_offse
Get the value of a statistical variable for a simple key cache
SYNOPSIS
- s_get_key_cache_stat_value()
- keycache_cb pointer to the control block of a simple key cache
+ get_simple_key_cache_stat_value()
+ keycache pointer to the control block of a simple key cache
var_no the ordered number of a statistical variable
DESCRIPTION
- This function is the implementation of the s_get_key_cache_stat_value
+ This function is the implementation of the get_simple_key_cache_stat_value
interface function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key cache.
- This function returns the value of the statistical variable var_no
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the value of the statistical variable var_no
for this key cache. The variables are numbered starting from 0 to 6.
RETURN
@@ -4960,12 +4947,12 @@ static size_t s_key_cache_stat_var_offse
*/
static
-ulonglong s_get_key_cache_stat_value(void *keycache_cb, uint var_no)
+ulonglong get_simple_key_cache_stat_value(SIMPLE_KEY_CACHE_CB *keycache,
+ uint var_no)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- size_t var_ofs= s_key_cache_stat_var_offsets[var_no];
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
ulonglong res= 0;
- DBUG_ENTER("s_get_key_cache_stat_value");
+ DBUG_ENTER("get_simple_key_cache_stat_value");
if (var_no < 3)
res= (ulonglong) (*(long *) ((char *) keycache + var_ofs));
@@ -4985,19 +4972,19 @@ ulonglong s_get_key_cache_stat_value(voi
the MySQL server code directly. We don't do it though.
*/
-static KEY_CACHE_FUNCS s_key_cache_funcs =
+static KEY_CACHE_FUNCS simple_key_cache_funcs =
{
- s_init_key_cache,
- s_resize_key_cache,
- s_change_key_cache_param,
- s_key_cache_read,
- s_key_cache_insert,
- s_key_cache_write,
- s_flush_key_blocks,
- s_reset_key_cache_counters,
- s_end_key_cache,
- s_get_key_cache_statistics,
- s_get_key_cache_stat_value
+ (INIT_KEY_CACHE) init_simple_key_cache,
+ (RESIZE_KEY_CACHE) resize_simple_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_simple_key_cache_param,
+ (KEY_CACHE_READ) simple_key_cache_read,
+ (KEY_CACHE_INSERT) simple_key_cache_insert,
+ (KEY_CACHE_WRITE) simple_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_simple_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_simple_key_cache_counters,
+ (END_KEY_CACHE) end_simple_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_simple_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_simple_key_cache_stat_value
};
@@ -5038,17 +5025,22 @@ static KEY_CACHE_FUNCS s_key_cache_funcs
/* Control block for a partitioned key cache */
-typedef struct st_p_key_cache_cb
+typedef struct st_partitioned_key_cache_cb
{
my_bool key_cache_inited; /*<=> control block is allocated */
- S_KEY_CACHE_CB **partition_array; /* array of the key cache partitions */
- uint partitions; /* number of partitions in the key cache */
+ SIMPLE_KEY_CACHE_CB **partition_array; /* the key cache partitions */
size_t key_cache_mem_size; /* specified size of the cache memory */
uint key_cache_block_size; /* size of the page buffer of a cache block */
-} P_KEY_CACHE_CB;
+ uint partitions; /* number of partitions in the key cache */
+} PARTITIONED_KEY_CACHE_CB;
static
-void p_end_key_cache(void *keycache_cb, my_bool cleanup);
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup);
+
+static int
+reset_partitioned_key_cache_counters(const char *name,
+ PARTITIONED_KEY_CACHE_CB *keycache);
/*
Determine the partition to which the index block to read is ascribed
@@ -5070,11 +5062,12 @@ void p_end_key_cache(void *keycache_cb,
file block is ascribed.
*/
-static
-S_KEY_CACHE_CB *get_key_cache_partition(P_KEY_CACHE_CB *keycache,
- File file, my_off_t filepos)
+static
+SIMPLE_KEY_CACHE_CB *
+get_key_cache_partition(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos)
{
- uint i= KEYCACHE_BASE_EXPR( file, filepos) % keycache->partitions;
+ uint i= KEYCACHE_BASE_EXPR(file, filepos) % keycache->partitions;
return keycache->partition_array[i];
}
@@ -5101,10 +5094,10 @@ S_KEY_CACHE_CB *get_key_cache_partition(
file block is ascribed.
*/
-static
-S_KEY_CACHE_CB *get_key_cache_partition_for_write(P_KEY_CACHE_CB *keycache,
- File file, my_off_t filepos,
- ulonglong* dirty_part_map)
+static SIMPLE_KEY_CACHE_CB
+*get_key_cache_partition_for_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos,
+ ulonglong* dirty_part_map)
{
uint i= KEYCACHE_BASE_EXPR( file, filepos) % keycache->partitions;
*dirty_part_map|= 1<<i;
@@ -5116,8 +5109,8 @@ S_KEY_CACHE_CB *get_key_cache_partition_
Initialize a partitioned key cache
SYNOPSIS
- p_init_key_cache()
- keycache_cb pointer to the control block of a partitioned key cache
+ init_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for all key cache partitions
division_limit division limit (may be zero)
@@ -5127,17 +5120,17 @@ S_KEY_CACHE_CB *get_key_cache_partition_
This function is the implementation of the init_key_cache interface function
that is employed by partitioned key caches.
The function builds and initializes an array of simple key caches, and then
- initializes the control block structure of the type P_KEY_CACHE_CB that is
- used for a partitioned key cache. The parameter keycache_cb is supposed to
- point to this structure. The number of partitions in the partitioned key
- cache to be built must be passed through the field 'partitions' of this
- structure. The parameter key_cache_block_size specifies the size of the
- blocks in the the simple key caches to be built. The parameters
- division_limit and age_threshold determine the initial values of those
- characteristics of the simple key caches that are used for midpoint
- insertion strategy. The parameter use_mem specifies the total amount of
- memory to be allocated for the key cache blocks in all simple key caches
- and for all auxiliary structures.
+ initializes the control block structure of the type PARTITIONED_KEY_CACHE_CB
+ that is used for a partitioned key cache. The parameter keycache is
+ supposed to point to this structure. The number of partitions in the
+ partitioned key cache to be built must be passed through the field
+ 'partitions' of this structure. The parameter key_cache_block_size specifies
+ the size of the blocks in the the simple key caches to be built.
+ The parameters division_limit and age_threshold determine the initial
+ values of those characteristics of the simple key caches that are used for
+ midpoint insertion strategy. The parameter use_mem specifies the total
+ amount of memory to be allocated for the key cache blocks in all simple key
+ caches and for all auxiliary structures.
RETURN VALUE
total number of blocks in key cache partitions, if successful,
@@ -5152,19 +5145,19 @@ S_KEY_CACHE_CB *get_key_cache_partition_
*/
static
-int p_init_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
int i;
size_t mem_per_cache;
int cnt;
- S_KEY_CACHE_CB *partition;
- S_KEY_CACHE_CB **partition_ptr;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
+ SIMPLE_KEY_CACHE_CB *partition;
+ SIMPLE_KEY_CACHE_CB **partition_ptr;
uint partitions= keycache->partitions;
- int blocks= -1;
- DBUG_ENTER("p_init_key_cache");
+ int blocks= 0;
+ DBUG_ENTER("partitioned_init_key_cache");
keycache->key_cache_block_size = key_cache_block_size;
@@ -5173,9 +5166,9 @@ int p_init_key_cache(void *keycache_cb,
else
{
if(!(partition_ptr=
- (S_KEY_CACHE_CB **) my_malloc(sizeof(S_KEY_CACHE_CB *) * partitions,
- MYF(0))))
- DBUG_RETURN(blocks);
+ (SIMPLE_KEY_CACHE_CB **) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB *) *
+ partitions, MYF(MY_WME))))
+ DBUG_RETURN(-1);
keycache->partition_array= partition_ptr;
}
@@ -5188,36 +5181,35 @@ int p_init_key_cache(void *keycache_cb,
partition= *partition_ptr;
else
{
- if (!(partition= (S_KEY_CACHE_CB *) my_malloc(sizeof(S_KEY_CACHE_CB),
- MYF(0))))
+ if (!(partition=
+ (SIMPLE_KEY_CACHE_CB *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(MY_WME))))
continue;
partition->key_cache_inited= 0;
}
- if ((cnt= s_init_key_cache(partition,
- key_cache_block_size, mem_per_cache,
- division_limit, age_threshold)) <= 0)
+ if ((cnt= init_simple_key_cache(partition,
+ key_cache_block_size, mem_per_cache,
+ division_limit, age_threshold)) <= 0)
{
- s_end_key_cache(partition, 1);
- my_free((uchar *) partition, MYF(0));
+ end_simple_key_cache(partition, 1);
+ my_free(partition, MYF(0));
partition= 0;
if (key_cache_inited)
{
memmove(partition_ptr, partition_ptr+1,
sizeof(partition_ptr)*(partitions-i-1));
}
+ if (!--partitions)
+ break;
if (i == 0)
{
i--;
- partitions--;
- if (partitions)
- mem_per_cache = use_mem / partitions;
+ mem_per_cache = use_mem / partitions;
+ continue;
}
- continue;
}
- if (blocks < 0)
- blocks= 0;
blocks+= cnt;
*partition_ptr++= partition;
}
@@ -5229,6 +5221,9 @@ int p_init_key_cache(void *keycache_cb,
keycache->key_cache_inited= 1;
+ if (!partitions)
+ blocks= -1;
+
DBUG_RETURN(blocks);
}
@@ -5237,8 +5232,8 @@ int p_init_key_cache(void *keycache_cb,
Resize a partitioned key cache
SYNOPSIS
- p_resize_key_cache()
- keycache_cb pointer to the control block of a partitioned key cache
+ resize_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the new key cache
division_limit new division limit (if not zero)
@@ -5247,9 +5242,9 @@ int p_init_key_cache(void *keycache_cb,
DESCRIPTION
This function is the implementation of the resize_key_cache interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for the partitioned
- key cache to be resized.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be resized.
The parameter key_cache_block_size specifies the new size of the blocks in
the simple key caches that comprise the partitioned key cache.
The parameters division_limit and age_threshold determine the new initial
@@ -5263,48 +5258,47 @@ int p_init_key_cache(void *keycache_cb,
0 - otherwise.
NOTES.
- The function first calls s_prepare_resize_key_cache for each simple
+ The function first calls prepare_resize_simple_key_cache for each simple
key cache effectively flushing all dirty pages from it and destroying
- the key cache. Then p_init_key cache is called. This call builds all
- the new array of simple key caches containing the same number of
- elements as the old one. After this the function calls the function
- s_finish_resize_key_cache for each simple key cache from this array.
+ the key cache. Then init_partitioned_key_cache is called. This call builds
+ a new array of simple key caches containing the same number of elements
+ as the old one. After this the function calls the function
+ finish_resize_simple_key_cache for each simple key cache from this array.
This implementation doesn't block the calls and executions of other
functions from the key cache interface. However it assumes that the
- calls of s_resize_key_cache itself are serialized.
-
+ calls of resize_partitioned_key_cache itself are serialized.
*/
static
-int p_resize_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
my_bool cleanup= use_mem == 0;
int blocks= -1;
int err= 0;
- DBUG_ENTER("p_resize_key_cache");
- if (use_mem == 0)
+ DBUG_ENTER("partitioned_resize_key_cache");
+ if (cleanup)
{
- p_end_key_cache(keycache_cb, 0);
- DBUG_RETURN(blocks);
+ end_partitioned_key_cache(keycache, 0);
+ DBUG_RETURN(-1);
}
for (i= 0; i < partitions; i++)
{
- err|= s_prepare_resize_key_cache(keycache->partition_array[i], 0, 1);
+ err|= prepare_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
}
- if (!err && use_mem)
- blocks= p_init_key_cache(keycache_cb, key_cache_block_size, use_mem,
- division_limit, age_threshold);
- if (blocks > 0 && !cleanup)
+ if (!err)
+ blocks= init_partitioned_key_cache(keycache, key_cache_block_size,
+ use_mem, division_limit, age_threshold);
+ if (blocks > 0)
{
for (i= 0; i < partitions; i++)
{
- s_finish_resize_key_cache(keycache->partition_array[i], 0, 1);
+ finish_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
}
}
DBUG_RETURN(blocks);
@@ -5315,17 +5309,17 @@ int p_resize_key_cache(void *keycache_cb
Change key cache parameters of a partitioned key cache
SYNOPSIS
- p_change_key_cache_param()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_change_key_cache_param()
+ keycache pointer to the control block of a partitioned key cache
division_limit new division limit (if not zero)
age_threshold new age threshold (if not zero)
DESCRIPTION
This function is the implementation of the change_key_cache_param interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for the simple key
- cache where new values of the division limit and the age threshold used
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the simple
+ key cache where new values of the division limit and the age threshold used
for midpoint insertion strategy are to be set. The parameters
division_limit and age_threshold provide these new values.
@@ -5333,23 +5327,22 @@ int p_resize_key_cache(void *keycache_cb
none
NOTES
- The function just calls s_change_key_cache_param for each element from the
- array of simple caches that comprise the partitioned key cache.
-
+ The function just calls change_simple_key_cache_param for each element from
+ the array of simple caches that comprise the partitioned key cache.
*/
static
-void p_change_key_cache_param(void *keycache_cb, uint division_limit,
- uint age_threshold)
+void change_partitioned_key_cache_param(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint division_limit,
+ uint age_threshold)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_change_key_cache_param");
+ DBUG_ENTER("partitioned_change_key_cache_param");
for (i= 0; i < partitions; i++)
{
- s_change_key_cache_param(keycache->partition_array[i], division_limit,
- age_threshold);
+ change_simple_key_cache_param(keycache->partition_array[i], division_limit,
+ age_threshold);
}
DBUG_VOID_RETURN;
}
@@ -5359,17 +5352,17 @@ void p_change_key_cache_param(void *keyc
Destroy a partitioned key cache
SYNOPSIS
- p_end_key_cache()
- keycache_cb pointer to the control block of a partitioned key cache
+ end_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
cleanup <=> complete free (free also control block structures
for all simple key caches)
DESCRIPTION
This function is the implementation of the end_key_cache interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for the partitioned
- key cache to be destroyed.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be destroyed.
The function frees the memory allocated for the cache blocks and
auxiliary structures used by simple key caches that comprise the
partitioned key cache. If the value of the parameter cleanup is TRUE
@@ -5378,23 +5371,23 @@ void p_change_key_cache_param(void *keyc
RETURN VALUE
none
-
*/
static
-void p_end_key_cache(void *keycache_cb, my_bool cleanup)
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_end_key_cache");
+ DBUG_ENTER("partitioned_end_key_cache");
DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
for (i= 0; i < partitions; i++)
{
- s_end_key_cache(keycache->partition_array[i], cleanup);
+ end_simple_key_cache(keycache->partition_array[i], cleanup);
}
- if (cleanup) {
+ if (cleanup)
+ {
for (i= 0; i < partitions; i++)
my_free((uchar*) keycache->partition_array[i], MYF(0));
my_free((uchar*) keycache->partition_array, MYF(0));
@@ -5409,8 +5402,8 @@ void p_end_key_cache(void *keycache_cb,
SYNOPSIS
- p_key_cache_read()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_key_cache_read()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file for the block of data to be read
filepos position of the block of data in the file
level determines the weight of the data
@@ -5422,9 +5415,9 @@ void p_end_key_cache(void *keycache_cb,
DESCRIPTION
This function is the implementation of the key_cache_read interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
In a general case the function reads a block of data from the key cache
into the buffer buff of the size specified by the parameter length. The
beginning of the block of data to be read is specified by the parameters
@@ -5432,7 +5425,7 @@ void p_end_key_cache(void *keycache_cb,
of the buffer. The data is read into the buffer in key_cache_block_size
increments. To read each portion the function first finds out in what
partition of the key cache this portion(page) is to be saved, and calls
- s_key_cache_read with the pointer to the corresponding simple key as
+ simple_key_cache_read with the pointer to the corresponding simple key as
its first parameter.
If the parameter return_buffer is not ignored and its value is TRUE, and
the data to be read of the specified size block_length can be read from one
@@ -5445,21 +5438,19 @@ void p_end_key_cache(void *keycache_cb,
RETURN VALUE
Returns address from where the data is placed if successful, 0 - otherwise.
-
*/
static
-uchar *p_key_cache_read(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
uint r_length;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint offset= (uint) (filepos % keycache->key_cache_block_size);
uchar *start= buff;
- DBUG_ENTER("p_key_cache_read");
+ DBUG_ENTER("partitioned_key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
@@ -5471,15 +5462,15 @@ uchar *p_key_cache_read(void *keycache_c
/* Read data in key_cache_block_size increments */
do
{
- S_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
- file, filepos);
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
uchar *ret_buff= 0;
r_length= length;
set_if_smaller(r_length, keycache->key_cache_block_size - offset);
- ret_buff= s_key_cache_read((void *) partition,
- file, filepos, level,
- buff, r_length,
- block_length, return_buffer);
+ ret_buff= simple_key_cache_read((void *) partition,
+ file, filepos, level,
+ buff, r_length,
+ block_length, return_buffer);
if (ret_buff == 0)
DBUG_RETURN(0);
#ifndef THREAD
@@ -5500,8 +5491,8 @@ uchar *p_key_cache_read(void *keycache_c
Insert a block of file data from a buffer into a partitioned key cache
SYNOPSIS
- p_key_cache_insert()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_key_cache_insert()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
@@ -5511,9 +5502,9 @@ uchar *p_key_cache_read(void *keycache_c
DESCRIPTION
This function is the implementation of the key_cache_insert interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned key
- cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
The function writes a block of file data from a buffer into the key cache.
The buffer is specified with the parameters buff and length - the pointer
to the beginning of the buffer and its size respectively. It's assumed
@@ -5521,8 +5512,8 @@ uchar *p_key_cache_read(void *keycache_c
filepos. The data is copied from the buffer in key_cache_block_size
increments. For every portion of data the function finds out in what simple
key cache from the array of partitions the data must be stored, and after
- this calls s_key_cache_insert to copy the data into a key buffer of this
- simple key cache.
+ this calls simple_key_cache_insert to copy the data into a key buffer of
+ this simple key cache.
The parameter level is used to set one characteristic for the key buffers
loaded with the data from buff. The characteristic is used only by the
midpoint insertion strategy.
@@ -5534,18 +5525,16 @@ uchar *p_key_cache_read(void *keycache_c
The function is used by MyISAM to move all blocks from a index file to
the key cache. It can be performed in parallel with reading the file data
from the key buffers by other threads.
-
*/
static
-int p_key_cache_insert(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length)
+int partitioned_key_cache_insert(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
{
uint w_length;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint offset= (uint) (filepos % keycache->key_cache_block_size);
- DBUG_ENTER("p_key_cache_insert");
+ DBUG_ENTER("partitioned_key_cache_insert");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file,(ulong) filepos, length));
@@ -5553,13 +5542,13 @@ int p_key_cache_insert(void *keycache_cb
/* Write data in key_cache_block_size increments */
do
{
- S_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
- file, filepos);
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
w_length= length;
- set_if_smaller(w_length, keycache->key_cache_block_size);
- if (s_key_cache_insert((void *) partition,
- file, filepos, level,
- buff, w_length))
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset);
+ if (simple_key_cache_insert((void *) partition,
+ file, filepos, level,
+ buff, w_length))
DBUG_RETURN(1);
filepos+= w_length;
@@ -5576,8 +5565,8 @@ int p_key_cache_insert(void *keycache_cb
SYNOPSIS
- p_key_cache_write()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_key_cache_write()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file to write data to
filepos position in the file to write data to
level determines the weight of the data
@@ -5591,9 +5580,9 @@ int p_key_cache_insert(void *keycache_cb
DESCRIPTION
This function is the implementation of the key_cache_write interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
In a general case the function copies data from a buffer into the key
cache. The buffer is specified with the parameters buff and length -
the pointer to the beginning of the buffer and its size respectively.
@@ -5601,8 +5590,8 @@ int p_key_cache_insert(void *keycache_cb
starting from the position filepos. The data is copied from the buffer
in key_cache_block_size increments. For every portion of data the
function finds out in what simple key cache from the array of partitions
- the data must be stored, and after this calls s_key_cache_write to copy
- the data into a key buffer of this simple key cache.
+ the data must be stored, and after this calls simple_key_cache_write to
+ copy the data into a key buffer of this simple key cache.
If the value of the parameter dont_write is FALSE then the function
also writes the data into file.
The parameter level is used to set one characteristic for the key buffers
@@ -5610,7 +5599,7 @@ int p_key_cache_insert(void *keycache_cb
the midpoint insertion strategy.
The parameter file_expra provides a pointer to the shared bitmap of
the partitions that may contains dirty pages for the file. This bitmap
- is used to optimize the function p_flush_key_blocks.
+ is used to optimize the function flush_partitioned_key_cache_blocks.
RETURN VALUE
0 if a success, 1 - otherwise.
@@ -5618,22 +5607,20 @@ int p_key_cache_insert(void *keycache_cb
NOTES
This implementation exploits the fact that the function is called only
when a thread has got an exclusive lock for the key file.
-
*/
static
-int p_key_cache_write(void *keycache_cb,
- File file, void *file_extra,
- my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+int partitioned_key_cache_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
uint w_length;
ulonglong *part_map= (ulonglong *) file_extra;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint offset= (uint) (filepos % keycache->key_cache_block_size);
- DBUG_ENTER("p_key_cache_write");
+ DBUG_ENTER("partitioned_key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu length: %u block_length: %u"
" key_block_length: %u",
@@ -5644,15 +5631,16 @@ int p_key_cache_write(void *keycache_cb,
/* Write data in key_cache_block_size increments */
do
{
- S_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
- file, filepos,
- part_map);
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
+ file,
+ filepos,
+ part_map);
w_length = length;
- set_if_smaller(w_length, keycache->key_cache_block_size );
- if (s_key_cache_write(partition,
- file, 0, filepos, level,
- buff, w_length, block_length,
- dont_write))
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset );
+ if (simple_key_cache_write(partition,
+ file, 0, filepos, level,
+ buff, w_length, block_length,
+ dont_write))
DBUG_RETURN(1);
filepos+= w_length;
@@ -5669,8 +5657,8 @@ int p_key_cache_write(void *keycache_cb,
SYNOPSIS
- p_flush_key_blocks()
- keycache_cb pointer to the control block of a partitioned key cache
+ flush_partitioned_key_cache_blocks()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file to flush to
file_extra maps of key cache partitions containing
dirty pages from file (not used)
@@ -5679,9 +5667,9 @@ int p_key_cache_write(void *keycache_cb,
DESCRIPTION
This function is the implementation of the flush_key_blocks interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
In a general case the function flushes the data from all dirty key
buffers related to the file 'file' into this file. The function does
exactly this if the value of the parameter type is FLUSH_KEEP. If the
@@ -5689,12 +5677,12 @@ int p_key_cache_write(void *keycache_cb,
releases the key buffers containing data from 'file' for new usage.
If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
just releases the key buffers containing data from 'file'.
- The function performs the operation by calling s_flush_key_blocks
- for the elements of the array of the simple key caches that comprise
- the partitioned key_cache. If the value of the parameter type is
- FLUSH_KEEP s_flush_key_blocks is called only for the partitions with
- possibly dirty pages marked in the bitmap pointed to by the parameter
- file_extra.
+ The function performs the operation by calling the function
+ flush_simple_key_cache_blocks for the elements of the array of the
+ simple key caches that comprise the partitioned key_cache. If the value
+ of the parameter type is FLUSH_KEEP s_flush_key_blocks is called only
+ for the partitions with possibly dirty pages marked in the bitmap
+ pointed to by the parameter file_extra.
RETURN
0 ok
@@ -5703,35 +5691,30 @@ int p_key_cache_write(void *keycache_cb,
NOTES
This implementation exploits the fact that the function is called only
when a thread has got an exclusive lock for the key file.
-
*/
static
-int p_flush_key_blocks(void *keycache_cb,
- File file, void *file_extra,
- enum flush_type type)
+int flush_partitioned_key_cache_blocks(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ enum flush_type type)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
int err= 0;
ulonglong *dirty_part_map= (ulonglong *) file_extra;
- DBUG_ENTER("p_flush_key_blocks");
+ DBUG_ENTER("partitioned_flush_key_blocks");
DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
for (i= 0; i < partitions; i++)
{
- S_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
if ((type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) &&
- !((*dirty_part_map) & (1<<i)))
+ !((*dirty_part_map) & ((ulonglong) 1 << i)))
continue;
- err+= test(s_flush_key_blocks(partition, file, 0, type));
+ err|= test(flush_simple_key_cache_blocks(partition, file, 0, type));
}
*dirty_part_map= 0;
- if (err > 0)
- err= 1;
-
DBUG_RETURN(err);
}
@@ -5740,38 +5723,36 @@ int p_flush_key_blocks(void *keycache_cb
Reset the counters of a partitioned key cache
SYNOPSIS
- p_reset_key_cache_counters()
+ reset_partitioned_key_cache_counters()
name the name of a key cache
- keycache_cb pointer to the control block of a partitioned key cache
+ keycache pointer to the control block of a partitioned key cache
DESCRIPTION
This function is the implementation of the reset_key_cache_counters
interface function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a partitioned
key cache.
This function resets the values of the statistical counters of the simple
key caches comprising partitioned key cache to 0. It does it by calling
- s_reset_key_cache_counters for each key cache partition.
+ reset_simple_key_cache_counters for each key cache partition.
The parameter name is currently not used.
RETURN
0 on success (always because it can't fail)
-
*/
-static
-int p_reset_key_cache_counters(const char *name __attribute__((unused)),
- void *keycache_cb)
+static int
+reset_partitioned_key_cache_counters(const char *name __attribute__((unused)),
+ PARTITIONED_KEY_CACHE_CB *keycache)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_reset_key_cache_counters");
+ DBUG_ENTER("partitioned_reset_key_cache_counters");
for (i = 0; i < partitions; i++)
{
- s_reset_key_cache_counters(name, keycache->partition_array[i]);
+ reset_simple_key_cache_counters(name, keycache->partition_array[i]);
}
DBUG_RETURN(0);
}
@@ -5781,17 +5762,17 @@ int p_reset_key_cache_counters(const cha
Get statistics for a partition key cache
SYNOPSIS
- p_get_key_cache_statistics()
- keycache_cb pointer to the control block of a partitioned key cache
+ get_partitioned_key_cache_statistics()
+ keycache pointer to the control block of a partitioned key cache
partition_no partition number to get statistics for
key_cache_stats OUT pointer to the structure for the returned statistics
DESCRIPTION
This function is the implementation of the get_key_cache_statistics
interface function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for
+ a partitioned key cache.
If the value of the parameter partition_no is equal to 0 then aggregated
statistics for all partitions is returned in the fields of the
structure key_cache_stat of the type KEY_CACHE_STATISTICS . Otherwise
@@ -5801,37 +5782,38 @@ int p_reset_key_cache_counters(const cha
RETURN
none
-
*/
static
-void p_get_key_cache_statistics(void *keycache_cb, uint partition_no,
- KEY_CACHE_STATISTICS *key_cache_stats)
+void
+get_partitioned_key_cache_statistics(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint partition_no,
+ KEY_CACHE_STATISTICS *keycache_stats)
{
uint i;
- S_KEY_CACHE_CB *partition;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
+ SIMPLE_KEY_CACHE_CB *partition;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_get_key_cache_statistics_");
+ DBUG_ENTER("get_partitioned_key_cache_statistics");
if (partition_no != 0)
{
partition= keycache->partition_array[partition_no-1];
- s_get_key_cache_statistics((void *) partition, 0, key_cache_stats);
+ get_simple_key_cache_statistics((void *) partition, 0, keycache_stats);
DBUG_VOID_RETURN;
}
- key_cache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
- key_cache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ bzero(keycache_stats, sizeof(KEY_CACHE_STATISTICS));
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
for (i = 0; i < partitions; i++)
{
partition= keycache->partition_array[i];
- key_cache_stats->blocks_used+= partition->blocks_used;
- key_cache_stats->blocks_unused+= partition->blocks_unused;
- key_cache_stats->blocks_changed+= partition->global_blocks_changed;
- key_cache_stats->read_requests+= partition->global_cache_r_requests;
- key_cache_stats->reads+= partition->global_cache_read;
- key_cache_stats->write_requests+= partition->global_cache_w_requests;
- key_cache_stats->writes+= partition->global_cache_write;
+ keycache_stats->blocks_used+= partition->blocks_used;
+ keycache_stats->blocks_unused+= partition->blocks_unused;
+ keycache_stats->blocks_changed+= partition->global_blocks_changed;
+ keycache_stats->read_requests+= partition->global_cache_r_requests;
+ keycache_stats->reads+= partition->global_cache_read;
+ keycache_stats->write_requests+= partition->global_cache_w_requests;
+ keycache_stats->writes+= partition->global_cache_write;
}
DBUG_VOID_RETURN;
}
@@ -5840,16 +5822,16 @@ void p_get_key_cache_statistics(void *ke
Get the value of a statistical variable for a partitioned key cache
SYNOPSIS
- p_get_key_cache_stat_value()
- keycache_cb pointer to the control block of a partitioned key cache
+ get_partitioned_key_cache_stat_value()
+ keycache pointer to the control block of a partitioned key cache
var_no the ordered number of a statistical variable
DESCRIPTION
This function is the implementation of the get_key_cache_stat_value
interface function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
This function returns the value of the statistical variable var_no
for this key cache. The variables are numbered starting from 0 to 6.
The returned value is calculated as the sum of the values of the
@@ -5858,24 +5840,24 @@ void p_get_key_cache_statistics(void *ke
RETURN
The value of the specified statistical variable
-
*/
static
-ulonglong p_get_key_cache_stat_value(void *keycache_cb, uint var_no)
+ulonglong
+get_partitioned_key_cache_stat_value(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint var_no)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- size_t var_ofs= s_key_cache_stat_var_offsets[var_no];
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
ulonglong res= 0;
- DBUG_ENTER("p_get_key_cache_stat_value");
+ DBUG_ENTER("get_partitioned_key_cache_stat_value");
- if (var_no < 3)
+ if (var_no < NO_LONG_KEY_CACHE_STAT_VARIABLES)
{
for (i = 0; i < partitions; i++)
{
- S_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
res+= (ulonglong) (*(long *) ((char *) partition + var_ofs));
}
}
@@ -5883,7 +5865,7 @@ ulonglong p_get_key_cache_stat_value(voi
{
for (i = 0; i < partitions; i++)
{
- S_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
res+= *(ulonglong *) ((char *) partition + var_ofs);
}
}
@@ -5901,19 +5883,19 @@ ulonglong p_get_key_cache_stat_value(voi
wrappers must be used for this purpose.
*/
-static KEY_CACHE_FUNCS p_key_cache_funcs =
+static KEY_CACHE_FUNCS partitioned_key_cache_funcs =
{
- p_init_key_cache,
- p_resize_key_cache,
- p_change_key_cache_param,
- p_key_cache_read,
- p_key_cache_insert,
- p_key_cache_write,
- p_flush_key_blocks,
- p_reset_key_cache_counters,
- p_end_key_cache,
- p_get_key_cache_statistics,
- p_get_key_cache_stat_value
+ (INIT_KEY_CACHE) init_partitioned_key_cache,
+ (RESIZE_KEY_CACHE) resize_partitioned_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_partitioned_key_cache_param,
+ (KEY_CACHE_READ) partitioned_key_cache_read,
+ (KEY_CACHE_INSERT) partitioned_key_cache_insert,
+ (KEY_CACHE_WRITE) partitioned_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_partitioned_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_partitioned_key_cache_counters,
+ (END_KEY_CACHE) end_partitioned_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_partitioned_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_partitioned_key_cache_stat_value
};
@@ -5926,12 +5908,12 @@ static KEY_CACHE_FUNCS p_key_cache_funcs
partitioned key caches. Each type (class) has its own implementation of the
basic key cache operations used the MyISAM storage engine. The pointers
to the implementation functions are stored in two static structures of the
- type KEY_CACHE_FUNC: s_key_cache_funcs - for simple key caches, and
- p_key_cache_funcs - for partitioned key caches. When a key cache object is
- created the constructor procedure init_key_cache places a pointer to the
- corresponding table into one of its fields. The procedure also initializes
- a control block for the key cache oject and saves the pointer to this
- block in another field of the key cache object.
+ type KEY_CACHE_FUNC: simple_key_cache_funcs - for simple key caches, and
+ partitioned_key_cache_funcs - for partitioned key caches. When a key cache
+ object is created the constructor procedure init_key_cache places a pointer
+ to the corresponding table into one of its fields. The procedure also
+ initializes a control block for the key cache oject and saves the pointer
+ to this block in another field of the key cache object.
When a key cache wrapper function is invoked for a key cache object to
perform a basic key cache operation it looks into the interface table
associated with the key cache oject and calls the corresponding
@@ -5982,7 +5964,6 @@ static KEY_CACHE_FUNCS p_key_cache_funcs
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
*/
int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
@@ -5997,19 +5978,21 @@ int init_key_cache(KEY_CACHE *keycache,
{
if (partitions == 0)
{
- if (!(keycache_cb= (void *) my_malloc(sizeof(S_KEY_CACHE_CB), MYF(0))))
+ if (!(keycache_cb= (void *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(0))))
return 0;
- ((S_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
keycache->key_cache_type= SIMPLE_KEY_CACHE;
- keycache->interface_funcs= &s_key_cache_funcs;
+ keycache->interface_funcs= &simple_key_cache_funcs;
}
else
{
- if (!(keycache_cb= (void *) my_malloc(sizeof(P_KEY_CACHE_CB), MYF(0))))
+ if (!(keycache_cb= (void *) my_malloc(sizeof(PARTITIONED_KEY_CACHE_CB),
+ MYF(0))))
return 0;
- ((P_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
keycache->key_cache_type= PARTITIONED_KEY_CACHE;
- keycache->interface_funcs= &p_key_cache_funcs;
+ keycache->interface_funcs= &partitioned_key_cache_funcs;
}
keycache->keycache_cb= keycache_cb;
keycache->key_cache_inited= 1;
@@ -6017,14 +6000,15 @@ int init_key_cache(KEY_CACHE *keycache,
if (partitions != 0)
{
- ((P_KEY_CACHE_CB *) keycache_cb)->partitions= partitions;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions= partitions;
}
keycache->can_be_used= 0;
blocks= keycache->interface_funcs->init(keycache_cb, key_cache_block_size,
use_mem, division_limit,
age_threshold);
keycache->partitions= partitions ?
- ((P_KEY_CACHE_CB *) keycache_cb)->partitions : 0;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions :
+ 0;
DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
if (blocks > 0)
keycache->can_be_used= 1;
@@ -6037,7 +6021,7 @@ int init_key_cache(KEY_CACHE *keycache,
SYNOPSIS
resize_key_cache()
- keycache pointer to the key cache to be resized
+ keycache pointer to the key cache to be resized
key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the new key cache
division_limit new division limit (if not zero)
@@ -6064,7 +6048,6 @@ int init_key_cache(KEY_CACHE *keycache,
Currently the function is called when the values of the variables
key_buffer_size and/or key_cache_block_size are being reset for
the key cache keycache.
-
*/
int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
@@ -6074,10 +6057,10 @@ int resize_key_cache(KEY_CACHE *keycache
if (keycache->key_cache_inited)
{
if ((uint) keycache->param_partitions != keycache->partitions && use_mem)
- blocks= repartition_key_cache (keycache,
- key_cache_block_size, use_mem,
- division_limit, age_threshold,
- (uint) keycache->param_partitions);
+ blocks= repartition_key_cache(keycache,
+ key_cache_block_size, use_mem,
+ division_limit, age_threshold,
+ (uint) keycache->param_partitions);
else
{
blocks= keycache->interface_funcs->resize(keycache->keycache_cb,
@@ -6087,10 +6070,10 @@ int resize_key_cache(KEY_CACHE *keycache
if (keycache->partitions)
keycache->partitions=
- ((P_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
+ ((PARTITIONED_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
}
- if (blocks <= 0)
- keycache->can_be_used= 0;
+
+ keycache->can_be_used= (blocks >= 0);
}
return blocks;
}
@@ -6117,7 +6100,6 @@ int resize_key_cache(KEY_CACHE *keycache
Currently the function is called when the values of the variables
key_cache_division_limit and/or key_cache_age_threshold are being reset
for the key cache keycache.
-
*/
void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
@@ -6262,7 +6244,6 @@ uchar *key_cache_read(KEY_CACHE *keycach
the key cache.
It is assumed that it may be performed in parallel with reading the file
data from the key buffers by other threads.
-
*/
int key_cache_insert(KEY_CACHE *keycache,
@@ -6316,7 +6297,6 @@ int key_cache_insert(KEY_CACHE *keycache
NOTES
This implementation may exploit the fact that the function is called only
when a thread has got an exclusive lock for the key file.
-
*/
int key_cache_write(KEY_CACHE *keycache,
@@ -6373,7 +6353,6 @@ int key_cache_write(KEY_CACHE *keycache,
NOTES
Any implementation of the function may exploit the fact that the function
is called only when a thread has got an exclusive lock for the key file.
-
*/
int flush_key_blocks(KEY_CACHE *keycache,
@@ -6406,7 +6385,6 @@ int flush_key_blocks(KEY_CACHE *keycache
NOTES
This procedure is used by process_key_caches() to reset the counters of all
currently used key caches, both the default one and the named ones.
-
*/
int reset_key_cache_counters(const char *name __attribute__((unused)),
@@ -6441,13 +6419,11 @@ int reset_key_cache_counters(const char
RETURN
none
-
*/
void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no,
KEY_CACHE_STATISTICS *key_cache_stats)
{
- bzero(key_cache_stats, sizeof(KEY_CACHE_STATISTICS));
if (keycache->key_cache_inited)
{
keycache->interface_funcs->get_stats(keycache->keycache_cb,
@@ -6484,7 +6460,6 @@ void get_key_cache_statistics(KEY_CACHE
reads 4
write_requests 5
writes 6
-
*/
ulonglong get_key_cache_stat_value(KEY_CACHE *keycache, uint var_no)
@@ -6534,7 +6509,6 @@ ulonglong get_key_cache_stat_value(KEY_C
Currently the function is called when the value of the variable
key_cache_partitions is being reset for the key cache keycache.
-
*/
int repartition_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-29 21:16:12 +0000
+++ b/sql/sql_show.cc 2010-04-01 21:42:40 +0000
@@ -2235,8 +2235,9 @@ static void update_key_cache_stat_var(KE
case offsetof(KEY_CACHE, global_cache_read):
case offsetof(KEY_CACHE, global_cache_w_requests):
case offsetof(KEY_CACHE, global_cache_write):
- var_no= 3+(ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
- sizeof(ulonglong);
+ var_no= NO_LONG_KEY_CACHE_STAT_VARIABLES +
+ (ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
+ sizeof(ulonglong);
*(ulonglong *)((char *) key_cache + ofs)=
get_key_cache_stat_value(key_cache, var_no);
break;
@@ -6643,13 +6644,13 @@ int store_key_cache_table_record(THD *th
KEY_CACHE *key_cache,
uint partitions, uint partition_no)
{
- KEY_CACHE_STATISTICS key_cache_stats;
+ KEY_CACHE_STATISTICS keycache_stats;
uint err;
DBUG_ENTER("store_key_cache_table_record");
- get_key_cache_statistics(key_cache, partition_no, &key_cache_stats);
+ get_key_cache_statistics(key_cache, partition_no, &keycache_stats);
- if (key_cache_stats.mem_size == 0)
+ if (!key_cache->key_cache_inited || keycache_stats.mem_size == 0)
DBUG_RETURN(0);
restore_record(table, s->default_values);
@@ -6669,15 +6670,15 @@ int store_key_cache_table_record(THD *th
table->field[2]->set_notnull();
table->field[2]->store((long) partition_no, TRUE);
}
- table->field[3]->store(key_cache_stats.mem_size, TRUE);
- table->field[4]->store(key_cache_stats.block_size, TRUE);
- table->field[5]->store(key_cache_stats.blocks_used, TRUE);
- table->field[6]->store(key_cache_stats.blocks_unused, TRUE);
- table->field[7]->store(key_cache_stats.blocks_changed, TRUE);
- table->field[8]->store(key_cache_stats.read_requests, TRUE);
- table->field[9]->store(key_cache_stats.reads, TRUE);
- table->field[10]->store(key_cache_stats.write_requests, TRUE);
- table->field[11]->store(key_cache_stats.writes, TRUE);
+ table->field[3]->store(keycache_stats.mem_size, TRUE);
+ table->field[4]->store(keycache_stats.block_size, TRUE);
+ table->field[5]->store(keycache_stats.blocks_used, TRUE);
+ table->field[6]->store(keycache_stats.blocks_unused, TRUE);
+ table->field[7]->store(keycache_stats.blocks_changed, TRUE);
+ table->field[8]->store(keycache_stats.read_requests, TRUE);
+ table->field[9]->store(keycache_stats.reads, TRUE);
+ table->field[10]->store(keycache_stats.write_requests, TRUE);
+ table->field[11]->store(keycache_stats.writes, TRUE);
err= schema_table_store_record(thd, table);
DBUG_RETURN(err);
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2747)
by Igor Babaev 01 Apr '10
by Igor Babaev 01 Apr '10
01 Apr '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100331233728-obczp1ecrffnaa2s
2747 Igor Babaev 2010-04-01
Post-review fixes.
modified:
include/keycache.h
mysql-test/r/key_cache.result
mysql-test/t/key_cache.test
mysys/mf_keycache.c
sql/sql_show.cc
=== modified file 'include/keycache.h'
--- a/include/keycache.h 2010-02-16 16:41:11 +0000
+++ b/include/keycache.h 2010-04-01 21:26:08 +0000
@@ -37,7 +37,6 @@ C_MODE_START
#define MAX_KEY_CACHE_PARTITIONS 64
-
/* The structure to get statistical data about a key cache */
typedef struct st_key_cache_statistics
@@ -53,6 +52,8 @@ typedef struct st_key_cache_statistics
ulonglong writes; /* number of actual writes from buffers into files */
} KEY_CACHE_STATISTICS;
+#define NO_LONG_KEY_CACHE_STAT_VARIABLES 3
+
/* The type of a key cache object */
typedef enum key_cache_type
{
@@ -61,6 +62,55 @@ typedef enum key_cache_type
} KEY_CACHE_TYPE;
+typedef
+ int (*INIT_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ int (*RESIZE_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ void (*CHANGE_KEY_CACHE_PARAM)
+ (void *keycache_cb,
+ uint division_limit, uint age_threshold);
+typedef
+ uchar* (*KEY_CACHE_READ)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int return_buffer);
+typedef
+ int (*KEY_CACHE_INSERT)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length);
+typedef
+ int (*KEY_CACHE_WRITE)
+ (void *keycache_cb,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int force_write);
+typedef
+ int (*FLUSH_KEY_BLOCKS)
+ (void *keycache_cb,
+ int file, void *file_extra,
+ enum flush_type type);
+typedef
+ int (*RESET_KEY_CACHE_COUNTERS)
+ (const char *name, void *keycache_cb);
+typedef
+ void (*END_KEY_CACHE)
+ (void *keycache_cb, my_bool cleanup);
+typedef
+ void (*GET_KEY_CACHE_STATISTICS)
+ (void *keycache_cb, uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats);
+typedef
+ ulonglong (*GET_KEY_CACHE_STAT_VALUE)
+ (void *keycache_cb, uint var_no);
+
/*
An object of the type KEY_CACHE_FUNCS contains pointers to all functions
from the key cache interface.
@@ -74,32 +124,17 @@ typedef enum key_cache_type
typedef struct st_key_cache_funcs
{
- int (*init) (void *, uint key_cache_block_size,
- size_t use_mem, uint division_limit, uint age_threshold);
- int (*resize) (void *, uint key_cache_block_size,
- size_t use_mem, uint division_limit, uint age_threshold);
- void (*change_param) (void *keycache_cb,
- uint division_limit, uint age_threshold);
- uchar* (*read) (void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length, int return_buffer);
- int (*insert) (void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length);
- int (*write) (void *keycache_cb,
- File file, void *file_extra,
- my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length, int force_write);
- int (*flush) (void *keycache_cb,
- int file, void *file_extra,
- enum flush_type type);
- int (*reset_counters) (const char *name, void *keycache_cb);
- void (*end) (void *keycache_cb, my_bool cleanup);
- void (*get_stats) (void *keycache_cb, uint partition_no,
- KEY_CACHE_STATISTICS *key_cache_stats);
- ulonglong (*get_stat_val) (void *keycache_cb, uint var_no);
+ INIT_KEY_CACHE init;
+ RESIZE_KEY_CACHE resize;
+ CHANGE_KEY_CACHE_PARAM change_param;
+ KEY_CACHE_READ read;
+ KEY_CACHE_INSERT insert;
+ KEY_CACHE_WRITE write;
+ FLUSH_KEY_BLOCKS flush;
+ RESET_KEY_CACHE_COUNTERS reset_counters;
+ END_KEY_CACHE end;
+ GET_KEY_CACHE_STATISTICS get_stats;
+ GET_KEY_CACHE_STAT_VALUE get_stat_val;
} KEY_CACHE_FUNCS;
=== modified file 'mysql-test/r/key_cache.result'
--- a/mysql-test/r/key_cache.result 2010-03-31 23:37:28 +0000
+++ b/mysql-test/r/key_cache.result 2010-04-01 21:26:08 +0000
@@ -672,12 +672,12 @@ insert into t2 values (2000, 3, 'yyyy');
select * from information_schema.key_caches where key_cache_name like "keycache2"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
select * from information_schema.key_caches where key_cache_name like "key%"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
-keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
@@ -718,7 +718,7 @@ KEY_CACHE_NAME PARTITIONS PARTITION_NUMB
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
@@ -726,66 +726,72 @@ KEY_CACHE_NAME PARTITIONS PARTITION_NUMB
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where partition_number is null;
+KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 262143 8192 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
insert into t2 values (8000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=64*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=128*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
-keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
drop table t1,t2;
set global keycache1.key_buffer_size=0;
set global keycache2.key_buffer_size=0;
=== modified file 'mysql-test/t/key_cache.test'
--- a/mysql-test/t/key_cache.test 2010-03-31 23:37:28 +0000
+++ b/mysql-test/t/key_cache.test 2010-04-01 21:26:08 +0000
@@ -469,6 +469,8 @@ insert into t2 values (7000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where partition_number is null;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2010-02-16 16:41:11 +0000
+++ b/mysys/mf_keycache.c 2010-04-01 21:26:08 +0000
@@ -49,6 +49,7 @@
One cache can handle many files.
It must contain buffers of the same blocksize.
+
init_key_cache() should be used to init cache handler.
The free list (free_block_list) is a stack like structure.
@@ -151,7 +152,7 @@ typedef struct st_keycache_wqueue
/* Control block for a simple (non-partitioned) key cache */
-typedef struct st_s_key_cache_cb
+typedef struct st_simple_key_cache_cb
{
my_bool key_cache_inited; /* <=> control block is allocated */
my_bool in_resize; /* true during resize operation */
@@ -202,7 +203,7 @@ typedef struct st_s_key_cache_cb
int blocks; /* max number of blocks in the cache */
uint hash_factor; /* factor used to calculate hash function */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
-} S_KEY_CACHE_CB;
+} SIMPLE_KEY_CACHE_CB;
/*
Some compilation flags have been added specifically for this module
@@ -314,12 +315,8 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cac
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
-static int flush_all_key_blocks(S_KEY_CACHE_CB *keycache);
-/*
-static void s_change_key_cache_param(void *keycache_cb, uint division_limit,
- uint age_threshold);
-*/
-static void s_end_key_cache(void *keycache_cb, my_bool cleanup);
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache);
+static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup);
#ifdef THREAD
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
pthread_mutex_t *mutex);
@@ -328,9 +325,9 @@ static void release_whole_queue(KEYCACHE
#define wait_on_queue(wqueue, mutex) do {} while (0)
#define release_whole_queue(wqueue) do {} while (0)
#endif
-static void free_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
#if !defined(DBUG_OFF)
-static void test_key_cache(S_KEY_CACHE_CB *keycache,
+static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
const char *where, my_bool lock);
#endif
#define KEYCACHE_BASE_EXPR(f, pos) \
@@ -433,7 +430,7 @@ static int keycache_pthread_cond_signal(
#define inline /* disabled inline for easier debugging */
static int fail_block(BLOCK_LINK *block);
static int fail_hlink(HASH_LINK *hlink);
-static int cache_empty(S_KEY_CACHE_CB *keycache);
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache);
#endif
@@ -447,8 +444,8 @@ static inline uint next_power(uint value
Initialize a simple key cache
SYNOPSIS
- s_init_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ init_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
key_cache_block_size size of blocks to keep cached data
use_mem memory to use for the key cache buferrs/structures
division_limit division limit (may be zero)
@@ -458,8 +455,8 @@ static inline uint next_power(uint value
This function is the implementation of the init_key_cache interface
function that is employed by simple (non-partitioned) key caches.
The function builds a simple key cache and initializes the control block
- structure of the type S_KEY_CACHE_CB that is used for this key cache.
- The parameter keycache_cb is supposed to point to this structure.
+ structure of the type SIMPLE_KEY_CACHE_CB that is used for this key cache.
+ The parameter keycache is supposed to point to this structure.
The parameter key_cache_block_size specifies the size of the blocks in
the key cache to be built. The parameters division_limit and age_threshhold
determine the initial values of those characteristics of the key cache
@@ -478,19 +475,17 @@ static inline uint next_power(uint value
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
*/
static
-int s_init_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
ulong blocks, hash_links;
size_t length;
int error;
- DBUG_ENTER("init_key_cache");
+ DBUG_ENTER("init_simple_key_cache");
DBUG_ASSERT(key_cache_block_size >= 512);
KEYCACHE_DEBUG_OPEN;
@@ -653,16 +648,16 @@ err:
Prepare for resizing a simple key cache
SYNOPSIS
- s_prepare_resize_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ prepare_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
with_resize_queue <=> resize queue is used
release_lock <=> release the key cache lock before return
DESCRIPTION
This function flushes all dirty pages from a simple key cache and after
- this it destroys the key cache calling s_end_key_cache. The function
- considers the parameter keycache_cb as a pointer to the control block
- structure of the type S_KEY_CACHE_CB for this key cache.
+ this it destroys the key cache calling end_simple_key_cache. The function
+ takes the parameter keycache as a pointer to the control block
+ structure of the type SIMPLE_KEY_CACHE_CB for this key cache.
The parameter with_resize_queue determines weather the resize queue is
involved (MySQL server never uses this queue). The parameter release_lock
says weather the key cache lock must be released before return from
@@ -673,19 +668,18 @@ err:
1 - otherwise.
NOTES
- This function is the called by s_resize_key_cache and p_resize_key_cache
- that resize simple and partitioned key caches respectively.
-
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
*/
static
-int s_prepare_resize_key_cache(void *keycache_cb,
- my_bool with_resize_queue,
- my_bool release_lock)
+int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool release_lock)
{
int res= 0;
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_prepare_resize_key_cache");
+ DBUG_ENTER("prepare_resize_simple_key_cache");
keycache_pthread_mutex_lock(&keycache->cache_lock);
@@ -749,7 +743,7 @@ int s_prepare_resize_key_cache(void *key
KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0);
#endif
- s_end_key_cache(keycache_cb, 0);
+ end_simple_key_cache(keycache, 0);
finish:
if (release_lock)
@@ -762,16 +756,16 @@ finish:
Finalize resizing a simple key cache
SYNOPSIS
- s_finish_resize_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ finish_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
with_resize_queue <=> resize queue is used
acquire_lock <=> acquire the key cache lock at start
DESCRIPTION
This function performs finalizing actions for the operation of
- resizing a simple key cache. The function considers the parameter
- keycache_cb as a pointer to the control block structure of the type
- S_KEY_CACHE_CB for this key cache. The function sets the flag
+ resizing a simple key cache. The function takes the parameter
+ keycache as a pointer to the control block structure of the type
+ SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
in_resize in this structure to FALSE.
The parameter with_resize_queue determines weather the resize queue
is involved (MySQL server never uses this queue).
@@ -782,22 +776,24 @@ finish:
none
NOTES
- This function is the called by s_resize_key_cache and p_resize_key_cache
- that resize simple and partitioned key caches respectively.
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
*/
static
-void s_finish_resize_key_cache(void *keycache_cb,
- my_bool with_resize_queue,
- my_bool acquire_lock)
+void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool acquire_lock)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_finish_resize_key_cache");
+ DBUG_ENTER("finish_resize_simple_key_cache");
if (acquire_lock)
keycache_pthread_mutex_lock(&keycache->cache_lock);
-
+
+ safe_mutex_assert_owner(&keycache->cache_lock);
+
/*
Mark the resize finished. This allows other threads to start a
resize or to request new cache blocks.
@@ -820,8 +816,8 @@ void s_finish_resize_key_cache(void *key
Resize a simple key cache
SYNOPSIS
- s_resize_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
key_cache_block_size size of blocks to keep cached data
use_mem memory to use for the key cache buffers/structures
division_limit new division limit (if not zero)
@@ -830,8 +826,8 @@ void s_finish_resize_key_cache(void *key
DESCRIPTION
This function is the implementation of the resize_key_cache interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for the simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
cache to be resized.
The parameter key_cache_block_size specifies the new size of the blocks in
the key cache. The parameters division_limit and age_threshold
@@ -845,14 +841,14 @@ void s_finish_resize_key_cache(void *key
0 - otherwise.
NOTES.
- The function first calls the function s_prepare_resize_key_cache
+ The function first calls the function prepare_resize_simple_key_cache
to flush all dirty blocks from key cache, to free memory used
for key cache blocks and auxiliary structures. After this the
function builds a new key cache with new parameters.
This implementation doesn't block the calls and executions of other
functions from the key cache interface. However it assumes that the
- calls of s_resize_key_cache itself are serialized.
+ calls of resize_simple_key_cache itself are serialized.
The function starts the operation only when all other threads
performing operations with the key cache let her to proceed
@@ -861,31 +857,30 @@ void s_finish_resize_key_cache(void *key
*/
static
-int s_resize_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
int blocks= 0;
- DBUG_ENTER("s_resize_key_cache");
+ DBUG_ENTER("resize_simple_key_cache");
if (!keycache->key_cache_inited)
- DBUG_RETURN(keycache->disk_blocks);
+ DBUG_RETURN(blocks);
/*
Note that the cache_lock mutex and the resize_queue are left untouched.
We do not lose the cache_lock and will release it only at the end of
this function.
*/
- if (s_prepare_resize_key_cache(keycache_cb, 1, 0))
+ if (prepare_resize_simple_key_cache(keycache, 1, 0))
goto finish;
/* The following will work even if use_mem is 0 */
- blocks= s_init_key_cache(keycache, key_cache_block_size, use_mem,
- division_limit, age_threshold);
+ blocks= init_simple_key_cache(keycache, key_cache_block_size, use_mem,
+ division_limit, age_threshold);
finish:
- s_finish_resize_key_cache(keycache_cb, 1, 0);
+ finish_resize_simple_key_cache(keycache, 1, 0);
DBUG_RETURN(blocks);
}
@@ -894,7 +889,7 @@ finish:
/*
Increment counter blocking resize key cache operation
*/
-static inline void inc_counter_for_resize_op(S_KEY_CACHE_CB *keycache)
+static inline void inc_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
keycache->cnt_for_resize_op++;
}
@@ -904,7 +899,7 @@ static inline void inc_counter_for_resiz
Decrement counter blocking resize key cache operation;
Signal the operation to proceed when counter becomes equal zero
*/
-static inline void dec_counter_for_resize_op(S_KEY_CACHE_CB *keycache)
+static inline void dec_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
if (!--keycache->cnt_for_resize_op)
release_whole_queue(&keycache->waiting_for_resize_cnt);
@@ -915,16 +910,16 @@ static inline void dec_counter_for_resiz
Change key cache parameters of a simple key cache
SYNOPSIS
- s_change_key_cache_param()
- keycache_cb pointer to the control block of a simple key cache
+ change_simple_key_cache_param()
+ keycache pointer to the control block of a simple key cache
division_limit new division limit (if not zero)
age_threshold new age threshold (if not zero)
DESCRIPTION
This function is the implementation of the change_key_cache_param interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for the simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
cache where new values of the division limit and the age threshold used
for midpoint insertion strategy are to be set. The parameters
division_limit and age_threshold provide these new values.
@@ -942,11 +937,10 @@ static inline void dec_counter_for_resiz
*/
static
-void s_change_key_cache_param(void *keycache_cb, uint division_limit,
- uint age_threshold)
+void change_simple_key_cache_param(SIMPLE_KEY_CACHE_CB *keycache, uint division_limit,
+ uint age_threshold)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_change_key_cache_param");
+ DBUG_ENTER("change_simple_key_cache_param");
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (division_limit)
keycache->min_warm_blocks= (keycache->disk_blocks *
@@ -963,15 +957,15 @@ void s_change_key_cache_param(void *keyc
Destroy a simple key cache
SYNOPSIS
- s_end_key_cache()
- keycache_cb pointer to the control block of a simple key cache
+ end_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
cleanup <=> complete free (free also mutex for key cache)
DESCRIPTION
This function is the implementation of the end_key_cache interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for the simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
cache to be destroyed.
The function frees the memory allocated for the key cache blocks and
auxiliary structures. If the value of the parameter cleanup is TRUE
@@ -982,10 +976,9 @@ void s_change_key_cache_param(void *keyc
*/
static
-void s_end_key_cache(void *keycache_cb, my_bool cleanup)
+void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_end_key_cache");
+ DBUG_ENTER("end_simple_key_cache");
DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
if (!keycache->key_cache_inited)
@@ -1276,7 +1269,7 @@ static inline void link_changed(BLOCK_LI
void
*/
-static void link_to_file_list(S_KEY_CACHE_CB *keycache,
+static void link_to_file_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int file,
my_bool unlink_block)
{
@@ -1317,7 +1310,7 @@ static void link_to_file_list(S_KEY_CACH
void
*/
-static void link_to_changed_list(S_KEY_CACHE_CB *keycache,
+static void link_to_changed_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
@@ -1372,8 +1365,8 @@ static void link_to_changed_list(S_KEY_C
not linked in the LRU ring.
*/
-static void link_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block, my_bool hot,
- my_bool at_end)
+static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block,
+ my_bool hot, my_bool at_end)
{
BLOCK_LINK *ins;
BLOCK_LINK **pins;
@@ -1493,7 +1486,7 @@ static void link_block(S_KEY_CACHE_CB *k
See NOTES for link_block
*/
-static void unlink_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
+static void unlink_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE));
DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/
@@ -1551,7 +1544,8 @@ static void unlink_block(S_KEY_CACHE_CB
RETURN
void
*/
-static void reg_requests(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block, int count)
+static void reg_requests(SIMPLE_KEY_CACHE_CB *keycache,
+ BLOCK_LINK *block, int count)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
DBUG_ASSERT(block->hash_link);
@@ -1594,7 +1588,7 @@ static void reg_requests(S_KEY_CACHE_CB
not linked in the LRU ring.
*/
-static void unreg_request(S_KEY_CACHE_CB *keycache,
+static void unreg_request(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int at_end)
{
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
@@ -1683,7 +1677,7 @@ static void remove_reader(BLOCK_LINK *bl
signals on its termination
*/
-static void wait_for_readers(S_KEY_CACHE_CB *keycache,
+static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
#ifdef THREAD
@@ -1732,7 +1726,7 @@ static inline void link_hash(HASH_LINK *
Remove a hash link from the hash table
*/
-static void unlink_hash(S_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
+static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
{
KEYCACHE_DBUG_PRINT("unlink_hash", ("fd: %u pos_ %lu #requests=%u",
(uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests));
@@ -1788,7 +1782,7 @@ static void unlink_hash(S_KEY_CACHE_CB *
Get the hash link for a page
*/
-static HASH_LINK *get_hash_link(S_KEY_CACHE_CB *keycache,
+static HASH_LINK *get_hash_link(SIMPLE_KEY_CACHE_CB *keycache,
int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
@@ -1909,7 +1903,7 @@ restart:
waits until first of this operations links any block back.
*/
-static BLOCK_LINK *find_key_block(S_KEY_CACHE_CB *keycache,
+static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache,
File file, my_off_t filepos,
int init_hits_left,
int wrmode, int *page_st)
@@ -2669,7 +2663,7 @@ restart:
portion is less than read_length, but not less than min_length.
*/
-static void read_block(S_KEY_CACHE_CB *keycache,
+static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, uint read_length,
uint min_length, my_bool primary)
{
@@ -2761,8 +2755,8 @@ static void read_block(S_KEY_CACHE_CB *k
SYNOPSIS
- s_key_cache_read()
- keycache_cb pointer to the control block of a simple key cache
+ simple_key_cache_read()
+ keycache pointer to the control block of a simple key cache
file handler for the file for the block of data to be read
filepos position of the block of data in the file
level determines the weight of the data
@@ -2774,8 +2768,8 @@ static void read_block(S_KEY_CACHE_CB *k
DESCRIPTION
This function is the implementation of the key_cache_read interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
cache.
In a general case the function reads a block of data from the key cache
into the buffer buff of the size specified by the parameter length. The
@@ -2802,17 +2796,16 @@ static void read_block(S_KEY_CACHE_CB *k
*/
-uchar *s_key_cache_read(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
my_bool locked_and_incremented= FALSE;
int error=0;
uchar *start= buff;
- DBUG_ENTER("s_key_cache_read");
+ DBUG_ENTER("simple_key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
@@ -3010,8 +3003,8 @@ end:
Insert a block of file data from a buffer into a simple key cache
SYNOPSIS
- s_key_cache_insert()
- keycache_cb pointer to the control block of a simple key cache
+ simple_key_cache_insert()
+ keycache pointer to the control block of a simple key cache
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
@@ -3021,8 +3014,8 @@ end:
DESCRIPTION
This function is the implementation of the key_cache_insert interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
cache.
The function writes a block of file data from a buffer into the key cache.
The buffer is specified with the parameters buff and length - the pointer
@@ -3045,11 +3038,10 @@ end:
*/
static
-int s_key_cache_insert(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length)
+int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
int error= 0;
DBUG_ENTER("key_cache_insert");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
@@ -3272,8 +3264,8 @@ int s_key_cache_insert(void *keycache_cb
SYNOPSIS
- s_key_cache_write()
- keycache_cb pointer to the control block of a simple key cache
+ simple_key_cache_write()
+ keycache pointer to the control block of a simple key cache
file handler for the file to write data to
file_extra maps of key cache partitions containing
dirty pages from file
@@ -3287,8 +3279,8 @@ int s_key_cache_insert(void *keycache_cb
DESCRIPTION
This function is the implementation of the key_cache_write interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
cache.
In a general case the function copies data from a buffer into the key
cache. The buffer is specified with the parameters buff and length -
@@ -3304,7 +3296,8 @@ int s_key_cache_insert(void *keycache_cb
The parameter file_extra currently makes sense only for simple key caches
that are elements of a partitioned key cache. It provides a pointer to the
shared bitmap of the partitions that may contains dirty pages for the file.
- This bitmap is used to optimize the function p_flush_key_blocks.
+ This bitmap is used to optimize the function
+ flush_partitioned_key_cache_blocks.
RETURN VALUE
0 if a success, 1 - otherwise.
@@ -3316,17 +3309,16 @@ int s_key_cache_insert(void *keycache_cb
*/
static
-int s_key_cache_write(void *keycache_cb,
- File file, void *file_extra __attribute__((unused)),
- my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, void *file_extra __attribute__((unused)),
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
my_bool locked_and_incremented= FALSE;
int error=0;
- DBUG_ENTER("s_key_cache_write");
+ DBUG_ENTER("simple_key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu length: %u block_length: %u"
" key_block_length: %u",
@@ -3641,7 +3633,7 @@ end:
Block must have a request registered on it.
*/
-static void free_block(S_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
KEYCACHE_THREAD_TRACE("free block");
KEYCACHE_DBUG_PRINT("free_block",
@@ -3781,7 +3773,7 @@ static int cmp_sec_link(BLOCK_LINK **a,
free used blocks if requested
*/
-static int flush_cached_blocks(S_KEY_CACHE_CB *keycache,
+static int flush_cached_blocks(SIMPLE_KEY_CACHE_CB *keycache,
File file, BLOCK_LINK **cache,
BLOCK_LINK **end,
enum flush_type type)
@@ -3909,7 +3901,7 @@ static int flush_cached_blocks(S_KEY_CAC
1 error
*/
-static int flush_key_blocks_int(S_KEY_CACHE_CB *keycache,
+static int flush_key_blocks_int(SIMPLE_KEY_CACHE_CB *keycache,
File file, enum flush_type type)
{
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
@@ -4349,8 +4341,8 @@ err:
SYNOPSIS
- s_flush_key_blocks()
- keycache_cb pointer to the control block of a simple key cache
+ flush_simple_key_blocks()
+ keycache pointer to the control block of a simple key cache
file handler for the file to flush to
file_extra maps of key cache partitions containing
dirty pages from file (not used)
@@ -4359,7 +4351,7 @@ err:
DESCRIPTION
This function is the implementation of the flush_key_blocks interface
function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
+ The function takes the parameter keycache as a pointer to the
control block structure of the type S_KEY_CACHE_CB for a simple key
cache.
In a general case the function flushes the data from all dirty key
@@ -4382,12 +4374,11 @@ err:
*/
static
-int s_flush_key_blocks(void *keycache_cb,
- File file,
- void *file_extra __attribute__((unused)),
- enum flush_type type)
+int flush_simple_key_cache_blocks(SIMPLE_KEY_CACHE_CB *keycache,
+ File file,
+ void *file_extra __attribute__((unused)),
+ enum flush_type type)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
int res= 0;
DBUG_ENTER("flush_key_blocks");
DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
@@ -4440,7 +4431,7 @@ int s_flush_key_blocks(void *keycache_cb
!= 0 Error
*/
-static int flush_all_key_blocks(S_KEY_CACHE_CB *keycache)
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache)
{
BLOCK_LINK *block;
uint total_found;
@@ -4546,14 +4537,14 @@ static int flush_all_key_blocks(S_KEY_CA
Reset the counters of a simple key cache
SYNOPSIS
- s_reset_key_cache_counters()
+ reset_simple_key_cache_counters()
name the name of a key cache
- keycache_cb pointer to the control block of a simple key cache
+ keycache pointer to the control block of a simple key cache
DESCRIPTION
This function is the implementation of the reset_key_cache_counters
interface function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
+ The function takes the parameter keycache as a pointer to the
control block structure of the type S_KEY_CACHE_CB for a simple key cache.
This function resets the values of all statistical counters for the key
cache to 0.
@@ -4565,11 +4556,10 @@ static int flush_all_key_blocks(S_KEY_CA
*/
static
-int s_reset_key_cache_counters(const char *name __attribute__((unused)),
- void *keycache_cb)
+int reset_simple_key_cache_counters(const char *name __attribute__((unused)),
+ SIMPLE_KEY_CACHE_CB *keycache)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_reset_key_cache_counters");
+ DBUG_ENTER("reset_simple_key_cache_counters");
if (!keycache->key_cache_inited)
{
DBUG_PRINT("info", ("Key cache %s not initialized.", name));
@@ -4590,9 +4580,10 @@ int s_reset_key_cache_counters(const cha
/*
Test if disk-cache is ok
*/
-static void test_key_cache(S_KEY_CACHE_CB *keycache __attribute__((unused)),
- const char *where __attribute__((unused)),
- my_bool lock __attribute__((unused)))
+static
+void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache __attribute__((unused)),
+ const char *where __attribute__((unused)),
+ my_bool lock __attribute__((unused)))
{
/* TODO */
}
@@ -4604,7 +4595,7 @@ static void test_key_cache(S_KEY_CACHE_C
#define MAX_QUEUE_LEN 100
-static void keycache_dump(S_KEY_CACHE_CB *keycache)
+static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache)
{
FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
struct st_my_thread_var *last;
@@ -4844,7 +4835,7 @@ static int fail_hlink(HASH_LINK *hlink)
return 0; /* Let the assert fail. */
}
-static int cache_empty(S_KEY_CACHE_CB *keycache)
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache)
{
int errcnt= 0;
int idx;
@@ -4887,54 +4878,57 @@ static int cache_empty(S_KEY_CACHE_CB *k
Get statistics for a simple key cache
SYNOPSIS
- get_key_cache_statistics()
- keycache_cb pointer to the control block of a simple key cache
+ get_simple_key_cache_statistics()
+ keycache pointer to the control block of a simple key cache
partition_no partition number (not used)
key_cache_stats OUT pointer to the structure for the returned statistics
DESCRIPTION
This function is the implementation of the get_key_cache_statistics
interface function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key cache.
- This function returns the statistical data for the key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the statistical data for the key cache.
The parameter partition_no is not used by this function.
RETURN
none
-
*/
static
-void s_get_key_cache_statistics(void *keycache_cb,
- uint partition_no __attribute__((unused)),
- KEY_CACHE_STATISTICS *key_cache_stats)
-{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- DBUG_ENTER("s_get_key_cache_statistics");
-
- key_cache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
- key_cache_stats->block_size= (longlong) keycache->key_cache_block_size;
- key_cache_stats->blocks_used= keycache->blocks_used;
- key_cache_stats->blocks_unused= keycache->blocks_unused;
- key_cache_stats->blocks_changed= keycache->global_blocks_changed;
- key_cache_stats->read_requests= keycache->global_cache_r_requests;
- key_cache_stats->reads= keycache->global_cache_read;
- key_cache_stats->write_requests= keycache->global_cache_w_requests;
- key_cache_stats->writes= keycache->global_cache_write;
+void get_simple_key_cache_statistics(SIMPLE_KEY_CACHE_CB *keycache,
+ uint partition_no __attribute__((unused)),
+ KEY_CACHE_STATISTICS *keycache_stats)
+{
+ DBUG_ENTER("simple_get_key_cache_statistics");
+
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ keycache_stats->blocks_used= keycache->blocks_used;
+ keycache_stats->blocks_unused= keycache->blocks_unused;
+ keycache_stats->blocks_changed= keycache->global_blocks_changed;
+ keycache_stats->read_requests= keycache->global_cache_r_requests;
+ keycache_stats->reads= keycache->global_cache_read;
+ keycache_stats->write_requests= keycache->global_cache_w_requests;
+ keycache_stats->writes= keycache->global_cache_write;
DBUG_VOID_RETURN;
}
-static size_t s_key_cache_stat_var_offsets[]=
+/*
+ Offsets of the statistical values in the control block for a simple key cache
+ The first NO_LONG_KEY_CACHE_STAT_VARIABLES=3 are of the ulong type while the
+ remaining are of the ulonglong type.
+ */
+static size_t simple_key_cache_stat_var_offsets[]=
{
- offsetof(S_KEY_CACHE_CB, blocks_used),
- offsetof(S_KEY_CACHE_CB, blocks_unused),
- offsetof(S_KEY_CACHE_CB, global_blocks_changed),
- offsetof(S_KEY_CACHE_CB, global_cache_w_requests),
- offsetof(S_KEY_CACHE_CB, global_cache_write),
- offsetof(S_KEY_CACHE_CB, global_cache_r_requests),
- offsetof(S_KEY_CACHE_CB, global_cache_read)
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_used),
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_unused),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_blocks_changed),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_w_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_write),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_r_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_read)
};
@@ -4942,16 +4936,16 @@ static size_t s_key_cache_stat_var_offse
Get the value of a statistical variable for a simple key cache
SYNOPSIS
- s_get_key_cache_stat_value()
- keycache_cb pointer to the control block of a simple key cache
+ get_simple_key_cache_stat_value()
+ keycache pointer to the control block of a simple key cache
var_no the ordered number of a statistical variable
DESCRIPTION
- This function is the implementation of the s_get_key_cache_stat_value
+ This function is the implementation of the get_simple_key_cache_stat_value
interface function that is employed by simple (non-partitioned) key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type S_KEY_CACHE_CB for a simple key cache.
- This function returns the value of the statistical variable var_no
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the value of the statistical variable var_no
for this key cache. The variables are numbered starting from 0 to 6.
RETURN
@@ -4960,12 +4954,12 @@ static size_t s_key_cache_stat_var_offse
*/
static
-ulonglong s_get_key_cache_stat_value(void *keycache_cb, uint var_no)
+ulonglong get_simple_key_cache_stat_value(SIMPLE_KEY_CACHE_CB *keycache,
+ uint var_no)
{
- S_KEY_CACHE_CB *keycache= (S_KEY_CACHE_CB *) keycache_cb;
- size_t var_ofs= s_key_cache_stat_var_offsets[var_no];
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
ulonglong res= 0;
- DBUG_ENTER("s_get_key_cache_stat_value");
+ DBUG_ENTER("get_simple_key_cache_stat_value");
if (var_no < 3)
res= (ulonglong) (*(long *) ((char *) keycache + var_ofs));
@@ -4985,19 +4979,19 @@ ulonglong s_get_key_cache_stat_value(voi
the MySQL server code directly. We don't do it though.
*/
-static KEY_CACHE_FUNCS s_key_cache_funcs =
+static KEY_CACHE_FUNCS simple_key_cache_funcs =
{
- s_init_key_cache,
- s_resize_key_cache,
- s_change_key_cache_param,
- s_key_cache_read,
- s_key_cache_insert,
- s_key_cache_write,
- s_flush_key_blocks,
- s_reset_key_cache_counters,
- s_end_key_cache,
- s_get_key_cache_statistics,
- s_get_key_cache_stat_value
+ (INIT_KEY_CACHE) init_simple_key_cache,
+ (RESIZE_KEY_CACHE) resize_simple_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_simple_key_cache_param,
+ (KEY_CACHE_READ) simple_key_cache_read,
+ (KEY_CACHE_INSERT) simple_key_cache_insert,
+ (KEY_CACHE_WRITE) simple_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_simple_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_simple_key_cache_counters,
+ (END_KEY_CACHE) end_simple_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_simple_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_simple_key_cache_stat_value
};
@@ -5038,17 +5032,22 @@ static KEY_CACHE_FUNCS s_key_cache_funcs
/* Control block for a partitioned key cache */
-typedef struct st_p_key_cache_cb
+typedef struct st_partitioned_key_cache_cb
{
my_bool key_cache_inited; /*<=> control block is allocated */
- S_KEY_CACHE_CB **partition_array; /* array of the key cache partitions */
- uint partitions; /* number of partitions in the key cache */
+ SIMPLE_KEY_CACHE_CB **partition_array; /* the key cache partitions */
size_t key_cache_mem_size; /* specified size of the cache memory */
uint key_cache_block_size; /* size of the page buffer of a cache block */
-} P_KEY_CACHE_CB;
+ uint partitions; /* number of partitions in the key cache */
+} PARTITIONED_KEY_CACHE_CB;
static
-void p_end_key_cache(void *keycache_cb, my_bool cleanup);
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup);
+
+static int
+reset_partitioned_key_cache_counters(const char *name,
+ PARTITIONED_KEY_CACHE_CB *keycache);
/*
Determine the partition to which the index block to read is ascribed
@@ -5070,11 +5069,12 @@ void p_end_key_cache(void *keycache_cb,
file block is ascribed.
*/
-static
-S_KEY_CACHE_CB *get_key_cache_partition(P_KEY_CACHE_CB *keycache,
- File file, my_off_t filepos)
+static
+SIMPLE_KEY_CACHE_CB *
+get_key_cache_partition(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos)
{
- uint i= KEYCACHE_BASE_EXPR( file, filepos) % keycache->partitions;
+ uint i= KEYCACHE_BASE_EXPR(file, filepos) % keycache->partitions;
return keycache->partition_array[i];
}
@@ -5101,10 +5101,10 @@ S_KEY_CACHE_CB *get_key_cache_partition(
file block is ascribed.
*/
-static
-S_KEY_CACHE_CB *get_key_cache_partition_for_write(P_KEY_CACHE_CB *keycache,
- File file, my_off_t filepos,
- ulonglong* dirty_part_map)
+static SIMPLE_KEY_CACHE_CB
+*get_key_cache_partition_for_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos,
+ ulonglong* dirty_part_map)
{
uint i= KEYCACHE_BASE_EXPR( file, filepos) % keycache->partitions;
*dirty_part_map|= 1<<i;
@@ -5116,8 +5116,8 @@ S_KEY_CACHE_CB *get_key_cache_partition_
Initialize a partitioned key cache
SYNOPSIS
- p_init_key_cache()
- keycache_cb pointer to the control block of a partitioned key cache
+ init_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for all key cache partitions
division_limit division limit (may be zero)
@@ -5127,17 +5127,17 @@ S_KEY_CACHE_CB *get_key_cache_partition_
This function is the implementation of the init_key_cache interface function
that is employed by partitioned key caches.
The function builds and initializes an array of simple key caches, and then
- initializes the control block structure of the type P_KEY_CACHE_CB that is
- used for a partitioned key cache. The parameter keycache_cb is supposed to
- point to this structure. The number of partitions in the partitioned key
- cache to be built must be passed through the field 'partitions' of this
- structure. The parameter key_cache_block_size specifies the size of the
- blocks in the the simple key caches to be built. The parameters
- division_limit and age_threshold determine the initial values of those
- characteristics of the simple key caches that are used for midpoint
- insertion strategy. The parameter use_mem specifies the total amount of
- memory to be allocated for the key cache blocks in all simple key caches
- and for all auxiliary structures.
+ initializes the control block structure of the type PARTITIONED_KEY_CACHE_CB
+ that is used for a partitioned key cache. The parameter keycache is
+ supposed to point to this structure. The number of partitions in the
+ partitioned key cache to be built must be passed through the field
+ 'partitions' of this structure. The parameter key_cache_block_size specifies
+ the size of the blocks in the the simple key caches to be built.
+ The parameters division_limit and age_threshold determine the initial
+ values of those characteristics of the simple key caches that are used for
+ midpoint insertion strategy. The parameter use_mem specifies the total
+ amount of memory to be allocated for the key cache blocks in all simple key
+ caches and for all auxiliary structures.
RETURN VALUE
total number of blocks in key cache partitions, if successful,
@@ -5152,19 +5152,19 @@ S_KEY_CACHE_CB *get_key_cache_partition_
*/
static
-int p_init_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
int i;
size_t mem_per_cache;
int cnt;
- S_KEY_CACHE_CB *partition;
- S_KEY_CACHE_CB **partition_ptr;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
+ SIMPLE_KEY_CACHE_CB *partition;
+ SIMPLE_KEY_CACHE_CB **partition_ptr;
uint partitions= keycache->partitions;
- int blocks= -1;
- DBUG_ENTER("p_init_key_cache");
+ int blocks= 0;
+ DBUG_ENTER("partitioned_init_key_cache");
keycache->key_cache_block_size = key_cache_block_size;
@@ -5173,9 +5173,9 @@ int p_init_key_cache(void *keycache_cb,
else
{
if(!(partition_ptr=
- (S_KEY_CACHE_CB **) my_malloc(sizeof(S_KEY_CACHE_CB *) * partitions,
- MYF(0))))
- DBUG_RETURN(blocks);
+ (SIMPLE_KEY_CACHE_CB **) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB *) *
+ partitions, MYF(MY_WME))))
+ DBUG_RETURN(-1);
keycache->partition_array= partition_ptr;
}
@@ -5188,36 +5188,35 @@ int p_init_key_cache(void *keycache_cb,
partition= *partition_ptr;
else
{
- if (!(partition= (S_KEY_CACHE_CB *) my_malloc(sizeof(S_KEY_CACHE_CB),
- MYF(0))))
+ if (!(partition=
+ (SIMPLE_KEY_CACHE_CB *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(MY_WME))))
continue;
partition->key_cache_inited= 0;
}
- if ((cnt= s_init_key_cache(partition,
- key_cache_block_size, mem_per_cache,
- division_limit, age_threshold)) <= 0)
+ if ((cnt= init_simple_key_cache(partition,
+ key_cache_block_size, mem_per_cache,
+ division_limit, age_threshold)) <= 0)
{
- s_end_key_cache(partition, 1);
- my_free((uchar *) partition, MYF(0));
+ end_simple_key_cache(partition, 1);
+ my_free(partition, MYF(0));
partition= 0;
if (key_cache_inited)
{
memmove(partition_ptr, partition_ptr+1,
sizeof(partition_ptr)*(partitions-i-1));
}
+ if (!--partitions)
+ break;
if (i == 0)
{
i--;
- partitions--;
- if (partitions)
- mem_per_cache = use_mem / partitions;
+ mem_per_cache = use_mem / partitions;
+ continue;
}
- continue;
}
- if (blocks < 0)
- blocks= 0;
blocks+= cnt;
*partition_ptr++= partition;
}
@@ -5229,6 +5228,9 @@ int p_init_key_cache(void *keycache_cb,
keycache->key_cache_inited= 1;
+ if (!partitions)
+ blocks= -1;
+
DBUG_RETURN(blocks);
}
@@ -5237,8 +5239,8 @@ int p_init_key_cache(void *keycache_cb,
Resize a partitioned key cache
SYNOPSIS
- p_resize_key_cache()
- keycache_cb pointer to the control block of a partitioned key cache
+ resize_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the new key cache
division_limit new division limit (if not zero)
@@ -5247,9 +5249,9 @@ int p_init_key_cache(void *keycache_cb,
DESCRIPTION
This function is the implementation of the resize_key_cache interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for the partitioned
- key cache to be resized.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be resized.
The parameter key_cache_block_size specifies the new size of the blocks in
the simple key caches that comprise the partitioned key cache.
The parameters division_limit and age_threshold determine the new initial
@@ -5263,48 +5265,48 @@ int p_init_key_cache(void *keycache_cb,
0 - otherwise.
NOTES.
- The function first calls s_prepare_resize_key_cache for each simple
+ The function first calls prepare_resize_simple_key_cache for each simple
key cache effectively flushing all dirty pages from it and destroying
- the key cache. Then p_init_key cache is called. This call builds all
- the new array of simple key caches containing the same number of
- elements as the old one. After this the function calls the function
- s_finish_resize_key_cache for each simple key cache from this array.
+ the key cache. Then init_partitioned_key_cache is called. This call builds
+ a new array of simple key caches containing the same number of elements
+ as the old one. After this the function calls the function
+ finish_resize_simple_key_cache for each simple key cache from this array.
This implementation doesn't block the calls and executions of other
functions from the key cache interface. However it assumes that the
- calls of s_resize_key_cache itself are serialized.
+ calls of resize_partitioned_key_cache itself are serialized.
*/
static
-int p_resize_key_cache(void *keycache_cb, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
my_bool cleanup= use_mem == 0;
int blocks= -1;
int err= 0;
- DBUG_ENTER("p_resize_key_cache");
- if (use_mem == 0)
+ DBUG_ENTER("partitioned_resize_key_cache");
+ if (cleanup)
{
- p_end_key_cache(keycache_cb, 0);
- DBUG_RETURN(blocks);
+ end_partitioned_key_cache(keycache, 0);
+ DBUG_RETURN(-1);
}
for (i= 0; i < partitions; i++)
{
- err|= s_prepare_resize_key_cache(keycache->partition_array[i], 0, 1);
+ err|= prepare_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
}
- if (!err && use_mem)
- blocks= p_init_key_cache(keycache_cb, key_cache_block_size, use_mem,
- division_limit, age_threshold);
- if (blocks > 0 && !cleanup)
+ if (!err)
+ blocks= init_partitioned_key_cache(keycache, key_cache_block_size,
+ use_mem, division_limit, age_threshold);
+ if (blocks > 0)
{
for (i= 0; i < partitions; i++)
{
- s_finish_resize_key_cache(keycache->partition_array[i], 0, 1);
+ finish_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
}
}
DBUG_RETURN(blocks);
@@ -5315,17 +5317,17 @@ int p_resize_key_cache(void *keycache_cb
Change key cache parameters of a partitioned key cache
SYNOPSIS
- p_change_key_cache_param()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_change_key_cache_param()
+ keycache pointer to the control block of a partitioned key cache
division_limit new division limit (if not zero)
age_threshold new age threshold (if not zero)
DESCRIPTION
This function is the implementation of the change_key_cache_param interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for the simple key
- cache where new values of the division limit and the age threshold used
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the simple
+ key cache where new values of the division limit and the age threshold used
for midpoint insertion strategy are to be set. The parameters
division_limit and age_threshold provide these new values.
@@ -5333,23 +5335,23 @@ int p_resize_key_cache(void *keycache_cb
none
NOTES
- The function just calls s_change_key_cache_param for each element from the
- array of simple caches that comprise the partitioned key cache.
+ The function just calls change_simple_key_cache_param for each element from
+ the array of simple caches that comprise the partitioned key cache.
*/
static
-void p_change_key_cache_param(void *keycache_cb, uint division_limit,
- uint age_threshold)
+void change_partitioned_key_cache_param(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint division_limit,
+ uint age_threshold)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_change_key_cache_param");
+ DBUG_ENTER("partitioned_change_key_cache_param");
for (i= 0; i < partitions; i++)
{
- s_change_key_cache_param(keycache->partition_array[i], division_limit,
- age_threshold);
+ change_simple_key_cache_param(keycache->partition_array[i], division_limit,
+ age_threshold);
}
DBUG_VOID_RETURN;
}
@@ -5359,17 +5361,17 @@ void p_change_key_cache_param(void *keyc
Destroy a partitioned key cache
SYNOPSIS
- p_end_key_cache()
- keycache_cb pointer to the control block of a partitioned key cache
+ end_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
cleanup <=> complete free (free also control block structures
for all simple key caches)
DESCRIPTION
This function is the implementation of the end_key_cache interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for the partitioned
- key cache to be destroyed.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be destroyed.
The function frees the memory allocated for the cache blocks and
auxiliary structures used by simple key caches that comprise the
partitioned key cache. If the value of the parameter cleanup is TRUE
@@ -5382,19 +5384,20 @@ void p_change_key_cache_param(void *keyc
*/
static
-void p_end_key_cache(void *keycache_cb, my_bool cleanup)
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_end_key_cache");
+ DBUG_ENTER("partitioned_end_key_cache");
DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
for (i= 0; i < partitions; i++)
{
- s_end_key_cache(keycache->partition_array[i], cleanup);
+ end_simple_key_cache(keycache->partition_array[i], cleanup);
}
- if (cleanup) {
+ if (cleanup)
+ {
for (i= 0; i < partitions; i++)
my_free((uchar*) keycache->partition_array[i], MYF(0));
my_free((uchar*) keycache->partition_array, MYF(0));
@@ -5409,8 +5412,8 @@ void p_end_key_cache(void *keycache_cb,
SYNOPSIS
- p_key_cache_read()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_key_cache_read()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file for the block of data to be read
filepos position of the block of data in the file
level determines the weight of the data
@@ -5422,9 +5425,9 @@ void p_end_key_cache(void *keycache_cb,
DESCRIPTION
This function is the implementation of the key_cache_read interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
In a general case the function reads a block of data from the key cache
into the buffer buff of the size specified by the parameter length. The
beginning of the block of data to be read is specified by the parameters
@@ -5432,7 +5435,7 @@ void p_end_key_cache(void *keycache_cb,
of the buffer. The data is read into the buffer in key_cache_block_size
increments. To read each portion the function first finds out in what
partition of the key cache this portion(page) is to be saved, and calls
- s_key_cache_read with the pointer to the corresponding simple key as
+ simple_key_cache_read with the pointer to the corresponding simple key as
its first parameter.
If the parameter return_buffer is not ignored and its value is TRUE, and
the data to be read of the specified size block_length can be read from one
@@ -5449,17 +5452,16 @@ void p_end_key_cache(void *keycache_cb,
*/
static
-uchar *p_key_cache_read(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
uint r_length;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint offset= (uint) (filepos % keycache->key_cache_block_size);
uchar *start= buff;
- DBUG_ENTER("p_key_cache_read");
+ DBUG_ENTER("partitioned_key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
@@ -5471,15 +5473,15 @@ uchar *p_key_cache_read(void *keycache_c
/* Read data in key_cache_block_size increments */
do
{
- S_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
- file, filepos);
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
uchar *ret_buff= 0;
r_length= length;
set_if_smaller(r_length, keycache->key_cache_block_size - offset);
- ret_buff= s_key_cache_read((void *) partition,
- file, filepos, level,
- buff, r_length,
- block_length, return_buffer);
+ ret_buff= simple_key_cache_read((void *) partition,
+ file, filepos, level,
+ buff, r_length,
+ block_length, return_buffer);
if (ret_buff == 0)
DBUG_RETURN(0);
#ifndef THREAD
@@ -5500,8 +5502,8 @@ uchar *p_key_cache_read(void *keycache_c
Insert a block of file data from a buffer into a partitioned key cache
SYNOPSIS
- p_key_cache_insert()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_key_cache_insert()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
@@ -5511,9 +5513,9 @@ uchar *p_key_cache_read(void *keycache_c
DESCRIPTION
This function is the implementation of the key_cache_insert interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned key
- cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
The function writes a block of file data from a buffer into the key cache.
The buffer is specified with the parameters buff and length - the pointer
to the beginning of the buffer and its size respectively. It's assumed
@@ -5521,8 +5523,8 @@ uchar *p_key_cache_read(void *keycache_c
filepos. The data is copied from the buffer in key_cache_block_size
increments. For every portion of data the function finds out in what simple
key cache from the array of partitions the data must be stored, and after
- this calls s_key_cache_insert to copy the data into a key buffer of this
- simple key cache.
+ this calls simple_key_cache_insert to copy the data into a key buffer of
+ this simple key cache.
The parameter level is used to set one characteristic for the key buffers
loaded with the data from buff. The characteristic is used only by the
midpoint insertion strategy.
@@ -5538,14 +5540,13 @@ uchar *p_key_cache_read(void *keycache_c
*/
static
-int p_key_cache_insert(void *keycache_cb,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length)
+int partitioned_key_cache_insert(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
{
uint w_length;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint offset= (uint) (filepos % keycache->key_cache_block_size);
- DBUG_ENTER("p_key_cache_insert");
+ DBUG_ENTER("partitioned_key_cache_insert");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file,(ulong) filepos, length));
@@ -5553,13 +5554,13 @@ int p_key_cache_insert(void *keycache_cb
/* Write data in key_cache_block_size increments */
do
{
- S_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
- file, filepos);
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
w_length= length;
- set_if_smaller(w_length, keycache->key_cache_block_size);
- if (s_key_cache_insert((void *) partition,
- file, filepos, level,
- buff, w_length))
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset);
+ if (simple_key_cache_insert((void *) partition,
+ file, filepos, level,
+ buff, w_length))
DBUG_RETURN(1);
filepos+= w_length;
@@ -5576,8 +5577,8 @@ int p_key_cache_insert(void *keycache_cb
SYNOPSIS
- p_key_cache_write()
- keycache_cb pointer to the control block of a partitioned key cache
+ partitioned_key_cache_write()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file to write data to
filepos position in the file to write data to
level determines the weight of the data
@@ -5591,9 +5592,9 @@ int p_key_cache_insert(void *keycache_cb
DESCRIPTION
This function is the implementation of the key_cache_write interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
In a general case the function copies data from a buffer into the key
cache. The buffer is specified with the parameters buff and length -
the pointer to the beginning of the buffer and its size respectively.
@@ -5601,8 +5602,8 @@ int p_key_cache_insert(void *keycache_cb
starting from the position filepos. The data is copied from the buffer
in key_cache_block_size increments. For every portion of data the
function finds out in what simple key cache from the array of partitions
- the data must be stored, and after this calls s_key_cache_write to copy
- the data into a key buffer of this simple key cache.
+ the data must be stored, and after this calls simple_key_cache_write to
+ copy the data into a key buffer of this simple key cache.
If the value of the parameter dont_write is FALSE then the function
also writes the data into file.
The parameter level is used to set one characteristic for the key buffers
@@ -5610,7 +5611,7 @@ int p_key_cache_insert(void *keycache_cb
the midpoint insertion strategy.
The parameter file_expra provides a pointer to the shared bitmap of
the partitions that may contains dirty pages for the file. This bitmap
- is used to optimize the function p_flush_key_blocks.
+ is used to optimize the function flush_partitioned_key_cache_blocks.
RETURN VALUE
0 if a success, 1 - otherwise.
@@ -5622,18 +5623,17 @@ int p_key_cache_insert(void *keycache_cb
*/
static
-int p_key_cache_write(void *keycache_cb,
- File file, void *file_extra,
- my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+int partitioned_key_cache_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
uint w_length;
ulonglong *part_map= (ulonglong *) file_extra;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint offset= (uint) (filepos % keycache->key_cache_block_size);
- DBUG_ENTER("p_key_cache_write");
+ DBUG_ENTER("partitioned_key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu length: %u block_length: %u"
" key_block_length: %u",
@@ -5644,15 +5644,16 @@ int p_key_cache_write(void *keycache_cb,
/* Write data in key_cache_block_size increments */
do
{
- S_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
- file, filepos,
- part_map);
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
+ file,
+ filepos,
+ part_map);
w_length = length;
- set_if_smaller(w_length, keycache->key_cache_block_size );
- if (s_key_cache_write(partition,
- file, 0, filepos, level,
- buff, w_length, block_length,
- dont_write))
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset );
+ if (simple_key_cache_write(partition,
+ file, 0, filepos, level,
+ buff, w_length, block_length,
+ dont_write))
DBUG_RETURN(1);
filepos+= w_length;
@@ -5669,8 +5670,8 @@ int p_key_cache_write(void *keycache_cb,
SYNOPSIS
- p_flush_key_blocks()
- keycache_cb pointer to the control block of a partitioned key cache
+ flush_partitioned_key_cache_blocks()
+ keycache pointer to the control block of a partitioned key cache
file handler for the file to flush to
file_extra maps of key cache partitions containing
dirty pages from file (not used)
@@ -5679,9 +5680,9 @@ int p_key_cache_write(void *keycache_cb,
DESCRIPTION
This function is the implementation of the flush_key_blocks interface
function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
In a general case the function flushes the data from all dirty key
buffers related to the file 'file' into this file. The function does
exactly this if the value of the parameter type is FLUSH_KEEP. If the
@@ -5689,12 +5690,12 @@ int p_key_cache_write(void *keycache_cb,
releases the key buffers containing data from 'file' for new usage.
If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
just releases the key buffers containing data from 'file'.
- The function performs the operation by calling s_flush_key_blocks
- for the elements of the array of the simple key caches that comprise
- the partitioned key_cache. If the value of the parameter type is
- FLUSH_KEEP s_flush_key_blocks is called only for the partitions with
- possibly dirty pages marked in the bitmap pointed to by the parameter
- file_extra.
+ The function performs the operation by calling the function
+ flush_simple_key_cache_blocks for the elements of the array of the
+ simple key caches that comprise the partitioned key_cache. If the value
+ of the parameter type is FLUSH_KEEP s_flush_key_blocks is called only
+ for the partitions with possibly dirty pages marked in the bitmap
+ pointed to by the parameter file_extra.
RETURN
0 ok
@@ -5707,31 +5708,27 @@ int p_key_cache_write(void *keycache_cb,
*/
static
-int p_flush_key_blocks(void *keycache_cb,
- File file, void *file_extra,
- enum flush_type type)
+int flush_partitioned_key_cache_blocks(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ enum flush_type type)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
int err= 0;
ulonglong *dirty_part_map= (ulonglong *) file_extra;
- DBUG_ENTER("p_flush_key_blocks");
+ DBUG_ENTER("partitioned_flush_key_blocks");
DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
for (i= 0; i < partitions; i++)
{
- S_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
if ((type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) &&
- !((*dirty_part_map) & (1<<i)))
+ !((*dirty_part_map) & ((ulonglong) 1 << i)))
continue;
- err+= test(s_flush_key_blocks(partition, file, 0, type));
+ err|= test(flush_simple_key_cache_blocks(partition, file, 0, type));
}
*dirty_part_map= 0;
- if (err > 0)
- err= 1;
-
DBUG_RETURN(err);
}
@@ -5740,19 +5737,19 @@ int p_flush_key_blocks(void *keycache_cb
Reset the counters of a partitioned key cache
SYNOPSIS
- p_reset_key_cache_counters()
+ reset_partitioned_key_cache_counters()
name the name of a key cache
- keycache_cb pointer to the control block of a partitioned key cache
+ keycache pointer to the control block of a partitioned key cache
DESCRIPTION
This function is the implementation of the reset_key_cache_counters
interface function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a partitioned
key cache.
This function resets the values of the statistical counters of the simple
key caches comprising partitioned key cache to 0. It does it by calling
- s_reset_key_cache_counters for each key cache partition.
+ reset_simple_key_cache_counters for each key cache partition.
The parameter name is currently not used.
RETURN
@@ -5760,18 +5757,17 @@ int p_flush_key_blocks(void *keycache_cb
*/
-static
-int p_reset_key_cache_counters(const char *name __attribute__((unused)),
- void *keycache_cb)
+static int
+reset_partitioned_key_cache_counters(const char *name __attribute__((unused)),
+ PARTITIONED_KEY_CACHE_CB *keycache)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_reset_key_cache_counters");
+ DBUG_ENTER("partitioned_reset_key_cache_counters");
for (i = 0; i < partitions; i++)
{
- s_reset_key_cache_counters(name, keycache->partition_array[i]);
+ reset_simple_key_cache_counters(name, keycache->partition_array[i]);
}
DBUG_RETURN(0);
}
@@ -5781,17 +5777,17 @@ int p_reset_key_cache_counters(const cha
Get statistics for a partition key cache
SYNOPSIS
- p_get_key_cache_statistics()
- keycache_cb pointer to the control block of a partitioned key cache
+ get_partitioned_key_cache_statistics()
+ keycache pointer to the control block of a partitioned key cache
partition_no partition number to get statistics for
key_cache_stats OUT pointer to the structure for the returned statistics
DESCRIPTION
This function is the implementation of the get_key_cache_statistics
interface function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for
+ a partitioned key cache.
If the value of the parameter partition_no is equal to 0 then aggregated
statistics for all partitions is returned in the fields of the
structure key_cache_stat of the type KEY_CACHE_STATISTICS . Otherwise
@@ -5805,33 +5801,35 @@ int p_reset_key_cache_counters(const cha
*/
static
-void p_get_key_cache_statistics(void *keycache_cb, uint partition_no,
- KEY_CACHE_STATISTICS *key_cache_stats)
+void
+get_partitioned_key_cache_statistics(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint partition_no,
+ KEY_CACHE_STATISTICS *keycache_stats)
{
uint i;
- S_KEY_CACHE_CB *partition;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
+ SIMPLE_KEY_CACHE_CB *partition;
uint partitions= keycache->partitions;
- DBUG_ENTER("p_get_key_cache_statistics_");
+ DBUG_ENTER("get_partitioned_key_cache_statistics");
if (partition_no != 0)
{
partition= keycache->partition_array[partition_no-1];
- s_get_key_cache_statistics((void *) partition, 0, key_cache_stats);
+ get_simple_key_cache_statistics((void *) partition, 0, keycache_stats);
DBUG_VOID_RETURN;
}
- key_cache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
- key_cache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ bzero(keycache_stats, sizeof(KEY_CACHE_STATISTICS));
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
for (i = 0; i < partitions; i++)
{
partition= keycache->partition_array[i];
- key_cache_stats->blocks_used+= partition->blocks_used;
- key_cache_stats->blocks_unused+= partition->blocks_unused;
- key_cache_stats->blocks_changed+= partition->global_blocks_changed;
- key_cache_stats->read_requests+= partition->global_cache_r_requests;
- key_cache_stats->reads+= partition->global_cache_read;
- key_cache_stats->write_requests+= partition->global_cache_w_requests;
- key_cache_stats->writes+= partition->global_cache_write;
+ keycache_stats->blocks_used+= partition->blocks_used;
+ keycache_stats->blocks_unused+= partition->blocks_unused;
+ keycache_stats->blocks_changed+= partition->global_blocks_changed;
+ keycache_stats->read_requests+= partition->global_cache_r_requests;
+ keycache_stats->reads+= partition->global_cache_read;
+ keycache_stats->write_requests+= partition->global_cache_w_requests;
+ keycache_stats->writes+= partition->global_cache_write;
}
DBUG_VOID_RETURN;
}
@@ -5840,16 +5838,16 @@ void p_get_key_cache_statistics(void *ke
Get the value of a statistical variable for a partitioned key cache
SYNOPSIS
- p_get_key_cache_stat_value()
- keycache_cb pointer to the control block of a partitioned key cache
+ get_partitioned_key_cache_stat_value()
+ keycache pointer to the control block of a partitioned key cache
var_no the ordered number of a statistical variable
DESCRIPTION
This function is the implementation of the get_key_cache_stat_value
interface function that is employed by partitioned key caches.
- The function considers the parameter keycache_cb as a pointer to the
- control block structure of the type P_KEY_CACHE_CB for a partitioned
- key cache.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
This function returns the value of the statistical variable var_no
for this key cache. The variables are numbered starting from 0 to 6.
The returned value is calculated as the sum of the values of the
@@ -5862,20 +5860,21 @@ void p_get_key_cache_statistics(void *ke
*/
static
-ulonglong p_get_key_cache_stat_value(void *keycache_cb, uint var_no)
+ulonglong
+get_partitioned_key_cache_stat_value(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint var_no)
{
uint i;
- P_KEY_CACHE_CB *keycache= (P_KEY_CACHE_CB *) keycache_cb;
uint partitions= keycache->partitions;
- size_t var_ofs= s_key_cache_stat_var_offsets[var_no];
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
ulonglong res= 0;
- DBUG_ENTER("p_get_key_cache_stat_value");
+ DBUG_ENTER("get_partitioned_key_cache_stat_value");
- if (var_no < 3)
+ if (var_no < NO_LONG_KEY_CACHE_STAT_VARIABLES)
{
for (i = 0; i < partitions; i++)
{
- S_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
res+= (ulonglong) (*(long *) ((char *) partition + var_ofs));
}
}
@@ -5883,7 +5882,7 @@ ulonglong p_get_key_cache_stat_value(voi
{
for (i = 0; i < partitions; i++)
{
- S_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
res+= *(ulonglong *) ((char *) partition + var_ofs);
}
}
@@ -5901,19 +5900,19 @@ ulonglong p_get_key_cache_stat_value(voi
wrappers must be used for this purpose.
*/
-static KEY_CACHE_FUNCS p_key_cache_funcs =
+static KEY_CACHE_FUNCS partitioned_key_cache_funcs =
{
- p_init_key_cache,
- p_resize_key_cache,
- p_change_key_cache_param,
- p_key_cache_read,
- p_key_cache_insert,
- p_key_cache_write,
- p_flush_key_blocks,
- p_reset_key_cache_counters,
- p_end_key_cache,
- p_get_key_cache_statistics,
- p_get_key_cache_stat_value
+ (INIT_KEY_CACHE) init_partitioned_key_cache,
+ (RESIZE_KEY_CACHE) resize_partitioned_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_partitioned_key_cache_param,
+ (KEY_CACHE_READ) partitioned_key_cache_read,
+ (KEY_CACHE_INSERT) partitioned_key_cache_insert,
+ (KEY_CACHE_WRITE) partitioned_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_partitioned_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_partitioned_key_cache_counters,
+ (END_KEY_CACHE) end_partitioned_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_partitioned_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_partitioned_key_cache_stat_value
};
@@ -5926,12 +5925,12 @@ static KEY_CACHE_FUNCS p_key_cache_funcs
partitioned key caches. Each type (class) has its own implementation of the
basic key cache operations used the MyISAM storage engine. The pointers
to the implementation functions are stored in two static structures of the
- type KEY_CACHE_FUNC: s_key_cache_funcs - for simple key caches, and
- p_key_cache_funcs - for partitioned key caches. When a key cache object is
- created the constructor procedure init_key_cache places a pointer to the
- corresponding table into one of its fields. The procedure also initializes
- a control block for the key cache oject and saves the pointer to this
- block in another field of the key cache object.
+ type KEY_CACHE_FUNC: simple_key_cache_funcs - for simple key caches, and
+ partitioned_key_cache_funcs - for partitioned key caches. When a key cache
+ object is created the constructor procedure init_key_cache places a pointer
+ to the corresponding table into one of its fields. The procedure also
+ initializes a control block for the key cache oject and saves the pointer
+ to this block in another field of the key cache object.
When a key cache wrapper function is invoked for a key cache object to
perform a basic key cache operation it looks into the interface table
associated with the key cache oject and calls the corresponding
@@ -5997,19 +5996,21 @@ int init_key_cache(KEY_CACHE *keycache,
{
if (partitions == 0)
{
- if (!(keycache_cb= (void *) my_malloc(sizeof(S_KEY_CACHE_CB), MYF(0))))
+ if (!(keycache_cb= (void *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(0))))
return 0;
- ((S_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
keycache->key_cache_type= SIMPLE_KEY_CACHE;
- keycache->interface_funcs= &s_key_cache_funcs;
+ keycache->interface_funcs= &simple_key_cache_funcs;
}
else
{
- if (!(keycache_cb= (void *) my_malloc(sizeof(P_KEY_CACHE_CB), MYF(0))))
+ if (!(keycache_cb= (void *) my_malloc(sizeof(PARTITIONED_KEY_CACHE_CB),
+ MYF(0))))
return 0;
- ((P_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
keycache->key_cache_type= PARTITIONED_KEY_CACHE;
- keycache->interface_funcs= &p_key_cache_funcs;
+ keycache->interface_funcs= &partitioned_key_cache_funcs;
}
keycache->keycache_cb= keycache_cb;
keycache->key_cache_inited= 1;
@@ -6017,14 +6018,15 @@ int init_key_cache(KEY_CACHE *keycache,
if (partitions != 0)
{
- ((P_KEY_CACHE_CB *) keycache_cb)->partitions= partitions;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions= partitions;
}
keycache->can_be_used= 0;
blocks= keycache->interface_funcs->init(keycache_cb, key_cache_block_size,
use_mem, division_limit,
age_threshold);
keycache->partitions= partitions ?
- ((P_KEY_CACHE_CB *) keycache_cb)->partitions : 0;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions :
+ 0;
DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
if (blocks > 0)
keycache->can_be_used= 1;
@@ -6037,7 +6039,7 @@ int init_key_cache(KEY_CACHE *keycache,
SYNOPSIS
resize_key_cache()
- keycache pointer to the key cache to be resized
+ keycache pointer to the key cache to be resized
key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the new key cache
division_limit new division limit (if not zero)
@@ -6074,10 +6076,10 @@ int resize_key_cache(KEY_CACHE *keycache
if (keycache->key_cache_inited)
{
if ((uint) keycache->param_partitions != keycache->partitions && use_mem)
- blocks= repartition_key_cache (keycache,
- key_cache_block_size, use_mem,
- division_limit, age_threshold,
- (uint) keycache->param_partitions);
+ blocks= repartition_key_cache(keycache,
+ key_cache_block_size, use_mem,
+ division_limit, age_threshold,
+ (uint) keycache->param_partitions);
else
{
blocks= keycache->interface_funcs->resize(keycache->keycache_cb,
@@ -6087,10 +6089,10 @@ int resize_key_cache(KEY_CACHE *keycache
if (keycache->partitions)
keycache->partitions=
- ((P_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
+ ((PARTITIONED_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
}
- if (blocks <= 0)
- keycache->can_be_used= 0;
+
+ keycache->can_be_used= (blocks >= 0);
}
return blocks;
}
@@ -6447,7 +6449,6 @@ int reset_key_cache_counters(const char
void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no,
KEY_CACHE_STATISTICS *key_cache_stats)
{
- bzero(key_cache_stats, sizeof(KEY_CACHE_STATISTICS));
if (keycache->key_cache_inited)
{
keycache->interface_funcs->get_stats(keycache->keycache_cb,
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-29 21:16:12 +0000
+++ b/sql/sql_show.cc 2010-04-01 21:26:08 +0000
@@ -2235,8 +2235,9 @@ static void update_key_cache_stat_var(KE
case offsetof(KEY_CACHE, global_cache_read):
case offsetof(KEY_CACHE, global_cache_w_requests):
case offsetof(KEY_CACHE, global_cache_write):
- var_no= 3+(ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
- sizeof(ulonglong);
+ var_no= NO_LONG_KEY_CACHE_STAT_VARIABLES +
+ (ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
+ sizeof(ulonglong);
*(ulonglong *)((char *) key_cache + ofs)=
get_key_cache_stat_value(key_cache, var_no);
break;
@@ -6643,13 +6644,13 @@ int store_key_cache_table_record(THD *th
KEY_CACHE *key_cache,
uint partitions, uint partition_no)
{
- KEY_CACHE_STATISTICS key_cache_stats;
+ KEY_CACHE_STATISTICS keycache_stats;
uint err;
DBUG_ENTER("store_key_cache_table_record");
- get_key_cache_statistics(key_cache, partition_no, &key_cache_stats);
+ get_key_cache_statistics(key_cache, partition_no, &keycache_stats);
- if (key_cache_stats.mem_size == 0)
+ if (!key_cache->key_cache_inited || keycache_stats.mem_size == 0)
DBUG_RETURN(0);
restore_record(table, s->default_values);
@@ -6669,15 +6670,15 @@ int store_key_cache_table_record(THD *th
table->field[2]->set_notnull();
table->field[2]->store((long) partition_no, TRUE);
}
- table->field[3]->store(key_cache_stats.mem_size, TRUE);
- table->field[4]->store(key_cache_stats.block_size, TRUE);
- table->field[5]->store(key_cache_stats.blocks_used, TRUE);
- table->field[6]->store(key_cache_stats.blocks_unused, TRUE);
- table->field[7]->store(key_cache_stats.blocks_changed, TRUE);
- table->field[8]->store(key_cache_stats.read_requests, TRUE);
- table->field[9]->store(key_cache_stats.reads, TRUE);
- table->field[10]->store(key_cache_stats.write_requests, TRUE);
- table->field[11]->store(key_cache_stats.writes, TRUE);
+ table->field[3]->store(keycache_stats.mem_size, TRUE);
+ table->field[4]->store(keycache_stats.block_size, TRUE);
+ table->field[5]->store(keycache_stats.blocks_used, TRUE);
+ table->field[6]->store(keycache_stats.blocks_unused, TRUE);
+ table->field[7]->store(keycache_stats.blocks_changed, TRUE);
+ table->field[8]->store(keycache_stats.read_requests, TRUE);
+ table->field[9]->store(keycache_stats.reads, TRUE);
+ table->field[10]->store(keycache_stats.write_requests, TRUE);
+ table->field[11]->store(keycache_stats.writes, TRUE);
err= schema_table_store_record(thd, table);
DBUG_RETURN(err);
1
0

[Maria-developers] Rev 2767: Fied problem with of compilation without dynamic plugin loading. in file:///Users/bell/maria/bzr/work-maria-5.2-plugin/
by sanja@askmonty.org 01 Apr '10
by sanja@askmonty.org 01 Apr '10
01 Apr '10
At file:///Users/bell/maria/bzr/work-maria-5.2-plugin/
------------------------------------------------------------
revno: 2767
revision-id: sanja(a)askmonty.org-20100401200509-o67qhkcgzv5s9oai
parent: sanja(a)askmonty.org-20100401143451-z7dyg1mj84zf8ue5
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-plugin
timestamp: Thu 2010-04-01 23:05:09 +0300
message:
Fied problem with of compilation without dynamic plugin loading.
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-04-01 14:34:51 +0000
+++ b/sql/sql_plugin.cc 2010-04-01 20:05:09 +0000
@@ -388,6 +388,7 @@ static inline void free_plugin_mem(struc
@retval TRUE ERROR
*/
+#ifdef HAVE_DLOPEN
static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
void *sym, char *dlpath,
int report)
@@ -592,6 +593,7 @@ static my_bool read_maria_plugin_info(st
DBUG_RETURN(FALSE);
}
+#endif HAVE_DLOPEN
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
1
0

Re: [Maria-developers] [Fwd: WorkLog sends out too many mail-copies to maria-developers]
by Kristian Nielsen 01 Apr '10
by Kristian Nielsen 01 Apr '10
01 Apr '10
Bryan Alsdorf <bryan(a)askmonty.org> writes:
> Here is a message from Arjen regarding worklog. I haven't messed with
> it and I believe you are currently maintaining it.
>
> Thoughts?
I agree that Worklog mail sending is annoying/broken as it is now.
Unfortunately I don't know how to fix it, and I don't have the time currently
to investigate.
One thing we could do is disable the worklog-db(a)askmonty.org alias (eg. send
it to /dev/null). This should disable sending the mails to the mailing list at
least.
- Kristian.
> -------- Original Message --------
> Subject: WorkLog sends out too many mail-copies to maria-developers
> Date: Thu, 11 Mar 2010 08:59:22 +1000
> From: Arjen Lentz <arjen(a)openquery.com>
> To: Bryan Alsdorf <bryan(a)askmonty.org>
>
> Hi Bryan
>
> I think worklog is doing fail on mailouts. it sends to maria-
> developers list as well as a direct addressee. as a result is sends
> out multiples to maria-developers. it seems...
> archivist confirms this, for one item he also got 6 identical emails.
>
> Cheers,
> Arjen.
4
3

[Maria-developers] Rev 2766: Maria WL#61 in file:///home/bell/maria/bzr/work-maria-5.2-plugin/
by sanja@askmonty.org 01 Apr '10
by sanja@askmonty.org 01 Apr '10
01 Apr '10
At file:///home/bell/maria/bzr/work-maria-5.2-plugin/
------------------------------------------------------------
revno: 2766
revision-id: sanja(a)askmonty.org-20100401143451-z7dyg1mj84zf8ue5
parent: monty(a)askmonty.org-20100401100115-iz32pn7zhx2e237e
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-plugin
timestamp: Thu 2010-04-01 17:34:51 +0300
message:
Maria WL#61
Interface for maria extensions.
Alternative plugin interface with additional info (maturity and string version).
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt 2010-03-15 11:51:23 +0000
+++ b/CMakeLists.txt 2010-04-01 14:34:51 +0000
@@ -260,7 +260,7 @@
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${PLUGIN_NAME}_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin")
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
@@ -279,7 +279,7 @@
# Special handling for partition(not really pluggable)
IF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_PARTITION_STORAGE_ENGINE")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_partition_plugin")
ENDIF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
# Special handling for tmp tables with the maria engine
=== modified file 'config/ac-macros/plugins.m4'
--- a/config/ac-macros/plugins.m4 2010-03-29 15:14:28 +0000
+++ b/config/ac-macros/plugins.m4 2010-04-01 14:34:51 +0000
@@ -460,7 +460,7 @@
])
])
])
- mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ maria_plugin_defs="$maria_plugin_defs, [builtin_maria_]$2[_plugin]"
[with_plugin_]$2=yes
AC_MSG_RESULT([yes])
m4_ifdef([$11], [
=== modified file 'configure.in'
--- a/configure.in 2010-03-29 15:13:53 +0000
+++ b/configure.in 2010-04-01 14:34:51 +0000
@@ -2872,7 +2872,7 @@
AC_SUBST(mysql_plugin_dirs)
AC_SUBST(mysql_plugin_libs)
-AC_SUBST(mysql_plugin_defs)
+AC_SUBST(maria_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin.h 2010-04-01 14:34:51 +0000
@@ -57,7 +57,10 @@
Plugin API. Common for all plugin types.
*/
+/* MySQL plugin interface version */
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
+/* MariaDB plugin interface version */
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x0100
/*
The allowable types of plugins
@@ -81,6 +84,14 @@
#define PLUGIN_LICENSE_GPL_STRING "GPL"
#define PLUGIN_LICENSE_BSD_STRING "BSD"
+/* definitions of code maturity for plugins */
+#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0
+#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1
+#define MariaDB_PLUGIN_MATURITY_ALPHA 2
+#define MariaDB_PLUGIN_MATURITY_BETA 3
+#define MariaDB_PLUGIN_MATURITY_GAMMA 4
+#define MariaDB_PLUGIN_MATURITY_STABLE 5
+
/*
Macros for beginning and ending plugin declarations. Between
mysql_declare_plugin and mysql_declare_plugin_end there should
@@ -93,11 +104,24 @@
int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
int PSIZE= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin DECLS[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_maria_plugin); \
+struct st_maria_plugin DECLS[]= {
+
#else
+
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \
+MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \
+MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]= {
+
#endif
#define mysql_declare_plugin(NAME) \
@@ -106,7 +130,14 @@
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
builtin_ ## NAME ## _plugin)
+#define maria_declare_plugin(NAME) \
+MARIA_DECLARE_PLUGIN__(NAME, \
+ builtin_maria_ ## NAME ## _plugin_interface_version, \
+ builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_maria_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}
+#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}}
/*
declarations for SHOW STATUS support in plugins
@@ -403,6 +434,30 @@
void * __reserved1; /* reserved for dependency checking */
};
+/*
+ MariaDB extension for plugins declaration structure.
+
+ It also copy current MySQL plugin fields to have more independency
+ in plugins extension
+*/
+
+struct st_maria_plugin
+{
+ int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ void *info; /* pointer to type-specific plugin descriptor */
+ const char *name; /* plugin name */
+ const char *author; /* plugin author (for SHOW PLUGINS) */
+ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
+ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
+ int (*init)(void *); /* the function to invoke when plugin is loaded */
+ int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
+ unsigned int version; /* plugin version (for SHOW PLUGINS) */
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info; /* plugin version string */
+ int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */
+};
+
/*************************************************************************
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
*/
=== modified file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin_auth.h.pp 2010-04-01 14:34:51 +0000
@@ -77,6 +77,22 @@
struct st_mysql_sys_var **system_vars;
void * __reserved1;
};
+struct st_maria_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info;
+ int maturity;
+};
enum enum_ftparser_mode
{
MYSQL_FTPARSER_SIMPLE_MODE= 0,
=== modified file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/auth_socket.c 2010-04-01 14:34:51 +0000
@@ -99,4 +99,21 @@
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+mysql_declare_plugin_end;
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-03-31 18:37:45 +0000
+++ b/plugin/auth/dialog.c 2010-04-01 14:34:51 +0000
@@ -171,6 +171,38 @@
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+maria_declare_plugin_end;
/********************* CLIENT SIDE ***************************************/
/*
=== modified file 'plugin/daemon_example/daemon_example.cc'
--- a/plugin/daemon_example/daemon_example.cc 2007-06-27 14:49:12 +0000
+++ b/plugin/daemon_example/daemon_example.cc 2010-04-01 14:34:51 +0000
@@ -200,3 +200,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(daemon_example)
+{
+ MYSQL_DAEMON_PLUGIN,
+ &daemon_example_plugin,
+ "daemon_example",
+ "Brian Aker",
+ "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",
+ PLUGIN_LICENSE_GPL,
+ daemon_example_plugin_init, /* Plugin Init */
+ daemon_example_plugin_deinit, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'plugin/fulltext/plugin_example.c'
--- a/plugin/fulltext/plugin_example.c 2010-01-04 17:54:42 +0000
+++ b/plugin/fulltext/plugin_example.c 2010-04-01 14:34:51 +0000
@@ -270,4 +270,21 @@
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(ftexample)
+{
+ MYSQL_FTPARSER_PLUGIN, /* type */
+ &simple_parser_descriptor, /* descriptor */
+ "simple_parser", /* name */
+ "MySQL AB", /* author */
+ "Simple Full-Text Parser", /* description */
+ PLUGIN_LICENSE_GPL,
+ simple_parser_plugin_init, /* init function (when loaded) */
+ simple_parser_plugin_deinit,/* deinit function (when unloaded) */
+ 0x0001, /* version */
+ simple_status, /* status variables */
+ simple_system_variables, /* system variables */
+ "0.01", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-03-29 15:13:53 +0000
+++ b/sql/ha_ndbcluster.cc 2010-04-01 14:34:51 +0000
@@ -10564,6 +10564,23 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_storage_engine,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ "Clustered, fault-tolerant tables",
+ PLUGIN_LICENSE_GPL,
+ ndbcluster_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ ndb_status_variables_export,/* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
#else
int Sun_ar_require_a_symbol_here= 0;
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc 2010-04-01 14:34:51 +0000
@@ -6715,5 +6715,22 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_storage_engine,
+ "partition",
+ "Mikael Ronstrom, MySQL AB",
+ "Partition Storage Engine Helper",
+ PLUGIN_LICENSE_GPL,
+ partition_initialize, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#endif
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-04-01 09:04:26 +0000
+++ b/sql/log.cc 2010-04-01 14:34:51 +0000
@@ -6036,3 +6036,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_storage_engine,
+ "binlog",
+ "MySQL AB",
+ "This is a pseudo storage engine to represent the binlog in a transaction",
+ PLUGIN_LICENSE_GPL,
+ binlog_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-04-01 09:04:26 +0000
+++ b/sql/sql_acl.cc 2010-04-01 14:34:51 +0000
@@ -8260,3 +8260,35 @@
}
mysql_declare_plugin_end;
+maria_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_builtin.cc.in'
--- a/sql/sql_builtin.cc.in 2010-03-29 15:13:53 +0000
+++ b/sql/sql_builtin.cc.in 2010-04-01 14:34:51 +0000
@@ -16,13 +16,12 @@
#include <my_global.h>
#include <mysql/plugin.h>
-typedef struct st_mysql_plugin builtin_plugin[];
-
-extern builtin_plugin
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@;
-
-struct st_mysql_plugin *mysqld_builtins[]=
+typedef struct st_maria_plugin builtin_maria_plugin[];
+
+extern builtin_maria_plugin
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@;
+
+struct st_maria_plugin *mariadb_builtins[]=
{
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@,(struct st_maria_plugin *)0
};
-
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_plugin.cc 2010-04-01 14:34:51 +0000
@@ -20,7 +20,7 @@
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
-extern struct st_mysql_plugin *mysqld_builtins[];
+extern struct st_maria_plugin *mariadb_builtins[];
/**
@note The order of the enumeration is critical.
@@ -78,6 +78,14 @@
"_mysql_sizeof_struct_st_plugin_";
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
static int min_plugin_interface_version= MYSQL_PLUGIN_INTERFACE_VERSION & ~0xFF;
+static const char *maria_plugin_interface_version_sym=
+ "_maria_plugin_interface_version_";
+static const char *maria_sizeof_st_plugin_sym=
+ "_maria_sizeof_struct_st_plugin_";
+static const char *maria_plugin_declarations_sym=
+ "_maria_plugin_declarations_";
+static int min_maria_plugin_interface_version=
+ MARIA_PLUGIN_INTERFACE_VERSION & ~0xFF;
#endif
/* Note that 'int version' must be the first field of every plugin
@@ -211,7 +219,7 @@
const char *list);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
int *, char **);
-static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
+static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(THD *thd, struct system_variables *vars);
@@ -368,6 +376,223 @@
}
+/**
+ Reads data from mysql plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report What errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+ /* Determine interface version */
+ if (!sym)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= 0;
+ plugin_dl->mysqlversion= *(int *)sym;
+ /* Versioning */
+ if (plugin_dl->mysqlversion < min_plugin_interface_version ||
+ (plugin_dl->mysqlversion >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ /* convert mysql declaration to maria one */
+ {
+ int i;
+ uint sizeof_st_plugin;
+ struct st_mysql_plugin *old;
+ struct st_maria_plugin *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ DBUG_ASSERT(min_plugin_interface_version == 0);
+ sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
+ }
+
+ for (i= 0;
+ ((struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ {
+
+ cur->type= old->type;
+ cur->info= old->info;
+ cur->name= old->name;
+ cur->author= old->author;
+ cur->descr= old->descr;
+ cur->license= old->license;
+ cur->init= old->init;
+ cur->deinit= old->deinit;
+ cur->version= old->version;
+ cur->status_vars= old->status_vars;
+ cur->system_vars= old->system_vars;
+ /*
+ Something like this should be added to process
+ new mysql plugin versions:
+ if (plugin_dl->mysqlversion > 0x0101)
+ {
+ cur->newfield= CONSTANT_MEANS_UNKNOWN;
+ }
+ else
+ {
+ cur->newfield= old->newfield;
+ }
+ */
+ /* Maria only fields */
+ cur->version_info= "Unknown";
+ cur->maturity= MariaDB_PLUGIN_MATURITY_UNKNOWN;
+ }
+ plugin_dl->allocated= true;
+ plugin_dl->plugins= (struct st_maria_plugin *)cur;
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Reads data from maria plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report what errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+
+ /* Determine interface version */
+ if (!(sym))
+ {
+ /*
+ Actually this branch impossible because in case of absence of maria
+ version we try mysql version.
+ */
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY,
+ maria_plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= *(int *)sym;
+ plugin_dl->mysqlversion= 0;
+ /* Versioning */
+ if (plugin_dl->mariaversion < min_maria_plugin_interface_version ||
+ (plugin_dl->mariaversion >> 8) > (MARIA_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, maria_plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+ if (plugin_dl->mariaversion != MARIA_PLUGIN_INTERFACE_VERSION)
+ {
+ uint sizeof_st_plugin;
+ struct st_maria_plugin *old, *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, maria_sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_sizeof_st_plugin_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (sizeof_st_plugin != sizeof(st_mysql_plugin))
+ {
+ int i;
+ for (i= 0;
+ ((struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ memcpy(cur + i, old, min(sizeof(cur[i]), sizeof_st_plugin));
+
+ sym= cur;
+ plugin_dl->allocated= true;
+ }
+ }
+ plugin_dl->plugins= (struct st_maria_plugin *)sym;
+
+ DBUG_RETURN(FALSE);
+}
+
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
#ifdef HAVE_DLOPEN
@@ -415,22 +640,21 @@
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
DBUG_RETURN(0);
}
- /* Determine interface version */
- if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
+
+ /* Checks which plugin interface present and reads info */
+ if (!(sym= dlsym(plugin_dl.handle, maria_plugin_interface_version_sym)))
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
- DBUG_RETURN(0);
+ if (read_mysql_plugin_info(&plugin_dl,
+ dlsym(plugin_dl.handle,
+ plugin_interface_version_sym),
+ dlpath,
+ report))
+ DBUG_RETURN(0);
}
- plugin_dl.version= *(int *)sym;
- /* Versioning */
- if (plugin_dl.version < min_plugin_interface_version ||
- (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ else
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
- "plugin interface version mismatch");
- DBUG_RETURN(0);
+ if (read_maria_plugin_info(&plugin_dl, sym, dlpath, report))
+ DBUG_RETURN(0);
}
/* link the services in */
@@ -438,7 +662,7 @@
{
if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
{
- uint ver= (uint)(intptr)*(void**)sym;
+ uint ver= (uint)(intptr) *(void **)sym;
if (ver > list_of_services[i].version ||
(ver >> 8) < (list_of_services[i].version >> 8))
{
@@ -449,72 +673,9 @@
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
DBUG_RETURN(0);
}
- *(void**)sym= list_of_services[i].service;
- }
- }
-
- /* Find plugin declarations */
- if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
- DBUG_RETURN(0);
- }
-
- if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
- {
- uint sizeof_st_plugin;
- struct st_mysql_plugin *old, *cur;
- char *ptr= (char *)sym;
-
- if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
- sizeof_st_plugin= *(int *)sym;
- else
- {
-#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
- DBUG_RETURN(0);
-#else
- /*
- When the following assert starts failing, we'll have to switch
- to the upper branch of the #ifdef
- */
- DBUG_ASSERT(min_plugin_interface_version == 0);
- sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
-#endif
- }
-
- if (sizeof_st_plugin != sizeof(st_mysql_plugin))
- {
- for (i= 0;
- ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- /* no op */;
-
- cur= (struct st_mysql_plugin*)
- my_malloc((i+1)*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
- if (!cur)
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
- DBUG_RETURN(0);
- }
- /*
- All st_plugin fields not initialized in the plugin explicitly, are
- set to 0. It matches C standard behaviour for struct initializers that
- have less values than the struct definition.
- */
- for (i=0;
- (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
-
- sym= cur;
- plugin_dl.allocated= true;
- }
- }
- plugin_dl.plugins= (struct st_mysql_plugin *)sym;
+ *(void **)sym= list_of_services[i].service;
+ }
+ }
/* Duplicate and convert dll name */
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
@@ -756,7 +917,7 @@
int *argc, char **argv, int report)
{
struct st_plugin_int tmp;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
DBUG_ENTER("plugin_add");
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
{
@@ -1161,8 +1322,8 @@
{
uint i;
bool is_myisam;
- struct st_mysql_plugin **builtins;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin **builtins;
+ struct st_maria_plugin *plugin;
struct st_plugin_int tmp, *plugin_ptr, **reap;
MEM_ROOT tmp_root;
bool reaped_mandatory_plugin= FALSE;
@@ -1201,7 +1362,7 @@
/*
First we register builtin plugins
*/
- for (builtins= mysqld_builtins; *builtins; builtins++)
+ for (builtins= mariadb_builtins; *builtins; builtins++)
{
for (plugin= *builtins; plugin->info; plugin++)
{
@@ -1316,7 +1477,7 @@
}
-static bool register_builtin(struct st_mysql_plugin *plugin,
+static bool register_builtin(struct st_maria_plugin *plugin,
struct st_plugin_int *tmp,
struct st_plugin_int **ptr)
{
@@ -1352,7 +1513,7 @@
RETURN
false - plugin registered successfully
*/
-bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
+bool plugin_register_builtin(THD *thd, struct st_maria_plugin *plugin)
{
struct st_plugin_int tmp, *ptr;
bool result= true;
@@ -1481,7 +1642,7 @@
char buffer[FN_REFLEN];
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
struct st_plugin_dl *plugin_dl;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
char *p= buffer;
DBUG_ENTER("plugin_load_list");
while (list)
=== modified file 'sql/sql_plugin.h'
--- a/sql/sql_plugin.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_plugin.h 2010-04-01 14:34:51 +0000
@@ -52,8 +52,9 @@
{
LEX_STRING dl;
void *handle;
- struct st_mysql_plugin *plugins;
- int version;
+ struct st_maria_plugin *plugins;
+ int mysqlversion;
+ int mariaversion;
bool allocated;
uint ref_count; /* number of plugins loaded from the library */
};
@@ -63,7 +64,7 @@
struct st_plugin_int
{
LEX_STRING name;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
struct st_plugin_dl *plugin_dl;
uint state;
uint ref_count; /* number of threads using the plugin */
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_show.cc 2010-04-01 14:34:51 +0000
@@ -94,11 +94,21 @@
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
}
+
+static const LEX_STRING maturity_name[]={
+ { C_STRING_WITH_LEN("Unknown") },
+ { C_STRING_WITH_LEN("Experimental") },
+ { C_STRING_WITH_LEN("Alpha") },
+ { C_STRING_WITH_LEN("Beta") },
+ { C_STRING_WITH_LEN("Gamma") },
+ { C_STRING_WITH_LEN("Stable") }};
+
+
static my_bool show_plugins(THD *thd, plugin_ref plugin,
void *arg)
{
TABLE *table= (TABLE*) arg;
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
CHARSET_INFO *cs= system_charset_info;
char version_buf[20];
@@ -143,7 +153,7 @@
table->field[5]->set_notnull();
table->field[6]->store(version_buf,
make_version_string(version_buf, sizeof(version_buf),
- plugin_dl->version),
+ plugin_dl->mariaversion),
cs);
table->field[6]->set_notnull();
}
@@ -186,6 +196,26 @@
}
table->field[9]->set_notnull();
+ if ((uint) plug->maturity <= MariaDB_PLUGIN_MATURITY_STABLE)
+ table->field[10]->store(maturity_name[plug->maturity].str,
+ maturity_name[plug->maturity].length,
+ cs);
+ else
+ {
+ DBUG_ASSERT(0);
+ table->field[10]->store("Unknown", 7, cs);
+ }
+ table->field[10]->set_notnull();
+
+ if (plug->version_info)
+ {
+ table->field[11]->store(plug->version_info,
+ strlen(plug->version_info), cs);
+ table->field[11]->set_notnull();
+ }
+ else
+ table->field[11]->set_null();
+
return schema_table_store_record(thd, table);
}
@@ -4398,7 +4428,7 @@
if (plugin_state(plugin) != PLUGIN_IS_READY)
{
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
if (!(wild && wild[0] &&
wild_case_compare(scs, plug->name,wild)))
{
@@ -7095,6 +7125,8 @@
{"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
+ {"PLUGIN_MATURITY", 12, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
+ {"PLUGIN_AUTH_VERSION", 80, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
=== modified file 'storage/archive/ha_archive.cc'
--- a/storage/archive/ha_archive.cc 2010-03-04 08:03:07 +0000
+++ b/storage/archive/ha_archive.cc 2010-04-01 14:34:51 +0000
@@ -1655,4 +1655,21 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_storage_engine,
+ "ARCHIVE",
+ "Brian Aker, MySQL AB",
+ "Archive storage engine",
+ PLUGIN_LICENSE_GPL,
+ archive_db_init, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0300 /* 3.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/blackhole/ha_blackhole.cc'
--- a/storage/blackhole/ha_blackhole.cc 2009-10-16 10:29:42 +0000
+++ b/storage/blackhole/ha_blackhole.cc 2010-04-01 14:34:51 +0000
@@ -369,3 +369,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_storage_engine,
+ "BLACKHOLE",
+ "MySQL AB",
+ "/dev/null storage engine (anything you write to it disappears)",
+ PLUGIN_LICENSE_GPL,
+ blackhole_init, /* Plugin Init */
+ blackhole_fini, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/csv/ha_tina.cc'
--- a/storage/csv/ha_tina.cc 2009-12-03 11:19:05 +0000
+++ b/storage/csv/ha_tina.cc 2010-04-01 14:34:51 +0000
@@ -1636,4 +1636,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
-
+maria_declare_plugin(csv)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &csv_storage_engine,
+ "CSV",
+ "Brian Aker, MySQL AB",
+ "CSV storage engine",
+ PLUGIN_LICENSE_GPL,
+ tina_init_func, /* Plugin Init */
+ tina_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc 2010-04-01 14:34:51 +0000
@@ -924,3 +924,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(example)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &example_storage_engine,
+ "EXAMPLE",
+ "Brian Aker, MySQL AB",
+ "Example storage engine",
+ PLUGIN_LICENSE_GPL,
+ example_init_func, /* Plugin Init */
+ example_done_func, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ func_status, /* status variables */
+ example_system_variables, /* system variables */
+ "0.1", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federated/ha_federated.cc'
--- a/storage/federated/ha_federated.cc 2009-09-07 20:50:10 +0000
+++ b/storage/federated/ha_federated.cc 2010-04-01 14:34:51 +0000
@@ -3379,3 +3379,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ "Federated MySQL storage engine",
+ PLUGIN_LICENSE_GPL,
+ federated_db_init, /* Plugin Init */
+ federated_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 2010-03-10 10:32:14 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2010-04-01 14:34:51 +0000
@@ -3505,9 +3505,26 @@
PLUGIN_LICENSE_GPL,
federatedx_db_init, /* Plugin Init */
federatedx_done, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
+ 0x0200 /* 2.0 */,
NULL, /* status variables */
NULL, /* system variables */
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_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 */
+ 0x0200 /* 2.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "2.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/heap/ha_heap.cc'
--- a/storage/heap/ha_heap.cc 2009-09-07 20:50:10 +0000
+++ b/storage/heap/ha_heap.cc 2010-04-01 14:34:51 +0000
@@ -767,3 +767,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_storage_engine,
+ "MEMORY",
+ "MySQL AB",
+ "Hash based, stored in memory, useful for temporary tables",
+ PLUGIN_LICENSE_GPL,
+ heap_init,
+ NULL,
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/ibmdb2i/ha_ibmdb2i.cc'
--- a/storage/ibmdb2i/ha_ibmdb2i.cc 2009-12-11 07:01:16 +0000
+++ b/storage/ibmdb2i/ha_ibmdb2i.cc 2010-04-01 14:34:51 +0000
@@ -3357,3 +3357,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ibmdb2i)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ibmdb2i_storage_engine,
+ "IBMDB2I",
+ "The IBM development team in Rochester, Minnesota",
+ "IBM DB2 for i Storage Engine",
+ PLUGIN_LICENSE_GPL,
+ ibmdb2i_init_func, /* Plugin Init */
+ ibmdb2i_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ ibmdb2i_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_UNKNOWN /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2010-03-15 11:51:23 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2010-04-01 14:34:51 +0000
@@ -8930,6 +8930,23 @@
NULL /* reserved */
}
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase OY",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ innodb_status_variables_export, /* status variables */
+ innobase_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE, /* maturity */
+}
+maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/innodb_plugin/handler/i_s.cc'
--- a/storage/innodb_plugin/handler/i_s.cc 2009-10-12 12:00:56 +0000
+++ b/storage/innodb_plugin/handler/i_s.cc 2010-04-01 14:34:51 +0000
@@ -455,6 +455,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -730,6 +783,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -913,6 +1019,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -1245,6 +1404,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1295,6 +1507,60 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -1511,6 +1777,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1561,6 +1880,60 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ha_maria.cc 2010-04-01 14:34:51 +0000
@@ -3471,9 +3471,26 @@
PLUGIN_LICENSE_GPL,
ha_maria_init, /* Plugin Init */
NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
+ 0x0105, /* 1.5 */
status_variables, /* status variables */
system_variables, /* system variables */
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(maria)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &maria_storage_engine,
+ "MARIA",
+ "MySQL AB",
+ "Crash-safe tables with MyISAM heritage",
+ PLUGIN_LICENSE_GPL,
+ ha_maria_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0105, /* 1.5 */
+ status_variables, /* status variables */
+ system_variables, /* system variables */
+ "1.5", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc 2010-01-04 17:54:42 +0000
+++ b/storage/myisam/ha_myisam.cc 2010-04-01 14:34:51 +0000
@@ -2174,6 +2174,23 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_storage_engine,
+ "MyISAM",
+ "MySQL AB",
+ "Default engine as of MySQL 3.23 with great performance",
+ PLUGIN_LICENSE_GPL,
+ myisam_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#ifdef HAVE_QUERY_CACHE
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2010-03-30 12:36:49 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2010-04-01 14:34:51 +0000
@@ -1289,3 +1289,20 @@
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_storage_engine,
+ "MRG_MYISAM",
+ "MySQL AB",
+ "Collection of identical MyISAM tables",
+ PLUGIN_LICENSE_GPL,
+ myisammrg_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-31 18:37:45 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-04-01 14:34:51 +0000
@@ -5919,6 +5919,40 @@
drizzle_declare_plugin_end;
#else
mysql_declare_plugin_end;
+#ifdef MARIADB_BASE_VERSION
+maria_declare_plugin(pbxt)
+{ /* PBXT */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &pbxt_storage_engine,
+ "PBXT",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "High performance, multi-versioning transactional engine",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init, /* Plugin Init */
+ pbxt_end, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ NULL, /* status variables */
+ pbxt_system_variables, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+},
+{ /* PBXT_STATISTICS */
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &pbxt_statitics,
+ "PBXT_STATISTICS",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "PBXT internal system statitics",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init_statistics, /* plugin init */
+ pbxt_exit_statistics, /* plugin deinit */
+ 0x0005,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
+#endif
#endif
#if defined(XT_WIN) && defined(XT_COREDUMP)
=== modified file 'storage/xtradb/handler/ha_innodb.cc'
--- a/storage/xtradb/handler/ha_innodb.cc 2010-02-01 06:14:12 +0000
+++ b/storage/xtradb/handler/ha_innodb.cc 2010-04-01 14:34:51 +0000
@@ -10818,6 +10818,39 @@
i_s_innodb_admin_command,
i_s_innodb_patches
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{ /* InnoDB */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase Oy",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ INNODB_VERSION_SHORT,
+ innodb_status_variables_export,/* status variables */
+ innobase_system_variables, /* system variables */
+ INNODB_VERSION_STR, /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+},
+i_s_innodb_rseg_maria,
+i_s_innodb_buffer_pool_pages_maria,
+i_s_innodb_buffer_pool_pages_index_maria,
+i_s_innodb_buffer_pool_pages_blob_maria,
+i_s_innodb_trx_maria,
+i_s_innodb_locks_maria,
+i_s_innodb_lock_waits_maria,
+i_s_innodb_cmp_maria,
+i_s_innodb_cmp_reset_maria,
+i_s_innodb_cmpmem_maria,
+i_s_innodb_cmpmem_reset_maria,
+i_s_innodb_table_stats_maria,
+i_s_innodb_index_stats_maria,
+i_s_innodb_admin_command_maria,
+i_s_innodb_patches_maria
+maria_declare_plugin_end;
+
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/xtradb/handler/i_s.cc'
--- a/storage/xtradb/handler/i_s.cc 2010-03-31 20:50:54 +0000
+++ b/storage/xtradb/handler/i_s.cc 2010-04-01 14:34:51 +0000
@@ -393,6 +393,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_patches_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "XTRADB_ENHANCEMENTS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Enhancements applied to InnoDB plugin"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_patches_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
{
@@ -1040,6 +1093,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1089,6 +1195,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1138,6 +1297,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
@@ -1373,6 +1585,60 @@
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -1648,6 +1914,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -1831,6 +2150,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -2163,6 +2535,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2213,6 +2638,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -2431,6 +2909,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2481,6 +3012,60 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
@@ -2660,6 +3245,59 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_RSEG"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB rollback segment information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_rseg_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
@@ -2940,6 +3578,23 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
@@ -2956,6 +3611,23 @@
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
@@ -3121,3 +3793,20 @@
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
=== modified file 'storage/xtradb/handler/i_s.h'
--- a/storage/xtradb/handler/i_s.h 2009-11-04 20:11:12 +0000
+++ b/storage/xtradb/handler/i_s.h 2010-04-01 14:34:51 +0000
@@ -42,4 +42,20 @@
extern struct st_mysql_plugin i_s_innodb_index_stats;
extern struct st_mysql_plugin i_s_innodb_admin_command;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria;
+extern struct st_maria_plugin i_s_innodb_trx_maria;
+extern struct st_maria_plugin i_s_innodb_locks_maria;
+extern struct st_maria_plugin i_s_innodb_lock_waits_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_reset_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_reset_maria;
+extern struct st_maria_plugin i_s_innodb_patches_maria;
+extern struct st_maria_plugin i_s_innodb_rseg_maria;
+extern struct st_maria_plugin i_s_innodb_table_stats_maria;
+extern struct st_maria_plugin i_s_innodb_index_stats_maria;
+extern struct st_maria_plugin i_s_innodb_admin_command_maria;
+
#endif /* i_s_h */
1
0

[Maria-developers] Rev 2761: Maria WL#61 in file:///Users/bell/maria/bzr/work-maria-5.2-engine-backup/
by sanja@askmonty.org 01 Apr '10
by sanja@askmonty.org 01 Apr '10
01 Apr '10
At file:///Users/bell/maria/bzr/work-maria-5.2-engine-backup/
------------------------------------------------------------
revno: 2761
revision-id: sanja(a)askmonty.org-20100401121502-80l92vwisynnoizv
parent: sanja(a)askmonty.org-20100330123515-4p8q03xccl3d6k59
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-engine-backup
timestamp: Thu 2010-04-01 15:15:02 +0300
message:
Maria WL#61
Interface for maria extensions.
Alternative plugin interface with additional info (maturity and string version).
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt 2010-03-15 11:51:23 +0000
+++ b/CMakeLists.txt 2010-04-01 12:15:02 +0000
@@ -260,7 +260,7 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${PLUGIN_NAME}_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin")
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
@@ -279,7 +279,7 @@ ENDFOREACH(SUBDIR ${STORAGE_SUBDIRS})
# Special handling for partition(not really pluggable)
IF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_PARTITION_STORAGE_ENGINE")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_partition_plugin")
ENDIF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
# Special handling for tmp tables with the maria engine
=== modified file 'config/ac-macros/plugins.m4'
--- a/config/ac-macros/plugins.m4 2010-03-29 15:14:28 +0000
+++ b/config/ac-macros/plugins.m4 2010-04-01 12:15:02 +0000
@@ -460,7 +460,7 @@ dnl Although this is "pretty", it breaks
])
])
])
- mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ maria_plugin_defs="$maria_plugin_defs, [builtin_maria_]$2[_plugin]"
[with_plugin_]$2=yes
AC_MSG_RESULT([yes])
m4_ifdef([$11], [
=== modified file 'configure.in'
--- a/configure.in 2010-03-29 15:13:53 +0000
+++ b/configure.in 2010-04-01 12:15:02 +0000
@@ -2872,7 +2872,7 @@ AC_SUBST(server_scripts)
AC_SUBST(mysql_plugin_dirs)
AC_SUBST(mysql_plugin_libs)
-AC_SUBST(mysql_plugin_defs)
+AC_SUBST(maria_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin.h 2010-04-01 12:15:02 +0000
@@ -57,7 +57,10 @@ typedef struct st_mysql_xid MYSQL_XID;
Plugin API. Common for all plugin types.
*/
+/* MySQL plugin interface version */
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
+/* MariaDB plugin interface version */
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x0100
/*
The allowable types of plugins
@@ -81,6 +84,14 @@ typedef struct st_mysql_xid MYSQL_XID;
#define PLUGIN_LICENSE_GPL_STRING "GPL"
#define PLUGIN_LICENSE_BSD_STRING "BSD"
+/* definitions of code maturity for plugins */
+#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0
+#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1
+#define MariaDB_PLUGIN_MATURITY_ALPHA 2
+#define MariaDB_PLUGIN_MATURITY_BETA 3
+#define MariaDB_PLUGIN_MATURITY_GAMMA 4
+#define MariaDB_PLUGIN_MATURITY_STABLE 5
+
/*
Macros for beginning and ending plugin declarations. Between
mysql_declare_plugin and mysql_declare_plugin_end there should
@@ -93,7 +105,14 @@ typedef struct st_mysql_xid MYSQL_XID;
int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
int PSIZE= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin DECLS[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_maria_plugin); \
+struct st_maria_plugin DECLS[]= {
+
#else
+
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
@@ -98,6 +117,12 @@ struct st_mysql_plugin DECLS[]= {
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \
+MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \
+MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]= {
+
#endif
#define mysql_declare_plugin(NAME) \
@@ -106,7 +131,14 @@ __MYSQL_DECLARE_PLUGIN(NAME, \
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
builtin_ ## NAME ## _plugin)
+#define maria_declare_plugin(NAME) \
+MARIA_DECLARE_PLUGIN__(NAME, \
+ builtin_maria_ ## NAME ## _plugin_interface_version, \
+ builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_maria_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}
+#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}}
/*
declarations for SHOW STATUS support in plugins
@@ -403,6 +435,30 @@ struct st_mysql_plugin
void * __reserved1; /* reserved for dependency checking */
};
+/*
+ MariaDB extension for plugins declaration structure.
+
+ It also copy current MySQL plugin fields to have more independency
+ in plugins extension
+*/
+
+struct st_maria_plugin
+{
+ int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ void *info; /* pointer to type-specific plugin descriptor */
+ const char *name; /* plugin name */
+ const char *author; /* plugin author (for SHOW PLUGINS) */
+ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
+ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
+ int (*init)(void *); /* the function to invoke when plugin is loaded */
+ int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
+ unsigned int version; /* plugin version (for SHOW PLUGINS) */
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info; /* plugin version string */
+ int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */
+};
+
/*************************************************************************
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
*/
=== modified file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin_auth.h.pp 2010-04-01 12:15:02 +0000
@@ -77,6 +77,22 @@ struct st_mysql_plugin
struct st_mysql_sys_var **system_vars;
void * __reserved1;
};
+struct st_maria_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info;
+ int maturity;
+};
enum enum_ftparser_mode
{
MYSQL_FTPARSER_SIMPLE_MODE= 0,
=== modified file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/auth_socket.c 2010-04-01 12:15:02 +0000
@@ -99,4 +99,21 @@ mysql_declare_plugin(socket_auth)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+mysql_declare_plugin_end;
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/dialog.c 2010-04-01 12:15:02 +0000
@@ -165,6 +165,38 @@ mysql_declare_plugin(dialog)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+maria_declare_plugin_end;
/********************* CLIENT SIDE ***************************************/
/*
=== modified file 'plugin/daemon_example/daemon_example.cc'
--- a/plugin/daemon_example/daemon_example.cc 2007-06-27 14:49:12 +0000
+++ b/plugin/daemon_example/daemon_example.cc 2010-04-01 12:15:02 +0000
@@ -200,3 +200,20 @@ mysql_declare_plugin(daemon_example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(daemon_example)
+{
+ MYSQL_DAEMON_PLUGIN,
+ &daemon_example_plugin,
+ "daemon_example",
+ "Brian Aker",
+ "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",
+ PLUGIN_LICENSE_GPL,
+ daemon_example_plugin_init, /* Plugin Init */
+ daemon_example_plugin_deinit, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'plugin/fulltext/plugin_example.c'
--- a/plugin/fulltext/plugin_example.c 2010-01-04 17:54:42 +0000
+++ b/plugin/fulltext/plugin_example.c 2010-04-01 12:15:02 +0000
@@ -270,4 +270,21 @@ mysql_declare_plugin(ftexample)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(ftexample)
+{
+ MYSQL_FTPARSER_PLUGIN, /* type */
+ &simple_parser_descriptor, /* descriptor */
+ "simple_parser", /* name */
+ "MySQL AB", /* author */
+ "Simple Full-Text Parser", /* description */
+ PLUGIN_LICENSE_GPL,
+ simple_parser_plugin_init, /* init function (when loaded) */
+ simple_parser_plugin_deinit,/* deinit function (when unloaded) */
+ 0x0001, /* version */
+ simple_status, /* status variables */
+ simple_system_variables, /* system variables */
+ "0.01", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-03-29 15:13:53 +0000
+++ b/sql/ha_ndbcluster.cc 2010-04-01 12:15:02 +0000
@@ -10564,6 +10564,23 @@ mysql_declare_plugin(ndbcluster)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_storage_engine,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ "Clustered, fault-tolerant tables",
+ PLUGIN_LICENSE_GPL,
+ ndbcluster_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ ndb_status_variables_export,/* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
#else
int Sun_ar_require_a_symbol_here= 0;
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc 2010-04-01 12:15:02 +0000
@@ -6715,5 +6715,22 @@ mysql_declare_plugin(partition)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_storage_engine,
+ "partition",
+ "Mikael Ronstrom, MySQL AB",
+ "Partition Storage Engine Helper",
+ PLUGIN_LICENSE_GPL,
+ partition_initialize, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#endif
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-03-15 11:51:23 +0000
+++ b/sql/log.cc 2010-04-01 12:15:02 +0000
@@ -6028,3 +6028,20 @@ mysql_declare_plugin(binlog)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_storage_engine,
+ "binlog",
+ "MySQL AB",
+ "This is a pseudo storage engine to represent the binlog in a transaction",
+ PLUGIN_LICENSE_GPL,
+ binlog_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_acl.cc 2010-04-01 12:15:02 +0000
@@ -8254,3 +8254,35 @@ mysql_declare_plugin(mysql_password)
}
mysql_declare_plugin_end;
+maria_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_builtin.cc.in'
--- a/sql/sql_builtin.cc.in 2010-03-29 15:13:53 +0000
+++ b/sql/sql_builtin.cc.in 2010-04-01 12:15:02 +0000
@@ -16,13 +16,12 @@
#include <my_global.h>
#include <mysql/plugin.h>
-typedef struct st_mysql_plugin builtin_plugin[];
+typedef struct st_maria_plugin builtin_maria_plugin[];
-extern builtin_plugin
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@;
+extern builtin_maria_plugin
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@;
-struct st_mysql_plugin *mysqld_builtins[]=
+struct st_maria_plugin *mariadb_builtins[]=
{
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@,(struct st_maria_plugin *)0
};
-
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_plugin.cc 2010-04-01 12:15:02 +0000
@@ -20,7 +20,7 @@
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
-extern struct st_mysql_plugin *mysqld_builtins[];
+extern struct st_maria_plugin *mariadb_builtins[];
/**
@note The order of the enumeration is critical.
@@ -78,6 +78,14 @@ static const char *sizeof_st_plugin_sym=
"_mysql_sizeof_struct_st_plugin_";
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
static int min_plugin_interface_version= MYSQL_PLUGIN_INTERFACE_VERSION & ~0xFF;
+static const char *maria_plugin_interface_version_sym=
+ "_maria_plugin_interface_version_";
+static const char *maria_sizeof_st_plugin_sym=
+ "_maria_sizeof_struct_st_plugin_";
+static const char *maria_plugin_declarations_sym=
+ "_maria_plugin_declarations_";
+static int min_maria_plugin_interface_version=
+ MARIA_PLUGIN_INTERFACE_VERSION & ~0xFF;
#endif
/* Note that 'int version' must be the first field of every plugin
@@ -211,7 +219,7 @@ static bool plugin_load_list(MEM_ROOT *t
const char *list);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
int *, char **);
-static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
+static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(THD *thd, struct system_variables *vars);
@@ -368,6 +376,223 @@ static inline void free_plugin_mem(struc
}
+/**
+ Reads data from mysql plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report What errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+ /* Determine interface version */
+ if (!sym)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= 0;
+ plugin_dl->mysqlversion= *(int *)sym;
+ /* Versioning */
+ if (plugin_dl->mysqlversion < min_plugin_interface_version ||
+ (plugin_dl->mysqlversion >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ /* convert mysql declaration to maria one */
+ {
+ int i;
+ uint sizeof_st_plugin;
+ struct st_mysql_plugin *old;
+ struct st_maria_plugin *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ DBUG_ASSERT(min_plugin_interface_version == 0);
+ sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
+ }
+
+ for (i= 0;
+ ((struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ {
+
+ cur->type= old->type;
+ cur->info= old->info;
+ cur->name= old->name;
+ cur->author= old->author;
+ cur->descr= old->descr;
+ cur->license= old->license;
+ cur->init= old->init;
+ cur->deinit= old->deinit;
+ cur->version= old->version;
+ cur->status_vars= old->status_vars;
+ cur->system_vars= old->system_vars;
+ /*
+ Something like this should be added to process
+ new mysql plugin versions:
+ if (plugin_dl->mysqlversion > 0x0101)
+ {
+ cur->newfield= CONSTANT_MEANS_UNKNOWN;
+ }
+ else
+ {
+ cur->newfield= old->newfield;
+ }
+ */
+ /* Maria only fields */
+ cur->version_info= "Unknown";
+ cur->maturity= MariaDB_PLUGIN_MATURITY_UNKNOWN;
+ }
+ plugin_dl->allocated= true;
+ plugin_dl->plugins= (struct st_maria_plugin *)cur;
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Reads data from maria plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report what errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+
+ /* Determine interface version */
+ if (!(sym))
+ {
+ /*
+ Actually this branch impossible because in case of absence of maria
+ version we try mysql version.
+ */
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY,
+ maria_plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= *(int *)sym;
+ plugin_dl->mysqlversion= 0;
+ /* Versioning */
+ if (plugin_dl->mariaversion < min_maria_plugin_interface_version ||
+ (plugin_dl->mariaversion >> 8) > (MARIA_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, maria_plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+ if (plugin_dl->mariaversion != MARIA_PLUGIN_INTERFACE_VERSION)
+ {
+ uint sizeof_st_plugin;
+ struct st_maria_plugin *old, *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, maria_sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_sizeof_st_plugin_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (sizeof_st_plugin != sizeof(st_mysql_plugin))
+ {
+ int i;
+ for (i= 0;
+ ((struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ memcpy(cur + i, old, min(sizeof(cur[i]), sizeof_st_plugin));
+
+ sym= cur;
+ plugin_dl->allocated= true;
+ }
+ }
+ plugin_dl->plugins= (struct st_maria_plugin *)sym;
+
+ DBUG_RETURN(FALSE);
+}
+
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
#ifdef HAVE_DLOPEN
@@ -415,22 +640,21 @@ static st_plugin_dl *plugin_dl_add(const
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
DBUG_RETURN(0);
}
- /* Determine interface version */
- if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
+
+ /* Checks which plugin interface present and reads info */
+ if (!(sym= dlsym(plugin_dl.handle, maria_plugin_interface_version_sym)))
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
- DBUG_RETURN(0);
+ if (read_mysql_plugin_info(&plugin_dl,
+ dlsym(plugin_dl.handle,
+ plugin_interface_version_sym),
+ dlpath,
+ report))
+ DBUG_RETURN(0);
}
- plugin_dl.version= *(int *)sym;
- /* Versioning */
- if (plugin_dl.version < min_plugin_interface_version ||
- (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ else
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
- "plugin interface version mismatch");
- DBUG_RETURN(0);
+ if (read_maria_plugin_info(&plugin_dl, sym, dlpath, report))
+ DBUG_RETURN(0);
}
/* link the services in */
@@ -438,7 +662,7 @@ static st_plugin_dl *plugin_dl_add(const
{
if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
{
- uint ver= (uint)(intptr)*(void**)sym;
+ uint ver= (uint)(intptr) *(void **)sym;
if (ver > list_of_services[i].version ||
(ver >> 8) < (list_of_services[i].version >> 8))
{
@@ -449,72 +673,9 @@ static st_plugin_dl *plugin_dl_add(const
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
DBUG_RETURN(0);
}
- *(void**)sym= list_of_services[i].service;
- }
- }
-
- /* Find plugin declarations */
- if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
- DBUG_RETURN(0);
- }
-
- if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
- {
- uint sizeof_st_plugin;
- struct st_mysql_plugin *old, *cur;
- char *ptr= (char *)sym;
-
- if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
- sizeof_st_plugin= *(int *)sym;
- else
- {
-#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
- DBUG_RETURN(0);
-#else
- /*
- When the following assert starts failing, we'll have to switch
- to the upper branch of the #ifdef
- */
- DBUG_ASSERT(min_plugin_interface_version == 0);
- sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
-#endif
- }
-
- if (sizeof_st_plugin != sizeof(st_mysql_plugin))
- {
- for (i= 0;
- ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- /* no op */;
-
- cur= (struct st_mysql_plugin*)
- my_malloc((i+1)*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
- if (!cur)
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
- DBUG_RETURN(0);
- }
- /*
- All st_plugin fields not initialized in the plugin explicitly, are
- set to 0. It matches C standard behaviour for struct initializers that
- have less values than the struct definition.
- */
- for (i=0;
- (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
-
- sym= cur;
- plugin_dl.allocated= true;
+ *(void **)sym= list_of_services[i].service;
}
}
- plugin_dl.plugins= (struct st_mysql_plugin *)sym;
/* Duplicate and convert dll name */
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
@@ -756,7 +917,7 @@ static bool plugin_add(MEM_ROOT *tmp_roo
int *argc, char **argv, int report)
{
struct st_plugin_int tmp;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
DBUG_ENTER("plugin_add");
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
{
@@ -1161,8 +1322,8 @@ int plugin_init(int *argc, char **argv,
{
uint i;
bool is_myisam;
- struct st_mysql_plugin **builtins;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin **builtins;
+ struct st_maria_plugin *plugin;
struct st_plugin_int tmp, *plugin_ptr, **reap;
MEM_ROOT tmp_root;
bool reaped_mandatory_plugin= FALSE;
@@ -1201,7 +1362,7 @@ int plugin_init(int *argc, char **argv,
/*
First we register builtin plugins
*/
- for (builtins= mysqld_builtins; *builtins; builtins++)
+ for (builtins= mariadb_builtins; *builtins; builtins++)
{
for (plugin= *builtins; plugin->info; plugin++)
{
@@ -1316,7 +1477,7 @@ err:
}
-static bool register_builtin(struct st_mysql_plugin *plugin,
+static bool register_builtin(struct st_maria_plugin *plugin,
struct st_plugin_int *tmp,
struct st_plugin_int **ptr)
{
@@ -1352,7 +1513,7 @@ static bool register_builtin(struct st_m
RETURN
false - plugin registered successfully
*/
-bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
+bool plugin_register_builtin(THD *thd, struct st_maria_plugin *plugin)
{
struct st_plugin_int tmp, *ptr;
bool result= true;
@@ -1481,7 +1642,7 @@ static bool plugin_load_list(MEM_ROOT *t
char buffer[FN_REFLEN];
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
struct st_plugin_dl *plugin_dl;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
char *p= buffer;
DBUG_ENTER("plugin_load_list");
while (list)
=== modified file 'sql/sql_plugin.h'
--- a/sql/sql_plugin.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_plugin.h 2010-04-01 12:15:02 +0000
@@ -52,8 +52,9 @@ struct st_plugin_dl
{
LEX_STRING dl;
void *handle;
- struct st_mysql_plugin *plugins;
- int version;
+ struct st_maria_plugin *plugins;
+ int mysqlversion;
+ int mariaversion;
bool allocated;
uint ref_count; /* number of plugins loaded from the library */
};
@@ -63,7 +64,7 @@ struct st_plugin_dl
struct st_plugin_int
{
LEX_STRING name;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
struct st_plugin_dl *plugin_dl;
uint state;
uint ref_count; /* number of threads using the plugin */
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_show.cc 2010-04-01 12:15:02 +0000
@@ -94,11 +94,21 @@ static int make_version_string(char *buf
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
}
+
+static const LEX_STRING maturity_name[]={
+ { C_STRING_WITH_LEN("Unknown") },
+ { C_STRING_WITH_LEN("Experimental") },
+ { C_STRING_WITH_LEN("Alpha") },
+ { C_STRING_WITH_LEN("Beta") },
+ { C_STRING_WITH_LEN("Gamma") },
+ { C_STRING_WITH_LEN("Stable") }};
+
+
static my_bool show_plugins(THD *thd, plugin_ref plugin,
void *arg)
{
TABLE *table= (TABLE*) arg;
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
CHARSET_INFO *cs= system_charset_info;
char version_buf[20];
@@ -143,7 +153,7 @@ static my_bool show_plugins(THD *thd, pl
table->field[5]->set_notnull();
table->field[6]->store(version_buf,
make_version_string(version_buf, sizeof(version_buf),
- plugin_dl->version),
+ plugin_dl->mariaversion),
cs);
table->field[6]->set_notnull();
}
@@ -186,6 +196,26 @@ static my_bool show_plugins(THD *thd, pl
}
table->field[9]->set_notnull();
+ if ((uint) plug->maturity <= MariaDB_PLUGIN_MATURITY_STABLE)
+ table->field[10]->store(maturity_name[plug->maturity].str,
+ maturity_name[plug->maturity].length,
+ cs);
+ else
+ {
+ DBUG_ASSERT(0);
+ table->field[10]->store("Unknown", 7, cs);
+ }
+ table->field[10]->set_notnull();
+
+ if (plug->version_info)
+ {
+ table->field[11]->store(plug->version_info,
+ strlen(plug->version_info), cs);
+ table->field[11]->set_notnull();
+ }
+ else
+ table->field[11]->set_null();
+
return schema_table_store_record(thd, table);
}
@@ -4398,7 +4428,7 @@ static my_bool iter_schema_engines(THD *
if (plugin_state(plugin) != PLUGIN_IS_READY)
{
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
if (!(wild && wild[0] &&
wild_case_compare(scs, plug->name,wild)))
{
@@ -7095,6 +7125,8 @@ ST_FIELD_INFO plugin_fields_info[]=
{"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
+ {"PLUGIN_MATURITY", 12, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
+ {"PLUGIN_AUTH_VERSION", 80, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
=== modified file 'storage/archive/ha_archive.cc'
--- a/storage/archive/ha_archive.cc 2010-03-04 08:03:07 +0000
+++ b/storage/archive/ha_archive.cc 2010-04-01 12:15:02 +0000
@@ -1655,4 +1655,21 @@ mysql_declare_plugin(archive)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_storage_engine,
+ "ARCHIVE",
+ "Brian Aker, MySQL AB",
+ "Archive storage engine",
+ PLUGIN_LICENSE_GPL,
+ archive_db_init, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0300 /* 3.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/blackhole/ha_blackhole.cc'
--- a/storage/blackhole/ha_blackhole.cc 2009-10-16 10:29:42 +0000
+++ b/storage/blackhole/ha_blackhole.cc 2010-04-01 12:15:02 +0000
@@ -369,3 +369,20 @@ mysql_declare_plugin(blackhole)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_storage_engine,
+ "BLACKHOLE",
+ "MySQL AB",
+ "/dev/null storage engine (anything you write to it disappears)",
+ PLUGIN_LICENSE_GPL,
+ blackhole_init, /* Plugin Init */
+ blackhole_fini, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/csv/ha_tina.cc'
--- a/storage/csv/ha_tina.cc 2009-12-03 11:19:05 +0000
+++ b/storage/csv/ha_tina.cc 2010-04-01 12:15:02 +0000
@@ -1636,4 +1636,20 @@ mysql_declare_plugin(csv)
NULL /* config options */
}
mysql_declare_plugin_end;
-
+maria_declare_plugin(csv)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &csv_storage_engine,
+ "CSV",
+ "Brian Aker, MySQL AB",
+ "CSV storage engine",
+ PLUGIN_LICENSE_GPL,
+ tina_init_func, /* Plugin Init */
+ tina_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc 2010-04-01 12:15:02 +0000
@@ -924,3 +924,20 @@ mysql_declare_plugin(example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(example)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &example_storage_engine,
+ "EXAMPLE",
+ "Brian Aker, MySQL AB",
+ "Example storage engine",
+ PLUGIN_LICENSE_GPL,
+ example_init_func, /* Plugin Init */
+ example_done_func, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ func_status, /* status variables */
+ example_system_variables, /* system variables */
+ "0.1", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federated/ha_federated.cc'
--- a/storage/federated/ha_federated.cc 2009-09-07 20:50:10 +0000
+++ b/storage/federated/ha_federated.cc 2010-04-01 12:15:02 +0000
@@ -3379,3 +3379,20 @@ mysql_declare_plugin(federated)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ "Federated MySQL storage engine",
+ PLUGIN_LICENSE_GPL,
+ federated_db_init, /* Plugin Init */
+ federated_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 2010-03-10 10:32:14 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2010-04-01 12:15:02 +0000
@@ -3505,9 +3505,26 @@ mysql_declare_plugin(federated)
PLUGIN_LICENSE_GPL,
federatedx_db_init, /* Plugin Init */
federatedx_done, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
+ 0x0200 /* 2.0 */,
NULL, /* status variables */
NULL, /* system variables */
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_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 */
+ 0x0200 /* 2.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "2.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/heap/ha_heap.cc'
--- a/storage/heap/ha_heap.cc 2009-09-07 20:50:10 +0000
+++ b/storage/heap/ha_heap.cc 2010-04-01 12:15:02 +0000
@@ -767,3 +767,20 @@ mysql_declare_plugin(heap)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_storage_engine,
+ "MEMORY",
+ "MySQL AB",
+ "Hash based, stored in memory, useful for temporary tables",
+ PLUGIN_LICENSE_GPL,
+ heap_init,
+ NULL,
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/ibmdb2i/ha_ibmdb2i.cc'
--- a/storage/ibmdb2i/ha_ibmdb2i.cc 2009-12-11 07:01:16 +0000
+++ b/storage/ibmdb2i/ha_ibmdb2i.cc 2010-04-01 12:15:02 +0000
@@ -3357,3 +3357,20 @@ mysql_declare_plugin(ibmdb2i)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ibmdb2i)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ibmdb2i_storage_engine,
+ "IBMDB2I",
+ "The IBM development team in Rochester, Minnesota",
+ "IBM DB2 for i Storage Engine",
+ PLUGIN_LICENSE_GPL,
+ ibmdb2i_init_func, /* Plugin Init */
+ ibmdb2i_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ ibmdb2i_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_UNKNOWN /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2010-03-15 11:51:23 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2010-04-01 12:15:02 +0000
@@ -8930,6 +8930,23 @@ mysql_declare_plugin(innobase)
NULL /* reserved */
}
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase OY",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ innodb_status_variables_export, /* status variables */
+ innobase_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE, /* maturity */
+}
+maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/innodb_plugin/handler/i_s.cc'
--- a/storage/innodb_plugin/handler/i_s.cc 2009-10-12 12:00:56 +0000
+++ b/storage/innodb_plugin/handler/i_s.cc 2010-04-01 12:15:02 +0000
@@ -455,6 +455,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -730,6 +783,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -913,6 +1019,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -1245,6 +1404,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1295,6 +1507,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -1511,6 +1777,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1561,6 +1880,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ha_maria.cc 2010-04-01 12:15:02 +0000
@@ -3471,9 +3471,26 @@ mysql_declare_plugin(maria)
PLUGIN_LICENSE_GPL,
ha_maria_init, /* Plugin Init */
NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
+ 0x0105, /* 1.5 */
status_variables, /* status variables */
system_variables, /* system variables */
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(maria)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &maria_storage_engine,
+ "MARIA",
+ "MySQL AB",
+ "Crash-safe tables with MyISAM heritage",
+ PLUGIN_LICENSE_GPL,
+ ha_maria_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0105, /* 1.5 */
+ status_variables, /* status variables */
+ system_variables, /* system variables */
+ "1.5", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc 2010-01-04 17:54:42 +0000
+++ b/storage/myisam/ha_myisam.cc 2010-04-01 12:15:02 +0000
@@ -2174,6 +2174,23 @@ mysql_declare_plugin(myisam)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_storage_engine,
+ "MyISAM",
+ "MySQL AB",
+ "Default engine as of MySQL 3.23 with great performance",
+ PLUGIN_LICENSE_GPL,
+ myisam_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#ifdef HAVE_QUERY_CACHE
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2010-03-04 08:03:07 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2010-04-01 12:15:02 +0000
@@ -1289,3 +1289,20 @@ mysql_declare_plugin(myisammrg)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_storage_engine,
+ "MRG_MYISAM",
+ "MySQL AB",
+ "Collection of identical MyISAM tables",
+ PLUGIN_LICENSE_GPL,
+ myisammrg_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-03 14:44:14 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-04-01 12:15:02 +0000
@@ -5921,6 +5921,40 @@ mysql_declare_plugin(pbxt)
drizzle_declare_plugin_end;
#else
mysql_declare_plugin_end;
+#ifdef MARIADB_BASE_VERSION
+maria_declare_plugin(pbxt)
+{ /* PBXT */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &pbxt_storage_engine,
+ "PBXT",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "High performance, multi-versioning transactional engine",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init, /* Plugin Init */
+ pbxt_end, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ NULL, /* status variables */
+ pbxt_system_variables, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+},
+{ /* PBXT_STATISTICS */
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &pbxt_statitics,
+ "PBXT_STATISTICS",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "PBXT internal system statitics",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init_statistics, /* plugin init */
+ pbxt_exit_statistics, /* plugin deinit */
+ 0x0005,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
+#endif
#endif
#if defined(XT_WIN) && defined(XT_COREDUMP)
=== modified file 'storage/xtradb/handler/ha_innodb.cc'
--- a/storage/xtradb/handler/ha_innodb.cc 2010-02-01 06:14:12 +0000
+++ b/storage/xtradb/handler/ha_innodb.cc 2010-04-01 12:15:02 +0000
@@ -10818,6 +10818,39 @@ i_s_innodb_index_stats,
i_s_innodb_admin_command,
i_s_innodb_patches
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{ /* InnoDB */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase Oy",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ INNODB_VERSION_SHORT,
+ innodb_status_variables_export,/* status variables */
+ innobase_system_variables, /* system variables */
+ INNODB_VERSION_STR, /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+},
+i_s_innodb_rseg_maria,
+i_s_innodb_buffer_pool_pages_maria,
+i_s_innodb_buffer_pool_pages_index_maria,
+i_s_innodb_buffer_pool_pages_blob_maria,
+i_s_innodb_trx_maria,
+i_s_innodb_locks_maria,
+i_s_innodb_lock_waits_maria,
+i_s_innodb_cmp_maria,
+i_s_innodb_cmp_reset_maria,
+i_s_innodb_cmpmem_maria,
+i_s_innodb_cmpmem_reset_maria,
+i_s_innodb_table_stats_maria,
+i_s_innodb_index_stats_maria,
+i_s_innodb_admin_command_maria,
+i_s_innodb_patches_maria
+maria_declare_plugin_end;
+
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/xtradb/handler/i_s.cc'
--- a/storage/xtradb/handler/i_s.cc 2010-01-28 11:35:10 +0000
+++ b/storage/xtradb/handler/i_s.cc 2010-04-01 12:15:02 +0000
@@ -393,6 +393,59 @@ UNIV_INTERN struct st_mysql_plugin
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_patches_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "XTRADB_ENHANCEMENTS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Enhancements applied to InnoDB plugin"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_patches_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
{
@@ -1040,6 +1093,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1089,6 +1195,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1138,6 +1297,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
@@ -1373,6 +1585,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -1648,6 +1914,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -1831,22 +2150,75 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
-/*******************************************************************//**
-Common function to fill any of the dynamic tables:
-INFORMATION_SCHEMA.innodb_trx
-INFORMATION_SCHEMA.innodb_locks
-INFORMATION_SCHEMA.innodb_lock_waits
-@return 0 on success */
-static
-int
-trx_i_s_common_fill_table(
-/*======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
{
- const char* table_name;
- int ret;
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
+/*******************************************************************//**
+Common function to fill any of the dynamic tables:
+INFORMATION_SCHEMA.innodb_trx
+INFORMATION_SCHEMA.innodb_locks
+INFORMATION_SCHEMA.innodb_lock_waits
+@return 0 on success */
+static
+int
+trx_i_s_common_fill_table(
+/*======================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ COND* cond) /*!< in: condition (not used) */
+{
+ const char* table_name;
+ int ret;
trx_i_s_cache_t* cache;
DBUG_ENTER("trx_i_s_common_fill_table");
@@ -2163,6 +2535,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2213,6 +2638,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -2431,6 +2909,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2481,6 +3012,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
@@ -2660,6 +3245,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_RSEG"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB rollback segment information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_rseg_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
@@ -2940,6 +3578,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
@@ -2956,6 +3611,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
@@ -3122,3 +3794,20 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
=== modified file 'storage/xtradb/handler/i_s.h'
--- a/storage/xtradb/handler/i_s.h 2009-11-04 20:11:12 +0000
+++ b/storage/xtradb/handler/i_s.h 2010-04-01 12:15:02 +0000
@@ -42,4 +42,20 @@ extern struct st_mysql_plugin i_s_innodb
extern struct st_mysql_plugin i_s_innodb_index_stats;
extern struct st_mysql_plugin i_s_innodb_admin_command;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria;
+extern struct st_maria_plugin i_s_innodb_trx_maria;
+extern struct st_maria_plugin i_s_innodb_locks_maria;
+extern struct st_maria_plugin i_s_innodb_lock_waits_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_reset_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_reset_maria;
+extern struct st_maria_plugin i_s_innodb_patches_maria;
+extern struct st_maria_plugin i_s_innodb_rseg_maria;
+extern struct st_maria_plugin i_s_innodb_table_stats_maria;
+extern struct st_maria_plugin i_s_innodb_index_stats_maria;
+extern struct st_maria_plugin i_s_innodb_admin_command_maria;
+
#endif /* i_s_h */
1
0

[Maria-developers] New (by Shinguz): Index usage tracker (103)
by worklog-noreply@askmonty.org 01 Apr '10
by worklog-noreply@askmonty.org 01 Apr '10
01 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Index usage tracker
CREATION DATE..: Wed, 10 Mar 2010, 11:29
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 103 (http://askmonty.org/worklog/?tid=103)
VERSION........: Benchmarks-3.0
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
DESCRIPTION:
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
Thus some statistics about the index usage would be nice.
I think Percona has already something like this done some time ago. And big O
has similar functionality.
I could imagine something like this:
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| table_name | index_name | index_length | create_time | update_time
| use_time | read_first | read_key | read_next | full_scan |
range_scan |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| test_table | idx1 | 1234567890 | 2010-01-01 00:00:00 | 2010-01-01
00:00:00 | 2010-03-10 11:34:56 | 1234 | 42560 | 2468 | 234 |
321 |
| test_table | idx2 | 123456 | 2010-01-01 00:00:00 | NULL
| NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx3 | 234561 | 2010-01-01 00:00:00 | 2010-03-10
11:12:34 | 2010-03-10 11:34:56 | 7890 | 89890 | 15780 | 678 |
321 |
| test_table | idx4 | 345612 | 2010-01-01 00:00:00 | 2010-03-10
11:34:56 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx5 | 456123 | 2010-01-01 00:00:00 | 2010-03-10
06:56:12 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx6 | 561234 | 2010-01-01 00:00:00 | 2010-03-10
01:12:34 | 2010-03-10 11:34:42 | 3456 | 12356 | 6912 | 123 |
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
3
2

[Maria-developers] Updated (by Monty): Index usage tracker (103)
by worklog-noreply@askmonty.org 01 Apr '10
by worklog-noreply@askmonty.org 01 Apr '10
01 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Index usage tracker
CREATION DATE..: Wed, 10 Mar 2010, 11:29
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 103 (http://askmonty.org/worklog/?tid=103)
VERSION........: Server-9.x
STATUS.........: Complete
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
Version updated.
--- /tmp/wklog.103.old.21119 2010-04-01 12:00:42.000000000 +0000
+++ /tmp/wklog.103.new.21119 2010-04-01 12:00:42.000000000 +0000
@@ -1 +1 @@
-Benchmarks-3.0
+Server-9.x
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
Status updated.
--- /tmp/wklog.103.old.21119 2010-04-01 12:00:42.000000000 +0000
+++ /tmp/wklog.103.new.21119 2010-04-01 12:00:42.000000000 +0000
@@ -1 +1 @@
-Un-Assigned
+Complete
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.21108 2010-04-01 12:00:33.000000000 +0000
+++ /tmp/wklog.103.new.21108 2010-04-01 12:00:33.000000000 +0000
@@ -1,3 +1,7 @@
+Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
+requested information.
+
+
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
@@ -33,6 +37,7 @@
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
-=-=(Shinguz - Wed, 10 Mar 2010, 11:30)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.30875 2010-03-10 11:30:45.000000000 +0000
+++ /tmp/wklog.103.new.30875 2010-03-10 11:30:45.000000000 +0000
@@ -35,3 +35,6 @@
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
+
+If some more specification is need for implementation let me know and I will
+collect the stuff from the sources mentioned above.
DESCRIPTION:
Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
requested information.
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
Thus some statistics about the index usage would be nice.
I think Percona has already something like this done some time ago. And big O
has similar functionality.
I could imagine something like this:
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| table_name | index_name | index_length | create_time | update_time
| use_time | read_first | read_key | read_next | full_scan |
range_scan |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| test_table | idx1 | 1234567890 | 2010-01-01 00:00:00 | 2010-01-01
00:00:00 | 2010-03-10 11:34:56 | 1234 | 42560 | 2468 | 234 |
321 |
| test_table | idx2 | 123456 | 2010-01-01 00:00:00 | NULL
| NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx3 | 234561 | 2010-01-01 00:00:00 | 2010-03-10
11:12:34 | 2010-03-10 11:34:56 | 7890 | 89890 | 15780 | 678 |
321 |
| test_table | idx4 | 345612 | 2010-01-01 00:00:00 | 2010-03-10
11:34:56 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx5 | 456123 | 2010-01-01 00:00:00 | 2010-03-10
06:56:12 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx6 | 561234 | 2010-01-01 00:00:00 | 2010-03-10
01:12:34 | 2010-03-10 11:34:42 | 3456 | 12356 | 6912 | 123 |
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
If some more specification is need for implementation let me know and I will
collect the stuff from the sources mentioned above.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Monty): Index usage tracker (103)
by worklog-noreply@askmonty.org 01 Apr '10
by worklog-noreply@askmonty.org 01 Apr '10
01 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Index usage tracker
CREATION DATE..: Wed, 10 Mar 2010, 11:29
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 103 (http://askmonty.org/worklog/?tid=103)
VERSION........: Server-9.x
STATUS.........: Complete
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
Version updated.
--- /tmp/wklog.103.old.21119 2010-04-01 12:00:42.000000000 +0000
+++ /tmp/wklog.103.new.21119 2010-04-01 12:00:42.000000000 +0000
@@ -1 +1 @@
-Benchmarks-3.0
+Server-9.x
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
Status updated.
--- /tmp/wklog.103.old.21119 2010-04-01 12:00:42.000000000 +0000
+++ /tmp/wklog.103.new.21119 2010-04-01 12:00:42.000000000 +0000
@@ -1 +1 @@
-Un-Assigned
+Complete
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.21108 2010-04-01 12:00:33.000000000 +0000
+++ /tmp/wklog.103.new.21108 2010-04-01 12:00:33.000000000 +0000
@@ -1,3 +1,7 @@
+Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
+requested information.
+
+
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
@@ -33,6 +37,7 @@
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
-=-=(Shinguz - Wed, 10 Mar 2010, 11:30)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.30875 2010-03-10 11:30:45.000000000 +0000
+++ /tmp/wklog.103.new.30875 2010-03-10 11:30:45.000000000 +0000
@@ -35,3 +35,6 @@
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
+
+If some more specification is need for implementation let me know and I will
+collect the stuff from the sources mentioned above.
DESCRIPTION:
Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
requested information.
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
Thus some statistics about the index usage would be nice.
I think Percona has already something like this done some time ago. And big O
has similar functionality.
I could imagine something like this:
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| table_name | index_name | index_length | create_time | update_time
| use_time | read_first | read_key | read_next | full_scan |
range_scan |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| test_table | idx1 | 1234567890 | 2010-01-01 00:00:00 | 2010-01-01
00:00:00 | 2010-03-10 11:34:56 | 1234 | 42560 | 2468 | 234 |
321 |
| test_table | idx2 | 123456 | 2010-01-01 00:00:00 | NULL
| NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx3 | 234561 | 2010-01-01 00:00:00 | 2010-03-10
11:12:34 | 2010-03-10 11:34:56 | 7890 | 89890 | 15780 | 678 |
321 |
| test_table | idx4 | 345612 | 2010-01-01 00:00:00 | 2010-03-10
11:34:56 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx5 | 456123 | 2010-01-01 00:00:00 | 2010-03-10
06:56:12 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx6 | 561234 | 2010-01-01 00:00:00 | 2010-03-10
01:12:34 | 2010-03-10 11:34:42 | 3456 | 12356 | 6912 | 123 |
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
If some more specification is need for implementation let me know and I will
collect the stuff from the sources mentioned above.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Monty): Index usage tracker (103)
by worklog-noreply@askmonty.org 01 Apr '10
by worklog-noreply@askmonty.org 01 Apr '10
01 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Index usage tracker
CREATION DATE..: Wed, 10 Mar 2010, 11:29
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 103 (http://askmonty.org/worklog/?tid=103)
VERSION........: Benchmarks-3.0
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.21108 2010-04-01 12:00:33.000000000 +0000
+++ /tmp/wklog.103.new.21108 2010-04-01 12:00:33.000000000 +0000
@@ -1,3 +1,7 @@
+Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
+requested information.
+
+
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
@@ -33,6 +37,7 @@
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
-=-=(Shinguz - Wed, 10 Mar 2010, 11:30)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.30875 2010-03-10 11:30:45.000000000 +0000
+++ /tmp/wklog.103.new.30875 2010-03-10 11:30:45.000000000 +0000
@@ -35,3 +35,6 @@
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
+
+If some more specification is need for implementation let me know and I will
+collect the stuff from the sources mentioned above.
DESCRIPTION:
Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
requested information.
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
Thus some statistics about the index usage would be nice.
I think Percona has already something like this done some time ago. And big O
has similar functionality.
I could imagine something like this:
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| table_name | index_name | index_length | create_time | update_time
| use_time | read_first | read_key | read_next | full_scan |
range_scan |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| test_table | idx1 | 1234567890 | 2010-01-01 00:00:00 | 2010-01-01
00:00:00 | 2010-03-10 11:34:56 | 1234 | 42560 | 2468 | 234 |
321 |
| test_table | idx2 | 123456 | 2010-01-01 00:00:00 | NULL
| NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx3 | 234561 | 2010-01-01 00:00:00 | 2010-03-10
11:12:34 | 2010-03-10 11:34:56 | 7890 | 89890 | 15780 | 678 |
321 |
| test_table | idx4 | 345612 | 2010-01-01 00:00:00 | 2010-03-10
11:34:56 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx5 | 456123 | 2010-01-01 00:00:00 | 2010-03-10
06:56:12 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx6 | 561234 | 2010-01-01 00:00:00 | 2010-03-10
01:12:34 | 2010-03-10 11:34:42 | 3456 | 12356 | 6912 | 123 |
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
If some more specification is need for implementation let me know and I will
collect the stuff from the sources mentioned above.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Monty): Index usage tracker (103)
by worklog-noreply@askmonty.org 01 Apr '10
by worklog-noreply@askmonty.org 01 Apr '10
01 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Index usage tracker
CREATION DATE..: Wed, 10 Mar 2010, 11:29
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 103 (http://askmonty.org/worklog/?tid=103)
VERSION........: Benchmarks-3.0
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Monty - Thu, 01 Apr 2010, 12:00)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.21108 2010-04-01 12:00:33.000000000 +0000
+++ /tmp/wklog.103.new.21108 2010-04-01 12:00:33.000000000 +0000
@@ -1,3 +1,7 @@
+Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
+requested information.
+
+
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
@@ -33,6 +37,7 @@
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
-=-=(Shinguz - Wed, 10 Mar 2010, 11:30)=-=-
High Level Description modified.
--- /tmp/wklog.103.old.30875 2010-03-10 11:30:45.000000000 +0000
+++ /tmp/wklog.103.new.30875 2010-03-10 11:30:45.000000000 +0000
@@ -35,3 +35,6 @@
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
+
+If some more specification is need for implementation let me know and I will
+collect the stuff from the sources mentioned above.
DESCRIPTION:
Update: We have already in MariaDB 5.2 SHOW INDEX STATISTICS that provides the
requested information.
What indexes are needed is often easy to find. What is more difficult is to find
which indexes are not used at all.
Thus some statistics about the index usage would be nice.
I think Percona has already something like this done some time ago. And big O
has similar functionality.
I could imagine something like this:
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| table_name | index_name | index_length | create_time | update_time
| use_time | read_first | read_key | read_next | full_scan |
range_scan |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
| test_table | idx1 | 1234567890 | 2010-01-01 00:00:00 | 2010-01-01
00:00:00 | 2010-03-10 11:34:56 | 1234 | 42560 | 2468 | 234 |
321 |
| test_table | idx2 | 123456 | 2010-01-01 00:00:00 | NULL
| NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx3 | 234561 | 2010-01-01 00:00:00 | 2010-03-10
11:12:34 | 2010-03-10 11:34:56 | 7890 | 89890 | 15780 | 678 |
321 |
| test_table | idx4 | 345612 | 2010-01-01 00:00:00 | 2010-03-10
11:34:56 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx5 | 456123 | 2010-01-01 00:00:00 | 2010-03-10
06:56:12 | NULL | 0 | 0 | 0 | 0 |
0 |
| test_table | idx6 | 561234 | 2010-01-01 00:00:00 | 2010-03-10
01:12:34 | 2010-03-10 11:34:42 | 3456 | 12356 | 6912 | 123 |
12 |
+------------+------------+--------------+---------------------+---------------------+---------------------+------------+----------+-----------+-----------+------------+
Possibly this could/should be implemented on the handler interface level because
there we know what we are touching? But I am not familiar with the code.
If some more specification is need for implementation let me know and I will
collect the stuff from the sources mentioned above.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Rev 2761: Maria WL#61 in file:///Users/bell/maria/bzr/work-maria-5.2-engine-backup/
by sanja@askmonty.org 01 Apr '10
by sanja@askmonty.org 01 Apr '10
01 Apr '10
At file:///Users/bell/maria/bzr/work-maria-5.2-engine-backup/
------------------------------------------------------------
revno: 2761
revision-id: sanja(a)askmonty.org-20100330203255-1pyz892qsqg1liov
parent: sanja(a)askmonty.org-20100330123515-4p8q03xccl3d6k59
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-engine-backup
timestamp: Tue 2010-03-30 23:32:55 +0300
message:
Maria WL#61
Interface for maria extensions.
Alternative plugin interface with additional info (maturity and string version).
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt 2010-03-15 11:51:23 +0000
+++ b/CMakeLists.txt 2010-03-30 20:32:55 +0000
@@ -260,7 +260,7 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${PLUGIN_NAME}_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin")
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
@@ -279,7 +279,7 @@ ENDFOREACH(SUBDIR ${STORAGE_SUBDIRS})
# Special handling for partition(not really pluggable)
IF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_PARTITION_STORAGE_ENGINE")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_partition_plugin")
ENDIF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
# Special handling for tmp tables with the maria engine
=== modified file 'config/ac-macros/plugins.m4'
--- a/config/ac-macros/plugins.m4 2010-03-29 15:14:28 +0000
+++ b/config/ac-macros/plugins.m4 2010-03-30 20:32:55 +0000
@@ -460,7 +460,7 @@ dnl Although this is "pretty", it breaks
])
])
])
- mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ maria_plugin_defs="$maria_plugin_defs, [builtin_maria_]$2[_plugin]"
[with_plugin_]$2=yes
AC_MSG_RESULT([yes])
m4_ifdef([$11], [
=== modified file 'configure.in'
--- a/configure.in 2010-03-29 15:13:53 +0000
+++ b/configure.in 2010-03-30 20:32:55 +0000
@@ -2872,7 +2872,7 @@ AC_SUBST(server_scripts)
AC_SUBST(mysql_plugin_dirs)
AC_SUBST(mysql_plugin_libs)
-AC_SUBST(mysql_plugin_defs)
+AC_SUBST(maria_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin.h 2010-03-30 20:32:55 +0000
@@ -57,7 +57,10 @@ typedef struct st_mysql_xid MYSQL_XID;
Plugin API. Common for all plugin types.
*/
+/* MySQL plugin interface version */
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
+/* MariaDB plugin interface version */
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x0100
/*
The allowable types of plugins
@@ -81,6 +84,14 @@ typedef struct st_mysql_xid MYSQL_XID;
#define PLUGIN_LICENSE_GPL_STRING "GPL"
#define PLUGIN_LICENSE_BSD_STRING "BSD"
+/* definitions of code maturity for plugins */
+#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0
+#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1
+#define MariaDB_PLUGIN_MATURITY_ALPHA 2
+#define MariaDB_PLUGIN_MATURITY_BETA 3
+#define MariaDB_PLUGIN_MATURITY_GAMMA 4
+#define MariaDB_PLUGIN_MATURITY_STABLE 5
+
/*
Macros for beginning and ending plugin declarations. Between
mysql_declare_plugin and mysql_declare_plugin_end there should
@@ -93,7 +105,14 @@ typedef struct st_mysql_xid MYSQL_XID;
int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
int PSIZE= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin DECLS[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_maria_plugin); \
+struct st_maria_plugin DECLS[]= {
+
#else
+
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
@@ -98,6 +117,12 @@ struct st_mysql_plugin DECLS[]= {
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \
+MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \
+MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]= {
+
#endif
#define mysql_declare_plugin(NAME) \
@@ -106,7 +131,14 @@ __MYSQL_DECLARE_PLUGIN(NAME, \
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
builtin_ ## NAME ## _plugin)
+#define maria_declare_plugin(NAME) \
+MARIA_DECLARE_PLUGIN__(NAME, \
+ builtin_maria_ ## NAME ## _plugin_interface_version, \
+ builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_maria_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}
+#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}}
/*
declarations for SHOW STATUS support in plugins
@@ -403,6 +435,30 @@ struct st_mysql_plugin
void * __reserved1; /* reserved for dependency checking */
};
+/*
+ MariaDB extension for plugins declaration structure.
+
+ It also copy current MySQL plugin fields to have more independency
+ in plugins extension
+*/
+
+struct st_maria_plugin
+{
+ int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ void *info; /* pointer to type-specific plugin descriptor */
+ const char *name; /* plugin name */
+ const char *author; /* plugin author (for SHOW PLUGINS) */
+ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
+ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
+ int (*init)(void *); /* the function to invoke when plugin is loaded */
+ int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
+ unsigned int version; /* plugin version (for SHOW PLUGINS) */
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info; /* plugin version string */
+ int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */
+};
+
/*************************************************************************
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
*/
=== modified file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp 2010-03-29 15:13:53 +0000
+++ b/include/mysql/plugin_auth.h.pp 2010-03-30 20:32:55 +0000
@@ -77,6 +77,22 @@ struct st_mysql_plugin
struct st_mysql_sys_var **system_vars;
void * __reserved1;
};
+struct st_maria_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info;
+ int maturity;
+};
enum enum_ftparser_mode
{
MYSQL_FTPARSER_SIMPLE_MODE= 0,
=== modified file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/auth_socket.c 2010-03-30 20:32:55 +0000
@@ -99,4 +99,21 @@ mysql_declare_plugin(socket_auth)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+mysql_declare_plugin_end;
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/dialog.c 2010-03-30 20:32:55 +0000
@@ -165,6 +165,38 @@ mysql_declare_plugin(dialog)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+maria_declare_plugin_end;
/********************* CLIENT SIDE ***************************************/
/*
=== modified file 'plugin/daemon_example/daemon_example.cc'
--- a/plugin/daemon_example/daemon_example.cc 2007-06-27 14:49:12 +0000
+++ b/plugin/daemon_example/daemon_example.cc 2010-03-30 20:32:55 +0000
@@ -200,3 +200,20 @@ mysql_declare_plugin(daemon_example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(daemon_example)
+{
+ MYSQL_DAEMON_PLUGIN,
+ &daemon_example_plugin,
+ "daemon_example",
+ "Brian Aker",
+ "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",
+ PLUGIN_LICENSE_GPL,
+ daemon_example_plugin_init, /* Plugin Init */
+ daemon_example_plugin_deinit, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'plugin/fulltext/plugin_example.c'
--- a/plugin/fulltext/plugin_example.c 2010-01-04 17:54:42 +0000
+++ b/plugin/fulltext/plugin_example.c 2010-03-30 20:32:55 +0000
@@ -270,4 +270,21 @@ mysql_declare_plugin(ftexample)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(ftexample)
+{
+ MYSQL_FTPARSER_PLUGIN, /* type */
+ &simple_parser_descriptor, /* descriptor */
+ "simple_parser", /* name */
+ "MySQL AB", /* author */
+ "Simple Full-Text Parser", /* description */
+ PLUGIN_LICENSE_GPL,
+ simple_parser_plugin_init, /* init function (when loaded) */
+ simple_parser_plugin_deinit,/* deinit function (when unloaded) */
+ 0x0001, /* version */
+ simple_status, /* status variables */
+ simple_system_variables, /* system variables */
+ "0.01", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-03-29 15:13:53 +0000
+++ b/sql/ha_ndbcluster.cc 2010-03-30 20:32:55 +0000
@@ -10564,6 +10564,23 @@ mysql_declare_plugin(ndbcluster)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_storage_engine,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ "Clustered, fault-tolerant tables",
+ PLUGIN_LICENSE_GPL,
+ ndbcluster_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ ndb_status_variables_export,/* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
#else
int Sun_ar_require_a_symbol_here= 0;
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc 2010-03-30 20:32:55 +0000
@@ -6715,5 +6715,22 @@ mysql_declare_plugin(partition)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_storage_engine,
+ "partition",
+ "Mikael Ronstrom, MySQL AB",
+ "Partition Storage Engine Helper",
+ PLUGIN_LICENSE_GPL,
+ partition_initialize, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#endif
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-03-15 11:51:23 +0000
+++ b/sql/log.cc 2010-03-30 20:32:55 +0000
@@ -6028,3 +6028,20 @@ mysql_declare_plugin(binlog)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_storage_engine,
+ "binlog",
+ "MySQL AB",
+ "This is a pseudo storage engine to represent the binlog in a transaction",
+ PLUGIN_LICENSE_GPL,
+ binlog_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_acl.cc 2010-03-30 20:32:55 +0000
@@ -8254,3 +8254,35 @@ mysql_declare_plugin(mysql_password)
}
mysql_declare_plugin_end;
+maria_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+}
+maria_declare_plugin_end;
=== modified file 'sql/sql_builtin.cc.in'
--- a/sql/sql_builtin.cc.in 2010-03-29 15:13:53 +0000
+++ b/sql/sql_builtin.cc.in 2010-03-30 20:32:55 +0000
@@ -16,13 +16,12 @@
#include <my_global.h>
#include <mysql/plugin.h>
-typedef struct st_mysql_plugin builtin_plugin[];
+typedef struct st_maria_plugin builtin_maria_plugin[];
-extern builtin_plugin
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@;
+extern builtin_maria_plugin
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@;
-struct st_mysql_plugin *mysqld_builtins[]=
+struct st_maria_plugin *mariadb_builtins[]=
{
- builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@,(struct st_maria_plugin *)0
};
-
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_plugin.cc 2010-03-30 20:32:55 +0000
@@ -20,7 +20,7 @@
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
-extern struct st_mysql_plugin *mysqld_builtins[];
+extern struct st_maria_plugin *mariadb_builtins[];
/**
@note The order of the enumeration is critical.
@@ -78,6 +78,14 @@ static const char *sizeof_st_plugin_sym=
"_mysql_sizeof_struct_st_plugin_";
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
static int min_plugin_interface_version= MYSQL_PLUGIN_INTERFACE_VERSION & ~0xFF;
+static const char *maria_plugin_interface_version_sym=
+ "_maria_plugin_interface_version_";
+static const char *maria_sizeof_st_plugin_sym=
+ "_maria_sizeof_struct_st_plugin_";
+static const char *maria_plugin_declarations_sym=
+ "_maria_plugin_declarations_";
+static int min_maria_plugin_interface_version=
+ MARIA_PLUGIN_INTERFACE_VERSION & ~0xFF;
#endif
/* Note that 'int version' must be the first field of every plugin
@@ -211,7 +219,7 @@ static bool plugin_load_list(MEM_ROOT *t
const char *list);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
int *, char **);
-static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
+static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(THD *thd, struct system_variables *vars);
@@ -368,6 +376,223 @@ static inline void free_plugin_mem(struc
}
+/**
+ Reads data from mysql plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report What errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+ /* Determine interface version */
+ if (!sym)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= 0;
+ plugin_dl->mysqlversion= *(int *)sym;
+ /* Versioning */
+ if (plugin_dl->mysqlversion < min_plugin_interface_version ||
+ (plugin_dl->mysqlversion >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ /* convert mysql declaration to maria one */
+ {
+ int i;
+ uint sizeof_st_plugin;
+ struct st_mysql_plugin *old;
+ struct st_maria_plugin *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ DBUG_ASSERT(min_plugin_interface_version == 0);
+ sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
+ }
+
+ for (i= 0;
+ ((struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ {
+
+ cur->type= old->type;
+ cur->info= old->info;
+ cur->name= old->name;
+ cur->author= old->author;
+ cur->descr= old->descr;
+ cur->license= old->license;
+ cur->init= old->init;
+ cur->deinit= old->deinit;
+ cur->version= old->version;
+ cur->status_vars= old->status_vars;
+ cur->system_vars= old->system_vars;
+ /*
+ Something like this should be added to process
+ new mysql plugin versions:
+ if (plugin_dl->mysqlversion > 0x0101)
+ {
+ cur->newfield= CONSTANT_MEANS_UNKNOWN;
+ }
+ else
+ {
+ cur->newfield= old->newfield;
+ }
+ */
+ /* Maria only fields */
+ cur->version_info= "Unknown";
+ cur->maturity= MariaDB_PLUGIN_MATURITY_UNKNOWN;
+ }
+ plugin_dl->allocated= true;
+ plugin_dl->plugins= (struct st_maria_plugin *)cur;
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Reads data from maria plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report what errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+
+ /* Determine interface version */
+ if (!(sym))
+ {
+ /*
+ Actually this branch impossible because in case of absence of maria
+ version we try mysql version.
+ */
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY,
+ maria_plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= *(int *)sym;
+ plugin_dl->mysqlversion= 0;
+ /* Versioning */
+ if (plugin_dl->mariaversion < min_maria_plugin_interface_version ||
+ (plugin_dl->mariaversion >> 8) > (MARIA_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, maria_plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+ if (plugin_dl->mariaversion != MARIA_PLUGIN_INTERFACE_VERSION)
+ {
+ uint sizeof_st_plugin;
+ struct st_maria_plugin *old, *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, maria_sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_sizeof_st_plugin_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (sizeof_st_plugin != sizeof(st_mysql_plugin))
+ {
+ int i;
+ for (i= 0;
+ ((struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ memcpy(cur + i, old, min(sizeof(cur[i]), sizeof_st_plugin));
+
+ sym= cur;
+ plugin_dl->allocated= true;
+ }
+ }
+ plugin_dl->plugins= (struct st_maria_plugin *)sym;
+
+ DBUG_RETURN(FALSE);
+}
+
static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
#ifdef HAVE_DLOPEN
@@ -415,22 +640,21 @@ static st_plugin_dl *plugin_dl_add(const
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
DBUG_RETURN(0);
}
- /* Determine interface version */
- if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
+
+ /* Checks which plugin interface present and reads info */
+ if (!(sym= dlsym(plugin_dl.handle, maria_plugin_interface_version_sym)))
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
- DBUG_RETURN(0);
+ if (read_mysql_plugin_info(&plugin_dl,
+ dlsym(plugin_dl.handle,
+ plugin_interface_version_sym),
+ dlpath,
+ report))
+ DBUG_RETURN(0);
}
- plugin_dl.version= *(int *)sym;
- /* Versioning */
- if (plugin_dl.version < min_plugin_interface_version ||
- (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ else
{
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
- "plugin interface version mismatch");
- DBUG_RETURN(0);
+ if (read_maria_plugin_info(&plugin_dl, sym, dlpath, report))
+ DBUG_RETURN(0);
}
/* link the services in */
@@ -438,7 +662,7 @@ static st_plugin_dl *plugin_dl_add(const
{
if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
{
- uint ver= (uint)(intptr)*(void**)sym;
+ uint ver= (uint)(intptr) *(void **)sym;
if (ver > list_of_services[i].version ||
(ver >> 8) < (list_of_services[i].version >> 8))
{
@@ -449,72 +673,9 @@ static st_plugin_dl *plugin_dl_add(const
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
DBUG_RETURN(0);
}
- *(void**)sym= list_of_services[i].service;
- }
- }
-
- /* Find plugin declarations */
- if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
- DBUG_RETURN(0);
- }
-
- if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
- {
- uint sizeof_st_plugin;
- struct st_mysql_plugin *old, *cur;
- char *ptr= (char *)sym;
-
- if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
- sizeof_st_plugin= *(int *)sym;
- else
- {
-#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
- DBUG_RETURN(0);
-#else
- /*
- When the following assert starts failing, we'll have to switch
- to the upper branch of the #ifdef
- */
- DBUG_ASSERT(min_plugin_interface_version == 0);
- sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
-#endif
- }
-
- if (sizeof_st_plugin != sizeof(st_mysql_plugin))
- {
- for (i= 0;
- ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- /* no op */;
-
- cur= (struct st_mysql_plugin*)
- my_malloc((i+1)*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
- if (!cur)
- {
- free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
- DBUG_RETURN(0);
- }
- /*
- All st_plugin fields not initialized in the plugin explicitly, are
- set to 0. It matches C standard behaviour for struct initializers that
- have less values than the struct definition.
- */
- for (i=0;
- (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
-
- sym= cur;
- plugin_dl.allocated= true;
+ *(void **)sym= list_of_services[i].service;
}
}
- plugin_dl.plugins= (struct st_mysql_plugin *)sym;
/* Duplicate and convert dll name */
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
@@ -756,7 +917,7 @@ static bool plugin_add(MEM_ROOT *tmp_roo
int *argc, char **argv, int report)
{
struct st_plugin_int tmp;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
DBUG_ENTER("plugin_add");
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
{
@@ -1161,8 +1322,8 @@ int plugin_init(int *argc, char **argv,
{
uint i;
bool is_myisam;
- struct st_mysql_plugin **builtins;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin **builtins;
+ struct st_maria_plugin *plugin;
struct st_plugin_int tmp, *plugin_ptr, **reap;
MEM_ROOT tmp_root;
bool reaped_mandatory_plugin= FALSE;
@@ -1201,7 +1362,7 @@ int plugin_init(int *argc, char **argv,
/*
First we register builtin plugins
*/
- for (builtins= mysqld_builtins; *builtins; builtins++)
+ for (builtins= mariadb_builtins; *builtins; builtins++)
{
for (plugin= *builtins; plugin->info; plugin++)
{
@@ -1316,7 +1477,7 @@ err:
}
-static bool register_builtin(struct st_mysql_plugin *plugin,
+static bool register_builtin(struct st_maria_plugin *plugin,
struct st_plugin_int *tmp,
struct st_plugin_int **ptr)
{
@@ -1352,7 +1513,7 @@ static bool register_builtin(struct st_m
RETURN
false - plugin registered successfully
*/
-bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
+bool plugin_register_builtin(THD *thd, struct st_maria_plugin *plugin)
{
struct st_plugin_int tmp, *ptr;
bool result= true;
@@ -1481,7 +1642,7 @@ static bool plugin_load_list(MEM_ROOT *t
char buffer[FN_REFLEN];
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
struct st_plugin_dl *plugin_dl;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
char *p= buffer;
DBUG_ENTER("plugin_load_list");
while (list)
=== modified file 'sql/sql_plugin.h'
--- a/sql/sql_plugin.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_plugin.h 2010-03-30 20:32:55 +0000
@@ -52,8 +52,9 @@ struct st_plugin_dl
{
LEX_STRING dl;
void *handle;
- struct st_mysql_plugin *plugins;
- int version;
+ struct st_maria_plugin *plugins;
+ int mysqlversion;
+ int mariaversion;
bool allocated;
uint ref_count; /* number of plugins loaded from the library */
};
@@ -63,7 +64,7 @@ struct st_plugin_dl
struct st_plugin_int
{
LEX_STRING name;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
struct st_plugin_dl *plugin_dl;
uint state;
uint ref_count; /* number of threads using the plugin */
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_show.cc 2010-03-30 20:32:55 +0000
@@ -94,11 +94,21 @@ static int make_version_string(char *buf
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
}
+
+static const LEX_STRING maturity_name[]={
+ { C_STRING_WITH_LEN("Unknown") },
+ { C_STRING_WITH_LEN("Experimental") },
+ { C_STRING_WITH_LEN("Alpha") },
+ { C_STRING_WITH_LEN("Beta") },
+ { C_STRING_WITH_LEN("Gamma") },
+ { C_STRING_WITH_LEN("Stable") }};
+
+
static my_bool show_plugins(THD *thd, plugin_ref plugin,
void *arg)
{
TABLE *table= (TABLE*) arg;
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
CHARSET_INFO *cs= system_charset_info;
char version_buf[20];
@@ -143,7 +153,7 @@ static my_bool show_plugins(THD *thd, pl
table->field[5]->set_notnull();
table->field[6]->store(version_buf,
make_version_string(version_buf, sizeof(version_buf),
- plugin_dl->version),
+ plugin_dl->mariaversion),
cs);
table->field[6]->set_notnull();
}
@@ -186,6 +196,26 @@ static my_bool show_plugins(THD *thd, pl
}
table->field[9]->set_notnull();
+ if ((uint) plug->maturity <= MariaDB_PLUGIN_MATURITY_STABLE)
+ table->field[10]->store(maturity_name[plug->maturity].str,
+ maturity_name[plug->maturity].length,
+ cs);
+ else
+ {
+ DBUG_ASSERT(0);
+ table->field[10]->store("Unknown", 7, cs);
+ }
+ table->field[10]->set_notnull();
+
+ if (plug->version_info)
+ {
+ table->field[11]->store(plug->version_info,
+ strlen(plug->version_info), cs);
+ table->field[11]->set_notnull();
+ }
+ else
+ table->field[11]->set_null();
+
return schema_table_store_record(thd, table);
}
@@ -4398,7 +4428,7 @@ static my_bool iter_schema_engines(THD *
if (plugin_state(plugin) != PLUGIN_IS_READY)
{
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
if (!(wild && wild[0] &&
wild_case_compare(scs, plug->name,wild)))
{
@@ -7095,6 +7125,8 @@ ST_FIELD_INFO plugin_fields_info[]=
{"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
+ {"PLUGIN_MATURITY", 12, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
+ {"PLUGIN_AUTH_VERSION", 80, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
=== modified file 'storage/archive/ha_archive.cc'
--- a/storage/archive/ha_archive.cc 2010-03-04 08:03:07 +0000
+++ b/storage/archive/ha_archive.cc 2010-03-30 20:32:55 +0000
@@ -1655,4 +1655,21 @@ mysql_declare_plugin(archive)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_storage_engine,
+ "ARCHIVE",
+ "Brian Aker, MySQL AB",
+ "Archive storage engine",
+ PLUGIN_LICENSE_GPL,
+ archive_db_init, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0300 /* 3.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/blackhole/ha_blackhole.cc'
--- a/storage/blackhole/ha_blackhole.cc 2009-10-16 10:29:42 +0000
+++ b/storage/blackhole/ha_blackhole.cc 2010-03-30 20:32:55 +0000
@@ -369,3 +369,20 @@ mysql_declare_plugin(blackhole)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_storage_engine,
+ "BLACKHOLE",
+ "MySQL AB",
+ "/dev/null storage engine (anything you write to it disappears)",
+ PLUGIN_LICENSE_GPL,
+ blackhole_init, /* Plugin Init */
+ blackhole_fini, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/csv/ha_tina.cc'
--- a/storage/csv/ha_tina.cc 2009-12-03 11:19:05 +0000
+++ b/storage/csv/ha_tina.cc 2010-03-30 20:32:55 +0000
@@ -1636,4 +1636,20 @@ mysql_declare_plugin(csv)
NULL /* config options */
}
mysql_declare_plugin_end;
-
+maria_declare_plugin(csv)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &csv_storage_engine,
+ "CSV",
+ "Brian Aker, MySQL AB",
+ "CSV storage engine",
+ PLUGIN_LICENSE_GPL,
+ tina_init_func, /* Plugin Init */
+ tina_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc 2010-03-30 20:32:55 +0000
@@ -924,3 +924,20 @@ mysql_declare_plugin(example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(example)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &example_storage_engine,
+ "EXAMPLE",
+ "Brian Aker, MySQL AB",
+ "Example storage engine",
+ PLUGIN_LICENSE_GPL,
+ example_init_func, /* Plugin Init */
+ example_done_func, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ func_status, /* status variables */
+ example_system_variables, /* system variables */
+ "0.1", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federated/ha_federated.cc'
--- a/storage/federated/ha_federated.cc 2009-09-07 20:50:10 +0000
+++ b/storage/federated/ha_federated.cc 2010-03-30 20:32:55 +0000
@@ -3379,3 +3379,20 @@ mysql_declare_plugin(federated)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ "Federated MySQL storage engine",
+ PLUGIN_LICENSE_GPL,
+ federated_db_init, /* Plugin Init */
+ federated_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 2010-03-10 10:32:14 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2010-03-30 20:32:55 +0000
@@ -3505,9 +3505,26 @@ mysql_declare_plugin(federated)
PLUGIN_LICENSE_GPL,
federatedx_db_init, /* Plugin Init */
federatedx_done, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
+ 0x0200 /* 2.0 */,
NULL, /* status variables */
NULL, /* system variables */
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_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 */
+ 0x0200 /* 2.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "2.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/heap/ha_heap.cc'
--- a/storage/heap/ha_heap.cc 2009-09-07 20:50:10 +0000
+++ b/storage/heap/ha_heap.cc 2010-03-30 20:32:55 +0000
@@ -767,3 +767,20 @@ mysql_declare_plugin(heap)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_storage_engine,
+ "MEMORY",
+ "MySQL AB",
+ "Hash based, stored in memory, useful for temporary tables",
+ PLUGIN_LICENSE_GPL,
+ heap_init,
+ NULL,
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/ibmdb2i/ha_ibmdb2i.cc'
--- a/storage/ibmdb2i/ha_ibmdb2i.cc 2009-12-11 07:01:16 +0000
+++ b/storage/ibmdb2i/ha_ibmdb2i.cc 2010-03-30 20:32:55 +0000
@@ -3357,3 +3357,20 @@ mysql_declare_plugin(ibmdb2i)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ibmdb2i)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ibmdb2i_storage_engine,
+ "IBMDB2I",
+ "The IBM development team in Rochester, Minnesota",
+ "IBM DB2 for i Storage Engine",
+ PLUGIN_LICENSE_GPL,
+ ibmdb2i_init_func, /* Plugin Init */
+ ibmdb2i_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ ibmdb2i_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_UNKNOWN /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2010-03-15 11:51:23 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2010-03-30 20:32:55 +0000
@@ -8930,6 +8930,23 @@ mysql_declare_plugin(innobase)
NULL /* reserved */
}
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase OY",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ innodb_status_variables_export, /* status variables */
+ innobase_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE, /* maturity */
+}
+maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/innodb_plugin/handler/i_s.cc'
--- a/storage/innodb_plugin/handler/i_s.cc 2009-10-12 12:00:56 +0000
+++ b/storage/innodb_plugin/handler/i_s.cc 2010-03-30 20:32:55 +0000
@@ -455,6 +455,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -730,6 +783,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -913,6 +1019,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -1245,6 +1404,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1295,6 +1507,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -1511,6 +1777,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1561,6 +1880,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ha_maria.cc 2010-03-30 20:32:55 +0000
@@ -3471,9 +3471,26 @@ mysql_declare_plugin(maria)
PLUGIN_LICENSE_GPL,
ha_maria_init, /* Plugin Init */
NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
+ 0x0105, /* 1.5 */
status_variables, /* status variables */
system_variables, /* system variables */
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(maria)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &maria_storage_engine,
+ "MARIA",
+ "MySQL AB",
+ "Crash-safe tables with MyISAM heritage",
+ PLUGIN_LICENSE_GPL,
+ ha_maria_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0105, /* 1.5 */
+ status_variables, /* status variables */
+ system_variables, /* system variables */
+ "1.5", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc 2010-01-04 17:54:42 +0000
+++ b/storage/myisam/ha_myisam.cc 2010-03-30 20:32:55 +0000
@@ -2174,6 +2174,23 @@ mysql_declare_plugin(myisam)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_storage_engine,
+ "MyISAM",
+ "MySQL AB",
+ "Default engine as of MySQL 3.23 with great performance",
+ PLUGIN_LICENSE_GPL,
+ myisam_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#ifdef HAVE_QUERY_CACHE
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2010-03-04 08:03:07 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2010-03-30 20:32:55 +0000
@@ -1289,3 +1289,20 @@ mysql_declare_plugin(myisammrg)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_storage_engine,
+ "MRG_MYISAM",
+ "MySQL AB",
+ "Collection of identical MyISAM tables",
+ PLUGIN_LICENSE_GPL,
+ myisammrg_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-03 14:44:14 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-03-30 20:32:55 +0000
@@ -5921,6 +5921,40 @@ mysql_declare_plugin(pbxt)
drizzle_declare_plugin_end;
#else
mysql_declare_plugin_end;
+#ifdef MARIADB_BASE_VERSION
+maria_declare_plugin(pbxt)
+{ /* PBXT */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &pbxt_storage_engine,
+ "PBXT",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "High performance, multi-versioning transactional engine",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init, /* Plugin Init */
+ pbxt_end, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ NULL, /* status variables */
+ pbxt_system_variables, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+},
+{ /* PBXT_STATISTICS */
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &pbxt_statitics,
+ "PBXT_STATISTICS",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "PBXT internal system statitics",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init_statistics, /* plugin init */
+ pbxt_exit_statistics, /* plugin deinit */
+ 0x0005,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
+#endif
#endif
#if defined(XT_WIN) && defined(XT_COREDUMP)
=== modified file 'storage/xtradb/handler/ha_innodb.cc'
--- a/storage/xtradb/handler/ha_innodb.cc 2010-02-01 06:14:12 +0000
+++ b/storage/xtradb/handler/ha_innodb.cc 2010-03-30 20:32:55 +0000
@@ -10818,6 +10818,39 @@ i_s_innodb_index_stats,
i_s_innodb_admin_command,
i_s_innodb_patches
mysql_declare_plugin_end;
+maria_declare_plugin(innobase)
+{ /* InnoDB */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase Oy",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ INNODB_VERSION_SHORT,
+ innodb_status_variables_export,/* status variables */
+ innobase_system_variables, /* system variables */
+ INNODB_VERSION_STR, /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+},
+i_s_innodb_rseg_maria,
+i_s_innodb_buffer_pool_pages_maria,
+i_s_innodb_buffer_pool_pages_index_maria,
+i_s_innodb_buffer_pool_pages_blob_maria,
+i_s_innodb_trx_maria,
+i_s_innodb_locks_maria,
+i_s_innodb_lock_waits_maria,
+i_s_innodb_cmp_maria,
+i_s_innodb_cmp_reset_maria,
+i_s_innodb_cmpmem_maria,
+i_s_innodb_cmpmem_reset_maria,
+i_s_innodb_table_stats_maria,
+i_s_innodb_index_stats_maria,
+i_s_innodb_admin_command_maria,
+i_s_innodb_patches_maria
+maria_declare_plugin_end;
+
/** @brief Initialize the default value of innodb_commit_concurrency.
=== modified file 'storage/xtradb/handler/i_s.cc'
--- a/storage/xtradb/handler/i_s.cc 2010-01-28 11:35:10 +0000
+++ b/storage/xtradb/handler/i_s.cc 2010-03-30 20:32:55 +0000
@@ -393,6 +393,59 @@ UNIV_INTERN struct st_mysql_plugin
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_patches_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "XTRADB_ENHANCEMENTS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Enhancements applied to InnoDB plugin"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_patches_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
{
@@ -1040,6 +1093,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1089,6 +1195,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1138,6 +1297,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
@@ -1373,6 +1585,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -1648,6 +1914,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -1831,22 +2150,75 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
-/*******************************************************************//**
-Common function to fill any of the dynamic tables:
-INFORMATION_SCHEMA.innodb_trx
-INFORMATION_SCHEMA.innodb_locks
-INFORMATION_SCHEMA.innodb_lock_waits
-@return 0 on success */
-static
-int
-trx_i_s_common_fill_table(
-/*======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
{
- const char* table_name;
- int ret;
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
+/*******************************************************************//**
+Common function to fill any of the dynamic tables:
+INFORMATION_SCHEMA.innodb_trx
+INFORMATION_SCHEMA.innodb_locks
+INFORMATION_SCHEMA.innodb_lock_waits
+@return 0 on success */
+static
+int
+trx_i_s_common_fill_table(
+/*======================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ COND* cond) /*!< in: condition (not used) */
+{
+ const char* table_name;
+ int ret;
trx_i_s_cache_t* cache;
DBUG_ENTER("trx_i_s_common_fill_table");
@@ -2163,6 +2535,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2213,6 +2638,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -2431,6 +2909,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2481,6 +3012,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
@@ -2660,6 +3245,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_RSEG"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB rollback segment information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_rseg_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
@@ -2940,6 +3578,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
@@ -2956,6 +3611,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
@@ -3122,3 +3794,20 @@ UNIV_INTERN struct st_mysql_plugin i_s_i
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
=== modified file 'storage/xtradb/handler/i_s.h'
--- a/storage/xtradb/handler/i_s.h 2009-11-04 20:11:12 +0000
+++ b/storage/xtradb/handler/i_s.h 2010-03-30 20:32:55 +0000
@@ -42,4 +42,20 @@ extern struct st_mysql_plugin i_s_innodb
extern struct st_mysql_plugin i_s_innodb_index_stats;
extern struct st_mysql_plugin i_s_innodb_admin_command;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria;
+extern struct st_maria_plugin i_s_innodb_trx_maria;
+extern struct st_maria_plugin i_s_innodb_locks_maria;
+extern struct st_maria_plugin i_s_innodb_lock_waits_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_reset_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_reset_maria;
+extern struct st_maria_plugin i_s_innodb_patches_maria;
+extern struct st_maria_plugin i_s_innodb_rseg_maria;
+extern struct st_maria_plugin i_s_innodb_table_stats_maria;
+extern struct st_maria_plugin i_s_innodb_index_stats_maria;
+extern struct st_maria_plugin i_s_innodb_admin_command_maria;
+
#endif /* i_s_h */
2
1

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2765)
by Michael Widenius 01 Apr '10
by Michael Widenius 01 Apr '10
01 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100401091008-1tfywox0wefeygvb
2765 Michael Widenius 2010-04-01 [merge]
Auto merge with 5.1
modified:
support-files/compiler_warnings.supp
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-04-01 09:08:42 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-01 09:40:11 +0000
@@ -27,7 +27,7 @@ pars0grm.tab.c: .*'yyerrorlab' : unrefer
_flex_tmp.c: .*not enough actual parameters for macro 'yywrap'.*
pars0lex.l: .*conversion from 'ulint' to 'int', possible loss of data.*
btr/btr0cur\.c: .*value computed is not used.*: 3175-3375
-include/buf0buf\.ic: unused parameter ���mtr���
+include/buf0buf\.ic: unused parameter .*mtr.*
fil/fil0fil\.c: pointer targets in passing argument.*differ in signedness
fil/fil0fil\.c: comparison between signed and unsigned : 3100-3199
fil/fil0fil\.c: unused parameter
@@ -58,7 +58,7 @@ readline\.c : unused parameter
term\.c : unused parameter
vi\.c : unused parameter
common\.c : unused parameter
-term\.c : *.*
+term\.c : .*
#
1
0

[Maria-developers] Rev 2751: options for CREATE TABLE (MWL#43) in file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/
by sanja@askmonty.org 01 Apr '10
by sanja@askmonty.org 01 Apr '10
01 Apr '10
At file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/
------------------------------------------------------------
revno: 2751
revision-id: sanja(a)askmonty.org-20100326215117-svblh338osfg4i1c
parent: sergii(a)pisem.net-20100323092233-t2gwaclx94hd6exa
committer: sanja(a)askmonty.org
branch nick: work-maria-5.2-createoptions2
timestamp: Fri 2010-03-26 23:51:17 +0200
message:
options for CREATE TABLE (MWL#43)
=== modified file 'Docs/sp-imp-spec.txt'
--- a/Docs/sp-imp-spec.txt 2004-03-23 11:04:40 +0000
+++ b/Docs/sp-imp-spec.txt 2010-03-26 21:51:17 +0000
@@ -1075,7 +1075,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_ERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -1097,4 +1097,4 @@
) comment='Stored Procedures';
--
-
\ No newline at end of file
+
=== modified file 'include/my_base.h'
--- a/include/my_base.h 2010-02-10 19:06:24 +0000
+++ b/include/my_base.h 2010-03-26 21:51:17 +0000
@@ -314,6 +314,8 @@
#define HA_OPTION_RELIES_ON_SQL_LAYER 512
#define HA_OPTION_NULL_FIELDS 1024
#define HA_OPTION_PAGE_CHECKSUM 2048
+/* .frm has extra create options in linked-list format */
+#define HA_OPTION_TEXT_CREATE_OPTIONS (1L << 14)
#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */
#define HA_OPTION_READ_ONLY_DATA (1L << 16) /* Set by isamchk */
#define HA_OPTION_NO_CHECKSUM (1L << 17)
=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt 2010-01-31 09:13:21 +0000
+++ b/libmysqld/CMakeLists.txt 2010-03-26 21:51:17 +0000
@@ -139,7 +139,8 @@
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
- ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/create_options.cc
${GEN_SOURCES}
${LIB_SOURCES})
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-12-03 11:19:05 +0000
+++ b/libmysqld/Makefile.am 2010-03-26 21:51:17 +0000
@@ -75,7 +75,7 @@
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
debug_sync.cc \
- sql_tablespace.cc \
+ sql_tablespace.cc create_options.cc \
rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc event_parse_data.cc opt_table_elimination.cc
=== added file 'mysql-test/r/create_options.result'
--- a/mysql-test/r/create_options.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/create_options.result 2010-03-26 21:51:17 +0000
@@ -0,0 +1,169 @@
+drop table if exists t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'='vvv'
+Warning 1650 Unknown option 'dff'='vvv'
+Warning 1650 Unknown option 'tkey1'='1v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey='vvv',
+ KEY `akey` (`a`) dff='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey1='1v1'
+drop table t1;
+#reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'='vvv'
+Warning 1650 Unknown option 'dff'='vvv'
+Warning 1650 Unknown option 'tkey1'='1v2'
+Warning 1650 Unknown option 'tkey2'='2v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey='vvv',
+ KEY `akey` (`a`) dff='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey1='1v2' tkey2='2v1'
+#add option
+alter table t1 tkey4=4v1;
+Warnings:
+Warning 1650 Unknown option 'tkey4'='4v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey='vvv',
+ KEY `akey` (`a`) dff='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey1='1v2' tkey2='2v1' tkey4='4v1'
+#remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey='vvv',
+ KEY `akey` (`a`) dff='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey1='1v2' tkey2='2v1'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unknown option 'fkey1'='v1'
+Warning 1650 Unknown option 'kkey1'='v1'
+Warning 1650 Unknown option 'tkey2'='2v1'
+Warning 1650 Unknown option 'tkey3'='3v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v1',
+ KEY `akey` (`a`) kkey1='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+Warnings:
+Warning 1650 Unknown option 'FKEY1'='v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL FKEY1='v1',
+ KEY `akey` (`a`) kkey1='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning 1650 Unknown option 'fkey1'='v2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ KEY `akey` (`a`) kkey1='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#new column no options
+alter table t1 add column b int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) kkey1='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning 1650 Unknown option 'kkey2'='v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) kkey1='v1',
+ KEY `bkey` (`b`) kkey2='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+Warnings:
+Warning 1650 Unknown option 'fkey1'='v1'
+Warning 1650 Unknown option 'fkey2'='v2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL fkey1='v1' fkey2='v2',
+ KEY `akey` (`a`) kkey1='v1',
+ KEY `bkey` (`b`) kkey2='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL fkey1='v1' fkey2='v2',
+ KEY `akey` (`a`) kkey1='v1',
+ KEY `bkey` (`b`) kkey2='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#drop column
+alter table t1 drop b;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `c` int(11) DEFAULT NULL fkey1='v1' fkey2='v2',
+ KEY `akey` (`a`) kkey1='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#add column with options after delete
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning 1650 Unknown option 'fkey2'='v1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `c` int(11) DEFAULT NULL fkey1='v1' fkey2='v2',
+ `b` int(11) DEFAULT NULL fkey2='v1',
+ KEY `akey` (`a`) kkey1='v1',
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+#add key
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning 1650 Unknown option 'kkey2'='v2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL fkey1='v2',
+ `c` int(11) DEFAULT NULL fkey1='v1' fkey2='v2',
+ `b` int(11) DEFAULT NULL fkey2='v1',
+ KEY `akey` (`a`) kkey1='v1',
+ KEY `ckey` (`c`),
+ KEY `bkey` (`b`) kkey2='v2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 tkey2='2v1' tkey3='3v1'
+drop table t1;
+#error on unknown option
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+ERROR HY000: Unknown option 'fkey'='vvv'
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/r/events_bugs.result'
--- a/mysql-test/r/events_bugs.result 2009-03-11 20:30:56 +0000
+++ b/mysql-test/r/events_bugs.result 2010-03-26 21:51:17 +0000
@@ -729,9 +729,8 @@
create event e1 on schedule every 1 day do select 1;
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_ERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
name
=== modified file 'mysql-test/r/information_schema.result'
--- a/mysql-test/r/information_schema.result 2010-03-15 11:51:23 +0000
+++ b/mysql-test/r/information_schema.result 2010-03-26 21:51:17 +0000
@@ -615,7 +615,7 @@
proc definer char(77)
proc created timestamp
proc modified timestamp
-proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
proc comment char(64)
proc character_set_client char(32)
proc collation_connection char(32)
=== modified file 'mysql-test/r/plugin_load.result'
--- a/mysql-test/r/plugin_load.result 2008-01-26 00:05:15 +0000
+++ b/mysql-test/r/plugin_load.result 2010-03-26 21:51:17 +0000
@@ -1,3 +1,43 @@
SELECT @@global.example_enum_var = 'e2';
@@global.example_enum_var = 'e2'
1
+#legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example UUL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL complex='c,f,f,f'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 UUL=10000 STR='dskj' one_or_two='one' YESNO=0
+drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+#illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+Warnings:
+Warning 1651 Incorrect option value 'UUL'='10000000000000000000'
+Warning 1651 Incorrect option value 'one_or_two'='ttt'
+Warning 1651 Incorrect option value 'YESNO'='SSS'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 UUL=4294967295 YESNO=0
+#alter table
+alter table t1 UUL=10000000;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 YESNO=0 UUL=10000000
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL complex='c,c,c'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 YESNO=0 UUL=10000000
+drop table t1;
+#illegal value error
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+ERROR HY000: Incorrect option value 'UUL'='10000000000000000000'
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result 2009-12-23 13:44:03 +0000
+++ b/mysql-test/r/sp.result 2010-03-26 21:51:17 +0000
@@ -6940,9 +6940,8 @@
call p();
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_ERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
name
=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result 2009-10-27 10:09:36 +0000
+++ b/mysql-test/r/system_mysql_db.result 2010-03-26 21:51:17 +0000
@@ -200,7 +200,7 @@
`definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
- `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
@@ -225,7 +225,7 @@
`ends` datetime DEFAULT NULL,
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
- `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`originator` int(10) unsigned NOT NULL,
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2009-10-28 09:23:02 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-03-26 21:51:17 +0000
@@ -49,7 +49,7 @@
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned select,insert,update,references
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql event sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select,insert,update,references
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references
@@ -124,7 +124,7 @@
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
+NULL mysql proc sql_mode 15 NO set 488 1464 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') select,insert,update,references
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI select,insert,update,references
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references
@@ -327,7 +327,7 @@
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +402,7 @@
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 488 1464 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result 2009-05-19 16:43:50 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result 2010-03-26 21:51:17 +0000
@@ -49,7 +49,7 @@
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE')
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64)
@@ -124,7 +124,7 @@
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER')
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64)
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL
@@ -327,7 +327,7 @@
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +402,7 @@
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
-3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
=== added file 'mysql-test/t/create_options.test'
--- a/mysql-test/t/create_options.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/create_options.test 2010-03-26 21:51:17 +0000
@@ -0,0 +1,63 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+show create table t1;
+drop table t1;
+
+--echo #reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+show create table t1;
+
+-- echo #add option
+alter table t1 tkey4=4v1;
+show create table t1;
+
+--echo #remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+show create table t1;
+
+drop table t1;
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+show create table t1;
+
+--echo #change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+show create table t1;
+--echo #change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+show create table t1;
+--echo #new column no options
+alter table t1 add column b int;
+show create table t1;
+--echo #new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+show create table t1;
+--echo #new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+show create table t1;
+--echo #new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+--echo #drop column
+alter table t1 drop b;
+show create table t1;
+--echo #add column with options after delete
+alter table t1 add column b int fkey2=v1;
+show create table t1;
+--echo #add key
+alter table t1 add key bkey (b) kkey2=v2;
+show create table t1;
+drop table t1;
+
+--echo #error on unknown option
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+--error ER_UNKNOWN_OPTION
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/t/events_bugs.test'
--- a/mysql-test/t/events_bugs.test 2009-03-11 20:30:56 +0000
+++ b/mysql-test/t/events_bugs.test 2010-03-26 21:51:17 +0000
@@ -1204,7 +1204,6 @@
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
drop event e1;
=== modified file 'mysql-test/t/exampledb.test'
--- a/mysql-test/t/exampledb.test 2006-05-05 17:08:40 +0000
+++ b/mysql-test/t/exampledb.test 2010-03-26 21:51:17 +0000
@@ -20,3 +20,4 @@
drop table t1;
# End of 4.1 tests
+
=== modified file 'mysql-test/t/plugin_load.test'
--- a/mysql-test/t/plugin_load.test 2009-10-08 08:39:15 +0000
+++ b/mysql-test/t/plugin_load.test 2010-03-26 21:51:17 +0000
@@ -2,3 +2,30 @@
--source include/have_example_plugin.inc
SELECT @@global.example_enum_var = 'e2';
+
+--echo #legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example UUL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+drop table t1;
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+
+--echo #illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+show create table t1;
+
+--echo #alter table
+alter table t1 UUL=10000000;
+show create table t1;
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+drop table t1;
+
+
+--echo #illegal value error
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+--error ER_BAD_OPTION_VALUE
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
=== modified file 'mysql-test/t/sp.test'
--- a/mysql-test/t/sp.test 2009-12-23 13:44:03 +0000
+++ b/mysql-test/t/sp.test 2010-03-26 21:51:17 +0000
@@ -8210,7 +8210,6 @@
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
drop procedure p;
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql 2009-10-27 10:09:36 +0000
+++ b/scripts/mysql_system_tables.sql 2010-03-26 21:51:17 +0000
@@ -60,7 +60,7 @@
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
-CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
+CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'CREATE_OPTIONS_ERR', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
@@ -80,7 +80,7 @@
EXECUTE stmt;
DROP PREPARE stmt;
-CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
+CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
=== modified file 'scripts/mysql_system_tables_fix.sql'
--- a/scripts/mysql_system_tables_fix.sql 2009-12-03 16:15:47 +0000
+++ b/scripts/mysql_system_tables_fix.sql 2010-03-26 21:51:17 +0000
@@ -368,7 +368,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_ERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -482,14 +482,14 @@
ALTER TABLE event DROP PRIMARY KEY;
ALTER TABLE event ADD PRIMARY KEY(db, name);
# Add sql_mode column just in case.
-ALTER TABLE event ADD sql_mode set ('NOT_USED') AFTER on_completion;
+ALTER TABLE event ADD sql_mode set ('CREATE_OPTIONS_ERR') AFTER on_completion;
# Update list of sql_mode values.
ALTER TABLE event MODIFY sql_mode
set('REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_ERR',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2010-03-03 14:44:14 +0000
+++ b/sql/CMakeLists.txt 2010-03-26 21:51:17 +0000
@@ -77,6 +77,7 @@
rpl_rli.cc rpl_mi.cc sql_servers.cc
sql_connect.cc scheduler.cc
sql_profile.cc event_parse_data.cc opt_table_elimination.cc
+ create_options.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/sql/Makefile.am 2010-03-26 21:51:17 +0000
@@ -78,7 +78,8 @@
sql_plugin.h authors.h event_parse_data.h \
event_data_objects.h event_scheduler.h \
sql_partition.h partition_info.h partition_element.h \
- contributors.h sql_servers.h
+ contributors.h sql_servers.h \
+ create_options.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -124,7 +125,7 @@
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \
sql_servers.cc event_parse_data.cc \
- opt_table_elimination.cc
+ opt_table_elimination.cc create_options.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc 2010-03-15 11:51:23 +0000
+++ b/sql/event_db_repository.cc 2010-03-26 21:51:17 +0000
@@ -105,7 +105,8 @@
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY',"
+ "'NO_UNSIGNED_SUBTRACTION',"
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2010-03-17 02:32:31 +0000
+++ b/sql/field.cc 2010-03-26 21:51:17 +0000
@@ -1308,7 +1308,8 @@
utype unireg_check_arg, const char *field_name_arg)
:ptr(ptr_arg), null_ptr(null_ptr_arg),
table(0), orig_table(0), table_name(0),
- field_name(field_name_arg),
+ field_name(field_name_arg), option_list(0),
+ option_struct(0), new_option_struct(0),
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),
@@ -9567,7 +9568,8 @@
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,
- Virtual_column_info *fld_vcol_info)
+ Virtual_column_info *fld_vcol_info,
+ engine_option_value *create_opt)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9578,6 +9580,7 @@
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
+ option_list= create_opt;
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
@@ -10217,6 +10220,8 @@
decimals= old_field->decimals();
vcol_info= old_field->vcol_info;
stored_in_db= old_field->stored_in_db;
+ option_list= old_field->option_list;
+ option_struct= NULL;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -10291,6 +10296,22 @@
/**
+ Makes a clone of this object for ALTER/CREATE TABLE
+
+ @note: We need to do the clone of the list because in
+ ALTER TABLE we may change the list for the cloned field
+
+ @param mem_root MEM_ROOT where to clone the field
+*/
+
+Create_field *Create_field::clone(MEM_ROOT *mem_root) const
+{
+ Create_field *res= new (mem_root) Create_field(*this);
+ return res;
+}
+
+
+/**
maximum possible display length for blob.
@return
=== modified file 'sql/field.h'
--- a/sql/field.h 2010-03-15 11:51:23 +0000
+++ b/sql/field.h 2010-03-26 21:51:17 +0000
@@ -137,6 +137,14 @@
struct st_table *table; // Pointer for table
struct st_table *orig_table; // Pointer to original table
const char **table_name, *field_name;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
+ /**
+ structure with parsed new field parameters in ALTER TABLE for
+ check_if_incompatible_data()
+ */
+ void *new_option_struct;
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -2145,6 +2153,9 @@
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
+ engine_option_value *option_list;
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
@@ -2162,11 +2173,11 @@
*/
bool stored_in_db;
- Create_field() :after(0) {}
+ Create_field() :after(0), option_list(NULL), option_struct(NULL)
+ {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
- Create_field *clone(MEM_ROOT *mem_root) const
- { return new (mem_root) Create_field(*this); }
+ Create_field *clone(MEM_ROOT *mem_root) const;
void create_length_to_internal_length(void);
/* Init for a tmp table field. To be extended if need be. */
@@ -2178,8 +2189,8 @@
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,
- Virtual_column_info *vcol_info);
+ uint uint_geom_type, Virtual_column_info *vcol_info,
+ engine_option_value *option_list);
bool field_flags_are_binary()
{
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc 2010-03-26 21:51:17 +0000
@@ -1218,7 +1218,9 @@
DBUG_ENTER("prepare_new_partition");
if ((error= set_up_table_before_create(tbl, part_name, create_info,
- 0, p_elem)))
+ 0, p_elem)) ||
+ parse_engine_table_options(ha_thd(), file->ht,
+ file->table_share))
goto error_create;
if ((error= file->ha_create(part_name, tbl, create_info)))
{
@@ -1869,6 +1871,8 @@
{
if ((error= set_up_table_before_create(table_arg, from_buff,
create_info, i, NULL)) ||
+ parse_engine_table_options(ha_thd(), (*file)->ht,
+ (*file)->table_share) ||
((error= (*file)->ha_create(from_buff, table_arg, create_info))))
goto create_error;
}
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-03-15 11:51:23 +0000
+++ b/sql/handler.cc 2010-03-26 21:51:17 +0000
@@ -3716,7 +3716,12 @@
name= get_canonical_filename(table.file, share.path.str, name_buff);
+ if (parse_engine_table_options(thd, table.file->ht, &share))
+ goto err;
+
error= table.file->ha_create(name, &table, create_info);
+
+
VOID(closefrm(&table, 0));
if (error)
{
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2010-02-01 06:14:12 +0000
+++ b/sql/handler.h 2010-03-26 21:51:17 +0000
@@ -16,6 +16,9 @@
/* Definitions for parameters to do with handler-routines */
+#ifndef _HANDLER_H
+#define _HANDLER_H
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -23,6 +26,7 @@
#include <my_handler.h>
#include <ft_global.h>
#include <keycache.h>
+#include "create_options.h"
#ifndef NO_HASH
#define NO_HASH /* Not yet implemented */
@@ -516,6 +520,7 @@
struct st_table;
typedef struct st_table TABLE;
typedef struct st_table_share TABLE_SHARE;
+class engine_option;
struct st_foreign_key_info;
typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
@@ -549,6 +554,71 @@
enum log_status status;
};
+enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */
+ HA_OPTION_TYPE_STRING, /* char * */
+ HA_OPTION_TYPE_ENUM, /* uint */
+ HA_OPTION_TYPE_BOOL}; /* uint */
+
+#define HA_xOPTION_ULL(name, struc, field, def, min, max, blk_siz) \
+ { HA_OPTION_TYPE_ULL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, min, max, blk_siz, 0 }
+#define HA_xOPTION_STRING(name, struc, field) \
+ { HA_OPTION_TYPE_STRING, name, sizeof(name)-1, \
+ offsetof(struc, field), 0, 0, 0, 0, 0 }
+#define HA_xOPTION_ENUM(name, struc, field, values, def) \
+ { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, \
+ sizeof(values)-1, 0, values }
+#define HA_xOPTION_BOOL(name, struc, field, def) \
+ { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, 1, 0, 0 }
+#define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define HA_TOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_table_option_struct, field, def, min, max, blk_siz)
+#define HA_TOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_table_option_struct, field)
+#define HA_TOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def)
+#define HA_TOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_table_option_struct, field, def)
+#define HA_TOPTION_END HA_xOPTION_END
+
+#define HA_FOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_field_option_struct, field, def, min, max, blk_siz)
+#define HA_FOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_field_option_struct, field)
+#define HA_FOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def)
+#define HA_FOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_field_option_struct, field, def)
+#define HA_FOPTION_END HA_xOPTION_END
+
+#define HA_KOPTION_ULL(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_ULL(name, ha_key_option_struct, field, def, min, max, blk_siz)
+#define HA_KOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_key_option_struct, field)
+#define HA_KOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_BOOL(name, field, values, def) \
+ HA_xOPTION_BOOL(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_END HA_xOPTION_END
+
+typedef struct st_ha_create_table_option {
+ enum ha_option_type type;
+ const char *name;
+ size_t name_length;
+ ptrdiff_t offset;
+ ulonglong def_value;
+ ulonglong min_value, max_value, block_size;
+ const char *values;
+} ha_create_table_option;
+
+typedef struct st_ha_create_table_option_rules {
+ ha_create_table_option *table,
+ *field,
+ *key;
+} ha_create_table_option_rules;
enum handler_iterator_type
{
@@ -721,7 +791,7 @@
int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
const char *name);
uint32 license; /* Flag for Engine License */
- void *data; /* Location for engines to keep personal structures */
+ ha_create_table_option_rules *table_options_rules;
};
@@ -950,6 +1020,16 @@
bool varchar; /* 1 if table has a VARCHAR */
enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
enum ha_choice page_checksum; /* If we have page_checksums */
+ engine_option_value *option_list; /* list of table create options */
+ engine_option_value *option_list_last;
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
+ /* following 4 fields assigned only for check_if_incompatible_data() */
+ void *old_option_struct;
+ Field **old_field;
+ KEY *old_key_info;
+ uint old_keys;
+
} HA_CREATE_INFO;
@@ -2241,3 +2321,5 @@
#define ha_binlog_wait(a) do {} while (0)
#define ha_binlog_end(a) do {} while (0)
#endif
+
+#endif
=== modified file 'sql/log_event.h'
--- a/sql/log_event.h 2010-03-15 11:51:23 +0000
+++ b/sql/log_event.h 2010-03-26 21:51:17 +0000
@@ -1371,7 +1371,7 @@
MODE_PIPES_AS_CONCAT==0x2
MODE_ANSI_QUOTES==0x4
MODE_IGNORE_SPACE==0x8
- MODE_NOT_USED==0x10
+ MODE_CREATE_OPTIONS_ERR==0x10
MODE_ONLY_FULL_GROUP_BY==0x20
MODE_NO_UNSIGNED_SUBTRACTION==0x40
MODE_NO_DIR_IN_CREATE==0x80
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2010-03-15 11:51:23 +0000
+++ b/sql/mysql_priv.h 2010-03-26 21:51:17 +0000
@@ -54,7 +54,6 @@
#include "sql_plugin.h"
#include "scheduler.h"
#include "log_slow.h"
-
class Parser_state;
/**
@@ -520,7 +519,7 @@
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
-#define MODE_NOT_USED 16
+#define MODE_CREATE_OPTIONS_ERR 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define MODE_NO_DIR_IN_CREATE 128
@@ -783,6 +782,7 @@
ulonglong *engine_data);
#include "sql_string.h"
#include "sql_list.h"
+#include "create_options.h"
#include "sql_map.h"
#include "my_decimal.h"
#include "handler.h"
@@ -1508,7 +1508,8 @@
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info);
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-15 11:51:23 +0000
+++ b/sql/mysqld.cc 2010-03-26 21:51:17 +0000
@@ -243,7 +243,7 @@
static const char *sql_mode_names[]=
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "CREATE_OPTIONS_ERR", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"NO_DIR_IN_CREATE",
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
@@ -263,7 +263,7 @@
/*PIPES_AS_CONCAT*/ 15,
/*ANSI_QUOTES*/ 11,
/*IGNORE_SPACE*/ 12,
- /*?*/ 1,
+ /*CREATE_OPTIONS_ERR*/ 18,
/*ONLY_FULL_GROUP_BY*/ 18,
/*NO_UNSIGNED_SUBTRACTION*/ 23,
/*NO_DIR_IN_CREATE*/ 16,
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2010-03-15 11:51:23 +0000
+++ b/sql/share/errmsg.txt 2010-03-26 21:51:17 +0000
@@ -6240,3 +6240,8 @@
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"
+
+ER_UNKNOWN_OPTION
+ eng "Unknown option '%-.64s'='%-.64s'"
+ER_BAD_OPTION_VALUE
+ eng "Incorrect option value '%-.64s'='%-.64s'"
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp.cc 2010-03-26 21:51:17 +0000
@@ -147,7 +147,8 @@
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY',"
+ "'NO_UNSIGNED_SUBTRACTION',"
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp_head.cc 2010-03-26 21:51:17 +0000
@@ -2216,7 +2216,7 @@
lex->charset ? lex->charset :
thd->variables.collation_database,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_class.cc 2010-03-26 21:51:17 +0000
@@ -106,6 +106,7 @@
key_create_info(rhs.key_create_info),
columns(rhs.columns, mem_root),
name(rhs.name),
+ option_list(rhs.option_list),
generated(rhs.generated)
{
list_copy_and_replace_each_value(columns, mem_root);
@@ -775,6 +776,7 @@
void THD::push_internal_handler(Internal_error_handler *handler)
{
+ DBUG_ENTER("THD::push_internal_handler");
if (m_internal_handler)
{
handler->m_prev_internal_handler= m_internal_handler;
@@ -784,6 +786,7 @@
{
m_internal_handler= handler;
}
+ DBUG_VOID_RETURN;
}
@@ -803,8 +806,10 @@
void THD::pop_internal_handler()
{
+ DBUG_ENTER("THD::pop_internal_handler");
DBUG_ASSERT(m_internal_handler != NULL);
m_internal_handler= m_internal_handler->m_prev_internal_handler;
+ DBUG_VOID_RETURN;
}
extern "C"
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_class.h 2010-03-26 21:51:17 +0000
@@ -204,13 +204,15 @@
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
+ engine_option_value *option_list;
bool generated;
Key(enum Keytype type_par, const char *name_arg,
KEY_CREATE_INFO *key_info_arg,
- bool generated_arg, List<Key_part_spec> &cols)
+ bool generated_arg, List<Key_part_spec> &cols,
+ engine_option_value *create_opt)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
- name(name_arg), generated(generated_arg)
+ name(name_arg), option_list(create_opt), generated(generated_arg)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -239,7 +241,7 @@
Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
- :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_lex.h 2010-03-26 21:51:17 +0000
@@ -869,6 +869,7 @@
#define ALTER_ALL_PARTITION (1L << 21)
#define ALTER_REMOVE_PARTITIONING (1L << 22)
#define ALTER_FOREIGN_KEY (1L << 23)
+#define ALTER_CREATE_OPT (1L << 24)
enum enum_alter_table_change_level
{
@@ -1747,6 +1748,11 @@
const char *stmt_definition_end;
/**
+ Collects create options for Field and KEY
+ */
+ engine_option_value *option_list, *option_list_last;
+
+ /**
During name resolution search only in the table list given by
Name_resolution_context::first_name_resolution_table and
Name_resolution_context::last_name_resolution_table
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_parse.cc 2010-03-26 21:51:17 +0000
@@ -6155,7 +6155,8 @@
char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info)
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6173,7 +6174,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::PRIMARY, NullS,
&default_key_create_info,
- 0, lex->col_list);
+ 0, lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6183,7 +6184,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
- lex->col_list);
+ lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6241,7 +6242,8 @@
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, vcol_info))
+ interval_list, cs, uint_geom_type, vcol_info,
+ create_options))
DBUG_RETURN(1);
lex->alter_info.create_list.push_back(new_field);
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_show.cc 2010-03-26 21:51:17 +0000
@@ -83,6 +83,11 @@
static void
append_algorithm(TABLE_LIST *table, String *buff);
+static void
+append_quoted(THD *thd, String *packet, const char *name, uint length,
+ int q);
+static int get_quote_char_for_option(THD *thd, const char *name, uint length);
+
static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table);
/***************************************************************************
@@ -951,6 +956,30 @@
DBUG_RETURN(0);
}
+
+/**
+ Goes through all character combinations and ensure that it is number.
+
+ @param name attribute name
+ @param name_length length of name
+
+ @retval # Pointer to conflicting character
+ @retval 0 No conflicting character
+*/
+
+static const char *is_unsigned_number(const char *name, uint name_length)
+{
+ const char *end= name + name_length;
+
+ for (; name < end ; name++)
+ {
+ uchar chr= (uchar) *name;
+ if (chr < '0' || chr > '9')
+ return name;
+ }
+ return 0;
+}
+
/*
Go through all character combinations and ensure that sql_lex.cc can
parse it as an identifier.
@@ -1001,19 +1030,26 @@
void
append_identifier(THD *thd, String *packet, const char *name, uint length)
{
+ int q= get_quote_char_for_identifier(thd, name, length);
+
+ append_quoted(thd, packet, name, length, q);
+}
+
+static void
+append_quoted(THD *thd, String *packet, const char *name, uint length,
+ int q)
+{
+ char quote_char;
const char *name_end;
- char quote_char;
- int q= get_quote_char_for_identifier(thd, name, length);
if (q == EOF)
{
packet->append(name, length, packet->charset());
return;
}
-
/*
The identifier must be quoted as it includes a quote character or
- it's a keyword
+ it's a keyword
*/
VOID(packet->reserve(length*2 + 2));
@@ -1076,6 +1112,27 @@
return '`';
}
+/**
+ Gets the quote character for displaying an option key.
+
+ @param thd Thread handler
+ @param name name to quote
+ @param length length of name
+
+ @retval EOF No quote character is needed
+ @retval # Quote character
+*/
+
+static int get_quote_char_for_option(THD *thd, const char *name, uint length)
+{
+ if (length &&
+ !require_quotes(name, length))
+ return EOF;
+ if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
+ return '"';
+ return '`';
+}
+
/* Append directory name (if exists) to CREATE INFO */
@@ -1173,6 +1230,35 @@
return has_default;
}
+
+/**
+ Appends list of options to string
+
+ @param thd thread handler
+ @param packet string to append
+ @param opt list of options
+*/
+
+static void append_create_options(THD *thd, String *packet,
+ engine_option_value *opt)
+{
+ for(; opt; opt= opt->next)
+ {
+ packet->append(' ');
+ {
+ int q= get_quote_char_for_option(thd, opt->name.str, opt->name.length);
+
+ append_quoted(thd, packet, opt->name.str, opt->name.length, q);
+ }
+ packet->append('=');
+ if (opt->value.length < 21 &&
+ is_unsigned_number(opt->value.str, opt->value.length) == NULL)
+ packet->append(opt->value.str, opt->value.length);
+ else
+ append_unescaped(packet, opt->value.str, opt->value.length);
+ }
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1355,6 +1441,8 @@
packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
+ if (field->option_list)
+ append_create_options(thd, packet, field->option_list);
}
key_info= table->key_info;
@@ -1426,6 +1514,8 @@
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
}
+ if (key_info->option_list)
+ append_create_options(thd, packet, key_info->option_list);
}
/*
@@ -1585,6 +1675,10 @@
packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
+ /* create_table_options can be NULL for temporary tables */
+ if (share->option_list)
+ append_create_options(thd, packet,
+ share->option_list);
append_directory(thd, packet, "DATA", create_info.data_file_name);
append_directory(thd, packet, "INDEX", create_info.index_file_name);
}
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_table.cc 2010-03-26 21:51:17 +0000
@@ -2562,6 +2562,7 @@
ulong record_offset= 0;
KEY *key_info;
KEY_PART_INFO *key_part_info;
+ ha_create_table_option_rules *rules, fake_empty={NULL,NULL,NULL};
int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
@@ -2570,6 +2571,10 @@
uint total_uneven_bit_length= 0;
DBUG_ENTER("mysql_prepare_create_table");
+ rules= (create_info->db_type->table_options_rules ?
+ create_info->db_type->table_options_rules:
+ &fake_empty);
+
select_field_pos= alter_info->create_list.elements - select_field_count;
null_fields=blob_columns=0;
create_info->varchar= 0;
@@ -2863,6 +2868,11 @@
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
+ if (parse_option_list(thd, &sql_field->option_struct,
+ sql_field->option_list,
+ rules->field, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
/*
For now skip fields that are not physically stored in the database
(virtual fields) and update their offset later
@@ -3061,6 +3071,12 @@
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
key_info->algorithm= key->key_create_info.algorithm;
+ key_info->option_list= key->option_list;
+ if (parse_option_list(thd, &key_info->option_struct,
+ key_info->option_list,
+ rules->key, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
if (key->type == Key::FULLTEXT)
{
@@ -3438,6 +3454,12 @@
}
}
+ if (parse_option_list(thd, &create_info->option_struct,
+ create_info->option_list,
+ rules->table, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
+
DBUG_RETURN(FALSE);
}
@@ -5809,6 +5831,9 @@
DBUG_RETURN(0);
}
+ /* to allow check_if_incompatible_data compare */
+ field->new_option_struct= tmp_new_field->option_struct;
+
/* 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) ||
@@ -5956,9 +5981,15 @@
}
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
}
+ else
+ table_key->new_option_struct= new_key->option_struct;
}
/* Check if changes are compatible with current handler without a copy */
+ create_info->old_option_struct= table->s->option_struct;
+ create_info->old_field= table->field;
+ create_info->old_keys= table->s->keys;
+ create_info->old_key_info= table->key_info;
if (table->file->check_if_incompatible_data(create_info, changes))
{
DBUG_PRINT("info", ("check_if_incompatible_data() -> "
@@ -6132,6 +6163,16 @@
}
restore_record(table, s->default_values); // Empty record for DEFAULT
+ if (create_info->option_list)
+ {
+ create_info->option_list=
+ merge_engine_table_options(table->s->option_list,
+ create_info->option_list,
+ thd->mem_root);
+ }
+ else
+ create_info->option_list= table->s->option_list;
+
/*
First collect all fields from table which isn't in drop_list
*/
@@ -6384,7 +6425,7 @@
key= new Key(key_type, key_name,
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts);
+ key_parts, key_info->option_list);
new_key_list.push_back(key);
}
}
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2010-03-04 08:03:07 +0000
+++ b/sql/sql_view.cc 2010-03-26 21:51:17 +0000
@@ -1183,7 +1183,7 @@
+ MODE_PIPES_AS_CONCAT affect expression parsing
+ MODE_ANSI_QUOTES affect expression parsing
+ MODE_IGNORE_SPACE affect expression parsing
- - MODE_NOT_USED not used :)
+ - MODE_CREATE_OPTIONS_ERR affect only CREATE/ALTER TABLE parsing
* MODE_ONLY_FULL_GROUP_BY affect execution
* MODE_NO_UNSIGNED_SUBTRACTION affect execution
- MODE_NO_DIR_IN_CREATE affect table creation only
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-03-15 11:51:23 +0000
+++ b/sql/sql_yacc.yy 2010-03-26 21:51:17 +0000
@@ -607,6 +607,7 @@
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change= NullS;
+ lex->option_list= lex->option_list_last= NULL;
return FALSE;
}
@@ -616,7 +617,7 @@
{
Key *key;
key= new Key(type, name, info ? info : &lex->key_create_info, generated,
- lex->col_list);
+ lex->col_list, lex->option_list);
if (key == NULL)
return TRUE;
@@ -1858,6 +1859,8 @@
lex->create_info.default_table_charset= NULL;
lex->name.str= 0;
lex->name.length= 0;
+ lex->create_info.option_list=
+ lex->create_info.option_list_last= NULL;
}
create2
{
@@ -2340,6 +2343,7 @@
lex->interval_list.empty();
lex->uint_geom_type= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
;
@@ -4748,6 +4752,43 @@
Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
Lex->create_info.transactional= $3;
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->create_info.option_list,
+ &Lex->create_info.option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->create_info.option_list,
+ &Lex->create_info.option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->create_info.option_list,
+ &Lex->create_info.option_list_last,
+ YYTHD->mem_root);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->create_info.option_list,
+ &Lex->create_info.option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
;
default_charset:
@@ -4869,25 +4910,33 @@
;
key_def:
- normal_key_type opt_ident key_alg '(' key_list ')' normal_key_options
+ normal_key_type opt_ident key_alg '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $1, $2))
MYSQL_YYABORT;
}
| fulltext opt_key_or_index opt_ident init_key_options
- '(' key_list ')' fulltext_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ fulltext_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| spatial opt_key_or_index opt_ident init_key_options
- '(' key_list ')' spatial_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ spatial_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| opt_constraint constraint_key_type opt_ident key_alg
- '(' key_list ')' normal_key_options
+ '(' key_list ')'
+ { Lex->option_list= Lex->option_list_last= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $2, $3 ? $3 : $1))
MYSQL_YYABORT;
@@ -4950,6 +4999,7 @@
lex->comment=null_lex_str;
lex->charset=NULL;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
field_def
{
@@ -4960,7 +5010,7 @@
&lex->comment,
lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
;
@@ -5380,6 +5430,43 @@
Lex->charset=$2;
}
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
;
now_or_signed_literal:
@@ -5669,6 +5756,43 @@
all_key_opt:
KEY_BLOCK_SIZE opt_equal ulong_num
{ Lex->key_create_info.block_size= $3; }
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3.str, $3.length,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ $3,
+ &Lex->option_list,
+ &Lex->option_list_last,
+ YYTHD->mem_root);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1,
+ NULL, 0,
+ &Lex->option_list,
+ &Lex->option_list_last);
+ Lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
;
normal_key_opt:
@@ -6158,6 +6282,7 @@
LEX *lex=Lex;
lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->option_list= lex->option_list_last= NULL;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -6169,6 +6294,7 @@
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
field_def
{
@@ -6180,7 +6306,7 @@
&lex->comment,
$3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
opt_place
@@ -6287,8 +6413,7 @@
}
| create_table_options_space_separated
{
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_OPTIONS;
+ Lex->alter_info.flags|= ALTER_OPTIONS;
}
| FORCE_SYM
{
@@ -13630,6 +13755,7 @@
lex->interval_list.empty();
lex->type= 0;
lex->vcol_info= 0;
+ lex->option_list= lex->option_list_last= NULL;
}
type /* $11 */
{ /* $12 */
@@ -13880,6 +14006,7 @@
}
;
+
/**
@} (end of group Parser)
*/
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2010-02-01 06:14:12 +0000
+++ b/sql/structs.h 2010-03-26 21:51:17 +0000
@@ -68,6 +68,7 @@
uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;
+class engine_option_value;
typedef struct st_key {
uint key_length; /* Tot length of key */
@@ -101,6 +102,14 @@
int bdb_return_if_eq;
} handler;
struct st_table *table;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
+ /**
+ structure with parsed new field parameters in ALTER TABLE for
+ check_if_incompatible_data()
+ */
+ void *new_option_struct;
} KEY;
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/table.cc 2010-03-26 21:51:17 +0000
@@ -667,12 +667,13 @@
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 extra_rec_buf_length, options_len;
uint i,j;
bool use_hash;
char *keynames, *names, *comment_pos, *vcol_screen_pos;
uchar *record;
- uchar *disk_buff, *strpos, *null_flags, *null_pos;
+ uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+ uchar *buff= 0;
ulong pos, record_offset, *rec_per_key, rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -788,7 +789,6 @@
for (i=0 ; i < keys ; i++, keyinfo++)
{
- keyinfo->table= 0; // Updated in open_frm
if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -858,15 +858,14 @@
if ((n_length= uint4korr(head+55)))
{
/* Read extra data segment */
- uchar *buff, *next_chunk, *buff_end;
+ uchar *next_chunk, *buff_end;
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
goto err;
if (my_pread(file, buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
share->connect_string.length= uint2korr(buff);
if (!(share->connect_string.str= strmake_root(&share->mem_root,
@@ -874,8 +873,7 @@
share->connect_string.
length)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
next_chunk+= share->connect_string.length + 2;
buff_end= buff + n_length;
@@ -895,8 +893,7 @@
plugin_data(tmp_plugin, handlerton *)))
{
/* bad file, legacy_db_type did not match the name */
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
/*
tmp_plugin is locked with a local lock.
@@ -925,8 +922,7 @@
error= 8;
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
@@ -940,8 +936,7 @@
/* purecov: begin inspected */
error= 8;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
/* purecov: end */
}
next_chunk+= str_db_type_length + 2;
@@ -957,16 +952,14 @@
memdup_root(&share->mem_root, next_chunk + 4,
partition_info_len + 1)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
#else
if (partition_info_len)
{
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
#endif
next_chunk+= 5 + partition_info_len;
@@ -992,6 +985,17 @@
#endif
next_chunk++;
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ /*
+ store options position, but skip till the time we will
+ know number of fields
+ */
+ options_len= uint4korr(next_chunk);
+ options= next_chunk + 4;
+ next_chunk+= options_len;
+ options_len-= 4;
+ }
keyinfo= share->key_info;
for (i= 0; i < keys; i++, keyinfo++)
{
@@ -1002,8 +1006,7 @@
{
DBUG_PRINT("error",
("fulltext key uses parser that is not defined in .frm"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
parser_name.str= (char*) next_chunk;
parser_name.length= strlen((char*) next_chunk);
@@ -1013,12 +1016,10 @@
if (! keyinfo->parser)
{
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
}
- my_free(buff, MYF(0));
}
share->key_block_size= uint2korr(head+62);
@@ -1028,21 +1029,21 @@
share->rec_buff_length= rec_buff_length;
if (!(record= (uchar *) alloc_root(&share->mem_root,
rec_buff_length)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->default_values= record;
if (my_pread(file, record, (size_t) share->reclength,
record_offset, MYF(MY_NABP)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file, head,288,MYF(MY_NABP)))
- goto err;
+ goto free_and_err;
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err; // Wrong password
+ goto free_and_err; // Wrong password
}
#endif
@@ -1062,6 +1063,8 @@
share->comment.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*)+
@@ -1070,14 +1073,14 @@
keys+3)*sizeof(char *)+
(n_length+int_length+com_length+
vcol_screen_length)))))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->field= field_ptr;
read_length=(uint) (share->fields * field_pack_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 */
+ goto free_and_err; /* purecov: inspected */
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
@@ -1104,7 +1107,7 @@
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
if (share->fieldnames.count != share->fields)
- goto err;
+ goto free_and_err;
fix_type_pointers(&interval_array, share->intervals, interval_count,
&names);
@@ -1118,7 +1121,7 @@
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
count)))
- goto err;
+ goto free_and_err;
for (count= 0; count < interval->count; count++)
{
char *val= (char*) interval->type_names[count];
@@ -1134,7 +1137,7 @@
/* Allocate handler */
if (!(handler_file= get_new_handler(share, thd->mem_root,
share->db_type())))
- goto err;
+ goto free_and_err;
record= share->default_values-1; /* Fieldstart = 1 */
if (share->null_field_first)
@@ -1196,7 +1199,7 @@
charset= &my_charset_bin;
#else
error= 4; // unsupported field type
- goto err;
+ goto free_and_err;
#endif
}
else
@@ -1207,7 +1210,7 @@
{
error= 5; // Unknown or unavailable charset
errarg= (int) strpos[14];
- goto err;
+ goto free_and_err;
}
}
@@ -1247,7 +1250,7 @@
if ((uint)vcol_screen_pos[0] != 1)
{
error= 4;
- goto err;
+ goto free_and_err;
}
field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
fld_stored_in_db= (bool) (uint) vcol_screen_pos[2];
@@ -1256,7 +1259,7 @@
(char *)memdup_root(&share->mem_root,
vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE,
vcol_expr_length)))
- goto err;
+ goto free_and_err;
vcol_info->expr_str.length= vcol_expr_length;
vcol_screen_pos+= vcol_info_length;
share->vfields++;
@@ -1346,7 +1349,7 @@
if (!reg_field) // Not supported field type
{
error= 4;
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
}
reg_field->field_index= i;
@@ -1385,7 +1388,7 @@
sent (OOM).
*/
error= 8;
- goto err;
+ goto free_and_err;
}
}
if (!reg_field->stored_in_db)
@@ -1462,7 +1465,7 @@
if (!key_part->fieldnr)
{
error= 4; // Wrong file
- goto err;
+ goto free_and_err;
}
field= key_part->field= share->field[key_part->fieldnr-1];
key_part->type= field->key_type();
@@ -1627,6 +1630,15 @@
null_length, 255);
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ DBUG_ASSERT(options_len);
+ if (engine_table_options_frm_read(options, options_len, share) ||
+ parse_engine_table_options(thd, handler_file->ht, share))
+ goto free_and_err;
+ }
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
if (share->found_next_number_field)
{
reg_field= *share->found_next_number_field;
@@ -1685,6 +1697,8 @@
#endif
DBUG_RETURN (0);
+ free_and_err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
err:
share->error= error;
share->open_errno= my_errno;
@@ -2883,6 +2897,7 @@
ulong length;
uchar fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
+ DBUG_ENTER("create_frm");
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2964,7 +2979,7 @@
{
VOID(my_close(file,MYF(0)));
VOID(my_delete(name,MYF(0)));
- return(-1);
+ DBUG_RETURN(-1);
}
}
}
@@ -2975,7 +2990,7 @@
else
my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
}
- return (file);
+ DBUG_RETURN(file);
} /* create_frm */
@@ -2993,7 +3008,7 @@
create_info->table_charset= 0;
create_info->comment= share->comment;
create_info->transactional= share->transactional;
- create_info->page_checksum= share->page_checksum;
+ create_info->option_list= share->option_list;
DBUG_VOID_RETURN;
}
=== modified file 'sql/table.h'
--- a/sql/table.h 2010-02-12 08:47:31 +0000
+++ b/sql/table.h 2010-03-26 21:51:17 +0000
@@ -340,6 +340,8 @@
#ifdef NOT_YET
struct st_table *open_tables; /* link to open tables */
#endif
+ engine_option_value *option_list; /* text options for table */
+ void *option_struct; /* structure with parsed options */
/* The following is copied to each TABLE on OPEN */
Field **field;
=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc 2010-01-04 17:54:42 +0000
+++ b/sql/unireg.cc 2010-03-26 21:51:17 +0000
@@ -46,6 +46,13 @@
uint reclength, ulong data_offset,
handler *handler);
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
/**
An interceptor to hijack ER_TOO_MANY_FIELDS error from
pack_screens and retry again without UNIREG screens.
@@ -75,6 +82,7 @@
return is_handled;
}
+
/*
Create a frm (table definition) file
@@ -107,6 +115,7 @@
ulong key_buff_length;
File file;
ulong filepos, data_offset;
+ uint options_len= 0;
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
@@ -183,6 +192,17 @@
create_info->extra_size+= key_info[i].parser_name->length + 1;
}
+ {
+ options_len= engine_table_options_frm_length(create_info->option_list,
+ create_fields,
+ keys, key_info);
+ if (options_len)
+ {
+ create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+ create_info->extra_size+= (options_len+= 4);
+ }
+ }
+
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
{
@@ -294,6 +314,25 @@
if (my_write(file, (uchar*) buff, 6, MYF_RW))
goto err;
}
+
+ if (options_len)
+ {
+ uchar *optbuff= (uchar *)my_malloc(options_len, MYF(0));
+ my_bool error;
+ DBUG_PRINT("info", ("Create options length: %u", options_len));
+ if (!optbuff)
+ goto err;
+ int4store(optbuff, options_len);
+ engine_table_options_frm_image(optbuff + 4,
+ create_info->option_list,
+ create_fields,
+ keys, key_info);
+ error= my_write(file, optbuff, options_len, MYF_RW);
+ my_free(optbuff, MYF(0));
+ if (error)
+ goto err;
+ }
+
for (i= 0; i < keys; i++)
{
if (key_info[i].parser_name)
=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc 2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc 2010-03-26 21:51:17 +0000
@@ -62,7 +62,7 @@
ha_example::rnd_next
ha_example::rnd_next
ha_example::rnd_next
- ha_example::rnd_next
+ ha_example::rnd_nex/t
ha_example::rnd_next
ha_example::rnd_next
ha_example::rnd_next
@@ -113,6 +113,55 @@
/* The mutex used to init the hash; variable for example share methods */
pthread_mutex_t example_mutex;
+
+/**
+ structure for CREATE TABLE options (table options)
+*/
+
+struct example_table_options_struct
+{
+ const char *strparam;
+ ulonglong ullparam;
+ uint enumparam;
+ uint boolparam;
+};
+
+
+/**
+ structure for CREATE TABLE options (table options)
+*/
+
+struct example_field_options_struct
+{
+ const char *compex_param_to_parse_it_in_engine;
+};
+
+#define ha_table_option_struct example_table_options_struct
+ha_create_table_option example_table_option_list[]=
+{
+ HA_TOPTION_ULL("UUL", ullparam, UINT_MAX32, 0, UINT_MAX32, 1),
+ HA_TOPTION_STRING("STR", strparam),
+ HA_TOPTION_ENUM("one_or_two", enumparam, "one,two", 0),
+ HA_TOPTION_BOOL("YESNO", boolparam, 1),
+ HA_TOPTION_END
+};
+
+#define ha_field_option_struct example_field_options_struct
+ha_create_table_option example_field_option_list[]=
+{
+ HA_FOPTION_STRING("COMPLEX", compex_param_to_parse_it_in_engine),
+ HA_FOPTION_END
+};
+
+
+ha_create_table_option_rules example_table_option_list_rules=
+{
+ example_table_option_list,
+ example_field_option_list,
+ NULL
+};
+
+
/**
@brief
Function we use in the creation of our hash to get key.
@@ -138,6 +187,7 @@
example_hton->state= SHOW_OPTION_YES;
example_hton->create= example_create_handler;
example_hton->flags= HTON_CAN_RECREATE;
+ example_hton->table_options_rules= &example_table_option_list_rules;
DBUG_RETURN(0);
}
@@ -789,7 +839,7 @@
int ha_example::rename_table(const char * from, const char * to)
{
DBUG_ENTER("ha_example::rename_table ");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ DBUG_RETURN(0);
}
@@ -836,14 +886,85 @@
int ha_example::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
+ example_table_options_struct *prm=
+ (example_table_options_struct *)table_arg->s->option_struct;
DBUG_ENTER("ha_example::create");
/*
This is not implemented but we want someone to be able to see that it
works.
*/
+
+ DBUG_ASSERT(prm);
+ DBUG_PRINT("info", ("strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prm->strparam ? prm->strparam : "<NULL>"),
+ prm->ullparam, prm->enumparam, prm->boolparam));
+ for (Field **field= table_arg->s->field; *field; field++)
+ {
+ example_field_options_struct *fprm=
+ (example_field_options_struct *)(*field)->option_struct;
+ DBUG_ASSERT(fprm);
+ DBUG_PRINT("info", ("field: %s complex: '%-.64s'",
+ (*field)->field_name,
+ (fprm->compex_param_to_parse_it_in_engine ?
+ fprm->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+
+ }
+
DBUG_RETURN(0);
}
+bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes)
+{
+ example_table_options_struct *prm;
+ DBUG_ENTER("ha_example::check_if_incompatible_data");
+ DBUG_ASSERT(info->option_struct);
+ DBUG_ASSERT(info->old_option_struct);
+ DBUG_ASSERT(info->old_option_struct);
+ prm= (example_table_options_struct *)info->option_struct;
+ DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prm->strparam ? prm->strparam : "<NULL>"),
+ prm->ullparam, prm->enumparam, prm->boolparam));
+
+ prm= (example_table_options_struct *)info->old_option_struct;
+ DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (prm->strparam ? prm->strparam : "<NULL>"),
+ prm->ullparam, prm->enumparam, prm->boolparam));
+
+ for (Field **field= info->old_field; *field; field++)
+ {
+ example_field_options_struct *fprm;
+ if ((*field)->new_option_struct)
+ {
+ fprm=
+ (example_field_options_struct *)(*field)->new_option_struct;
+ DBUG_PRINT("info", ("new field: %s complex: '%-.64s'",
+ (*field)->field_name,
+ (fprm->compex_param_to_parse_it_in_engine ?
+ fprm->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ }
+ else
+ DBUG_PRINT("info", ("new field %s is the same", (*field)->field_name));
+
+ fprm=
+ (example_field_options_struct *)(*field)->option_struct;
+ DBUG_ASSERT(fprm);
+ DBUG_PRINT("info", ("old field: %s complex: '%-.64s'",
+ (*field)->field_name,
+ (fprm->compex_param_to_parse_it_in_engine ?
+ fprm->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ }
+
+ DBUG_RETURN(COMPATIBLE_DATA_YES);
+}
+
+
struct st_mysql_storage_engine example_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
=== modified file 'storage/example/ha_example.h'
--- a/storage/example/ha_example.h 2007-08-13 13:11:25 +0000
+++ b/storage/example/ha_example.h 2010-03-26 21:51:17 +0000
@@ -245,6 +245,8 @@
int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required
+ bool check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required
=== modified file 'storage/pbxt/src/discover_xt.cc'
--- a/storage/pbxt/src/discover_xt.cc 2010-02-01 06:14:12 +0000
+++ b/storage/pbxt/src/discover_xt.cc 2010-03-26 21:51:17 +0000
@@ -1623,7 +1623,7 @@
#endif
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/,
- NULL /*vcol_info*/))
+ NULL /*vcol_info*/, NULL /* create options */))
#endif
goto error;
2
1

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2840: Fixed wrong regexps
by noreply@launchpad.net 01 Apr '10
by noreply@launchpad.net 01 Apr '10
01 Apr '10
------------------------------------------------------------
revno: 2840
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Thu 2010-04-01 12:40:11 +0300
message:
Fixed wrong regexps
modified:
support-files/compiler_warnings.supp
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2840)
by Michael Widenius 01 Apr '10
by Michael Widenius 01 Apr '10
01 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100401090842-f0oddzva8k49zwsy
2840 Michael Widenius 2010-04-01
Fixed wrong regexps
modified:
support-files/compiler_warnings.supp
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-04-01 09:08:42 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-01 09:40:11 +0000
@@ -27,7 +27,7 @@ pars0grm.tab.c: .*'yyerrorlab' : unrefer
_flex_tmp.c: .*not enough actual parameters for macro 'yywrap'.*
pars0lex.l: .*conversion from 'ulint' to 'int', possible loss of data.*
btr/btr0cur\.c: .*value computed is not used.*: 3175-3375
-include/buf0buf\.ic: unused parameter ���mtr���
+include/buf0buf\.ic: unused parameter .*mtr.*
fil/fil0fil\.c: pointer targets in passing argument.*differ in signedness
fil/fil0fil\.c: comparison between signed and unsigned : 3100-3199
fil/fil0fil\.c: unused parameter
@@ -58,7 +58,7 @@ readline\.c : unused parameter
term\.c : unused parameter
vi\.c : unused parameter
common\.c : unused parameter
-term\.c : *.*
+term\.c : .*
#
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2839: Added missing space before :, which caused failuers in buildbot
by noreply@launchpad.net 01 Apr '10
by noreply@launchpad.net 01 Apr '10
01 Apr '10
------------------------------------------------------------
revno: 2839
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Thu 2010-04-01 12:08:42 +0300
message:
Added missing space before :, which caused failuers in buildbot
modified:
support-files/compiler_warnings.supp
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2764)
by Michael Widenius 01 Apr '10
by Michael Widenius 01 Apr '10
01 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100401090935-b2yfd23r67e7sl42
2764 Michael Widenius 2010-04-01 [merge]
Auto merge with 5.1
modified:
support-files/compiler_warnings.supp
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-03-31 19:12:21 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-01 09:08:42 +0000
@@ -160,4 +160,4 @@ ctype-simple\.c : .*unary minus operator
# Wrong warning due to GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29478
regexec\.c : passing argument 3 of.*matcher.* discards qualifiers from pointer target type
libmysql\.c: passing argument 2 of .*memcpy.* discards qualifiers from pointer target type : 3000-4000
-storage/xtradb/dict/dict0dict\.c: passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500
+storage/xtradb/dict/dict0dict\.c : passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2763)
by Michael Widenius 01 Apr '10
by Michael Widenius 01 Apr '10
01 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100401090426-sldnxikmb2x1og23
2763 Michael Widenius 2010-04-01 [merge]
Auto merge with 5.1
modified:
mysys/my_gethostbyname.c
storage/xtradb/handler/i_s.cc
storage/xtradb/log/log0recv.c
=== modified file 'mysys/my_gethostbyname.c'
--- a/mysys/my_gethostbyname.c 2010-03-30 12:36:49 +0000
+++ b/mysys/my_gethostbyname.c 2010-03-31 20:50:54 +0000
@@ -95,7 +95,7 @@ struct hostent *
my_gethostbyname_r(const char *name,
struct hostent *result __attribute__((unused)),
char *buffer __attribute__((unused)),
- int buflen__attribute__((unused)),
+ int buflen __attribute__((unused)),
int *h_errnop)
{
struct hostent *hp;
=== modified file 'storage/xtradb/handler/i_s.cc'
--- a/storage/xtradb/handler/i_s.cc 2010-01-28 11:35:10 +0000
+++ b/storage/xtradb/handler/i_s.cc 2010-03-31 20:50:54 +0000
@@ -2988,7 +2988,6 @@ i_s_innodb_admin_command_fill(
COND* cond)
{
TABLE* i_s_table = (TABLE *) tables->table;
- CHARSET_INFO *cs= system_charset_info;
char** query_str;
char* ptr;
char quote = '\0';
=== modified file 'storage/xtradb/log/log0recv.c'
--- a/storage/xtradb/log/log0recv.c 2010-01-15 15:58:25 +0000
+++ b/storage/xtradb/log/log0recv.c 2010-03-31 20:50:54 +0000
@@ -3280,7 +3280,6 @@ recv_recovery_from_checkpoint_finish(voi
#endif /* UNIV_DEBUG */
if (recv_needed_recovery && srv_recovery_stats) {
- FILE* file = stderr;
ulint i;
fprintf(stderr,
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2839)
by Michael Widenius 01 Apr '10
by Michael Widenius 01 Apr '10
01 Apr '10
#At lp:maria based on revid:monty@askmonty.org-20100331205054-jj7383wd8gcw7mzi
2839 Michael Widenius 2010-04-01
Added missing space before :, which caused failuers in buildbot
modified:
support-files/compiler_warnings.supp
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-03-31 19:12:21 +0000
+++ b/support-files/compiler_warnings.supp 2010-04-01 09:08:42 +0000
@@ -160,4 +160,4 @@ ctype-simple\.c : .*unary minus operator
# Wrong warning due to GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29478
regexec\.c : passing argument 3 of.*matcher.* discards qualifiers from pointer target type
libmysql\.c: passing argument 2 of .*memcpy.* discards qualifiers from pointer target type : 3000-4000
-storage/xtradb/dict/dict0dict\.c: passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500
+storage/xtradb/dict/dict0dict\.c : passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2762)
by Michael Widenius 01 Apr '10
by Michael Widenius 01 Apr '10
01 Apr '10
#At lp:maria/5.2 based on revid:monty@askmonty.org-20100331183745-0bpzimnis0s9hnai
2762 Michael Widenius 2010-04-01 [merge]
Merge with 5.1
Fixed valgrind warnings found from running main.connect under valgrind
added:
mysql-test/suite/pbxt/r/pbxt_xa.result
mysql-test/suite/pbxt/t/pbxt_xa.test
mysql-test/suite/pbxt/t/suite.opt
modified:
BUILD/compile-solaris-sparc
cmd-line-utils/libedit/filecomplete.c
extra/comp_err.c
extra/libevent/kqueue.c
include/sql_common.h
mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test
mysql-test/include/default_mysqld.cnf
mysql-test/lib/My/SafeProcess/safe_process.cc
mysql-test/lib/mtr_cases.pm
mysql-test/lib/v1/mysql-test-run.pl
mysql-test/suite/parts/t/rpl_partition.test
mysql-test/suite/rpl/r/rpl_do_grant.result
mysql-test/suite/rpl/r/rpl_optimize.result
mysql-test/suite/rpl/t/rpl_do_grant.test
mysql-test/suite/rpl/t/rpl_name_const.test
mysql-test/suite/rpl/t/rpl_optimize.test
mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
mysql-test/suite/rpl/t/rpl_row_trig003.test
mysql-test/t/bug47671-master.opt
mysql-test/t/ctype_latin1_de-master.opt
mysql-test/t/ctype_ucs2_def-master.opt
mysys/mf_keycache.c
mysys/my_gethostbyname.c
sql-common/client.c
sql/handler.cc
sql/item.cc
sql/item.h
sql/item_cmpfunc.cc
sql/item_create.cc
sql/item_create.h
sql/item_sum.cc
sql/item_sum.h
sql/log.cc
sql/mysqld.cc
sql/net_serv.cc
sql/set_var.cc
sql/sp_head.cc
sql/sql_acl.cc
sql/sql_class.h
sql/sql_table.cc
sql/sql_view.cc
sql/sql_yacc.yy
storage/example/ha_example.h
storage/maria/ma_loghandler.c
storage/maria/ma_search.c
storage/maria/maria_def.h
storage/myisam/ft_stopwords.c
storage/myisammrg/ha_myisammrg.cc
storage/myisammrg/myrg_open.c
storage/xtradb/include/page0page.h
storage/xtradb/include/page0page.ic
storage/xtradb/include/ut0lst.h
strings/ctype-ucs2.c
strings/ctype-utf8.c
strings/my_vsnprintf.c
support-files/compiler_warnings.supp
unittest/mysys/waiting_threads-t.c
per-file messages:
sql/sp_head.cc
Ensure that vcol_info is reset
sql/sql_acl.cc
Fixed usage of wrong memroot for password
sql/sql_yacc.yy
Ensure that vcol_info is reset
=== modified file 'BUILD/compile-solaris-sparc'
--- a/BUILD/compile-solaris-sparc 2008-09-30 20:57:48 +0000
+++ b/BUILD/compile-solaris-sparc 2010-03-31 19:12:21 +0000
@@ -9,6 +9,6 @@ PATH=$PATH:/usr/ccs/bin:/usr/local/bin
path=`dirname $0`
. "$path/autorun.sh"
-CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" LIBS="-lmtmalloc" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa $EXTRA_FLAGS $EXTRA_CFLAGS" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g $EXTRA_FLAGS $EXTRA_CXXFLAGS" LIBS="-lmtmalloc" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
make -j 4
=== modified file 'cmd-line-utils/libedit/filecomplete.c'
--- a/cmd-line-utils/libedit/filecomplete.c 2009-04-30 11:53:30 +0000
+++ b/cmd-line-utils/libedit/filecomplete.c 2010-03-31 19:12:21 +0000
@@ -95,10 +95,9 @@ static char break_chars[] = { ' ', '\t',
char *
fn_tilde_expand(const char *txt)
{
- struct passwd pwres, *pass;
+ struct passwd *pass;
char *temp;
size_t len = 0;
- char pwbuf[1024];
if (txt[0] != '~')
return (strdup(txt));
=== modified file 'extra/comp_err.c'
--- a/extra/comp_err.c 2009-11-20 10:11:31 +0000
+++ b/extra/comp_err.c 2010-03-30 12:36:49 +0000
@@ -660,7 +660,7 @@ static ha_checksum checksum_format_speci
case 'u':
case 'x':
case 's':
- chksum= my_checksum(chksum, start, (uint) (p + 1 - start));
+ chksum= my_checksum(chksum, (uchar*) start, (uint) (p + 1 - start));
start= 0; /* Not in format specifier anymore */
break;
=== modified file 'extra/libevent/kqueue.c'
--- a/extra/libevent/kqueue.c 2009-03-12 22:27:35 +0000
+++ b/extra/libevent/kqueue.c 2010-03-30 12:36:49 +0000
@@ -144,7 +144,7 @@ kq_init(struct event_base *base)
*/
if (kevent(kq,
kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
- kqueueop->events[0].ident != -1 ||
+ ((int) kqueueop->events[0].ident) != -1 ||
kqueueop->events[0].flags != EV_ERROR) {
event_warn("%s: detected broken kqueue; not using.", __func__);
free(kqueueop->changes);
=== modified file 'include/sql_common.h'
--- a/include/sql_common.h 2010-03-29 15:13:53 +0000
+++ b/include/sql_common.h 2010-04-01 09:04:26 +0000
@@ -96,7 +96,7 @@ void set_mysql_extended_error(MYSQL *mys
struct st_plugin_vio_info;
void mpvio_info(Vio *vio, struct st_plugin_vio_info *info);
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
- char *data_plugin, const char *db);
+ const char *data_plugin, const char *db);
int mysql_client_plugin_init();
void mysql_client_plugin_deinit();
struct st_mysql_client_plugin;
=== modified file 'mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test'
--- a/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test 2010-01-22 09:38:21 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_tmp_table_and_DDL.test 2010-03-28 18:10:00 +0000
@@ -157,3 +157,4 @@ INSERT INTO t1 VALUES (1);
DROP TEMPORARY TABLE t1;
+--sync_slave_with_master
=== modified file 'mysql-test/include/default_mysqld.cnf'
--- a/mysql-test/include/default_mysqld.cnf 2008-04-08 14:51:26 +0000
+++ b/mysql-test/include/default_mysqld.cnf 2010-03-28 18:10:00 +0000
@@ -2,7 +2,7 @@
[mysqld]
open-files-limit= 1024
local-infile
-default-character-set= latin1
+character-set-server= latin1
# Increase default connect_timeout to avoid intermittent
# disconnects when test servers are put under load see BUG#28359
=== modified file 'mysql-test/lib/My/SafeProcess/safe_process.cc'
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc 2009-07-08 12:31:22 +0000
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc 2010-03-28 18:10:00 +0000
@@ -159,7 +159,7 @@ int main(int argc, char* const argv[] )
signal(SIGCHLD, handle_signal);
signal(SIGABRT, handle_abort);
- sprintf(safe_process_name, "safe_process[%d]", own_pid);
+ sprintf(safe_process_name, "safe_process[%d]", (int) own_pid);
message("Started");
=== modified file 'mysql-test/lib/mtr_cases.pm'
--- a/mysql-test/lib/mtr_cases.pm 2010-01-15 15:27:55 +0000
+++ b/mysql-test/lib/mtr_cases.pm 2010-03-30 12:36:49 +0000
@@ -681,6 +681,8 @@ sub optimize_cases {
if ( $default_engine =~ /^ndb/i );
$tinfo->{'innodb_test'}= 1
if ( $default_engine =~ /^innodb/i );
+ $tinfo->{'pbxt_test'}= 1
+ if ( $default_engine =~ /^pbxt/i );
}
}
@@ -778,6 +780,8 @@ sub collect_one_test_case {
my $disabled= shift;
my $suite_opts= shift;
+ my $local_default_storage_engine= $default_storage_engine;
+
#print "collect_one_test_case\n";
#print " suitedir: $suitedir\n";
#print " testdir: $testdir\n";
@@ -932,15 +936,26 @@ sub collect_one_test_case {
tags_from_test_file($tinfo,"$testdir/${tname}.test");
- if ( defined $default_storage_engine )
+ # Get default storage engine from suite.opt file
+
+ if (defined $suite_opts &&
+ "@$suite_opts" =~ "default-storage-engine=\s*([^\s]*)")
+ {
+ $local_default_storage_engine= $1;
+ }
+
+ if ( defined $local_default_storage_engine )
{
# Different default engine is used
# tag test to require that engine
$tinfo->{'ndb_test'}= 1
- if ( $default_storage_engine =~ /^ndb/i );
+ if ( $local_default_storage_engine =~ /^ndb/i );
$tinfo->{'innodb_test'}= 1
- if ( $default_storage_engine =~ /^innodb/i );
+ if ( $local_default_storage_engine =~ /^innodb/i );
+
+ $tinfo->{'pbxt_test'}= 1
+ if ( $local_default_storage_engine =~ /^pbxt/i );
}
@@ -1103,6 +1118,28 @@ sub collect_one_test_case {
$tinfo->{template_path}= $config;
}
+ if ( $tinfo->{'pbxt_test'} )
+ {
+ # This is a test that needs pbxt
+ if ( $::mysqld_variables{'pbxt'} eq "OFF" ||
+ ! exists $::mysqld_variables{'pbxt'} )
+ {
+ # Engine is not supported, skip it
+ $tinfo->{'skip'}= 1;
+ return $tinfo;
+ }
+ }
+ else
+ {
+ # Only disable engine if it's on by default (to avoid warnings about
+ # not existing loose options
+ if ( $::mysqld_variables{'pbxt'} eq "ON")
+ {
+ push(@{$tinfo->{'master_opt'}}, "--loose-skip-pbxt");
+ push(@{$tinfo->{'slave_opt'}}, "--loose-skip-pbxt");
+ }
+ }
+
if ( $tinfo->{'example_plugin_test'} )
{
if ( !$ENV{'EXAMPLE_PLUGIN'} )
@@ -1156,6 +1193,7 @@ my @tags=
["include/have_log_bin.inc", "need_binlog", 1],
["include/have_innodb.inc", "innodb_test", 1],
+ ["include/have_pbxt.inc", "pbxt_test", 1],
["include/big_test.inc", "big_test", 1],
["include/have_debug.inc", "need_debug", 1],
["include/have_ndb.inc", "ndb_test", 1],
=== modified file 'mysql-test/lib/v1/mysql-test-run.pl'
--- a/mysql-test/lib/v1/mysql-test-run.pl 2010-03-04 08:03:07 +0000
+++ b/mysql-test/lib/v1/mysql-test-run.pl 2010-03-28 18:10:00 +0000
@@ -3965,7 +3965,7 @@ sub mysqld_arguments ($$$$) {
}
}
- mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
+ mtr_add_arg($args, "%s--character-set-server-set=latin1", $prefix);
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
=== modified file 'mysql-test/suite/parts/t/rpl_partition.test'
--- a/mysql-test/suite/parts/t/rpl_partition.test 2009-02-01 12:00:48 +0000
+++ b/mysql-test/suite/parts/t/rpl_partition.test 2010-03-29 19:07:45 +0000
@@ -1,6 +1,7 @@
--source include/have_partition.inc
--source include/have_innodb.inc
--source include/master-slave.inc
+--source include/big_test.inc
--vertical_results
=== added file 'mysql-test/suite/pbxt/r/pbxt_xa.result'
--- a/mysql-test/suite/pbxt/r/pbxt_xa.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/r/pbxt_xa.result 2010-03-24 22:12:39 +0000
@@ -0,0 +1,18 @@
+drop table if exists t1, t2;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
+CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=pbxt;
+BEGIN;
+SELECT @@log_bin;
+@@log_bin
+0
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+COMMIT;
+select * from t1;
+a
+1
+select * from t2;
+b
+2
+drop table t1, t2;
+drop database pbxt;
=== added file 'mysql-test/suite/pbxt/t/pbxt_xa.test'
--- a/mysql-test/suite/pbxt/t/pbxt_xa.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/pbxt_xa.test 2010-03-24 22:12:39 +0000
@@ -0,0 +1,23 @@
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+#
+# bug lp:544173, xa crash with two 2pc-capable storage engines without binlog
+#
+
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
+CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=pbxt;
+BEGIN;
+# verify that binlog is off
+SELECT @@log_bin;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+COMMIT;
+select * from t1;
+select * from t2;
+drop table t1, t2;
+drop database pbxt;
+
=== added file 'mysql-test/suite/pbxt/t/suite.opt'
--- a/mysql-test/suite/pbxt/t/suite.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/t/suite.opt 2010-03-30 12:36:49 +0000
@@ -0,0 +1 @@
+--default-storage-engine=pbxt
=== modified file 'mysql-test/suite/rpl/r/rpl_do_grant.result'
--- a/mysql-test/suite/rpl/r/rpl_do_grant.result 2010-03-16 12:38:35 +0000
+++ b/mysql-test/suite/rpl/r/rpl_do_grant.result 2010-04-01 09:04:26 +0000
@@ -165,10 +165,9 @@ USE test;
DROP FUNCTION bug42217_db.upgrade_del_func;
DROP FUNCTION bug42217_db.upgrade_alter_func;
DROP DATABASE bug42217_db;
-DROP USER 'create_rout_db'@'localhost';
-call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
-USE mtr;
call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
+stop slave;
+DROP USER 'create_rout_db'@'localhost';
######## BUG#49119 #######
### i) test case from the 'how to repeat section'
stop slave;
=== modified file 'mysql-test/suite/rpl/r/rpl_optimize.result'
--- a/mysql-test/suite/rpl/r/rpl_optimize.result 2010-01-13 09:00:03 +0000
+++ b/mysql-test/suite/rpl/r/rpl_optimize.result 2010-03-31 19:12:21 +0000
@@ -4,6 +4,7 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+drop tables if exists t1;
CALL mtr.add_suppression('Statement may not be safe to log in statement format.');
create table t1 (a int not null auto_increment primary key, b int, key(b));
INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
=== modified file 'mysql-test/suite/rpl/t/rpl_do_grant.test'
--- a/mysql-test/suite/rpl/t/rpl_do_grant.test 2010-03-16 12:38:35 +0000
+++ b/mysql-test/suite/rpl/t/rpl_do_grant.test 2010-04-01 09:04:26 +0000
@@ -209,12 +209,18 @@ USE test;
DROP FUNCTION bug42217_db.upgrade_del_func;
DROP FUNCTION bug42217_db.upgrade_alter_func;
DROP DATABASE bug42217_db;
-DROP USER 'create_rout_db'@'localhost';
call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
+
+sync_slave_with_master;
+
+# Drop the user that was already dropped on the slave
connection slave;
-USE mtr;
-call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396");
+--disable_warnings
+stop slave;
+connection master;
+DROP USER 'create_rout_db'@'localhost';
+--enable_warnings
# BUG#49119: Master crashes when executing 'REVOKE ... ON
# {PROCEDURE|FUNCTION} FROM ...'
=== modified file 'mysql-test/suite/rpl/t/rpl_name_const.test'
--- a/mysql-test/suite/rpl/t/rpl_name_const.test 2009-04-08 23:42:51 +0000
+++ b/mysql-test/suite/rpl/t/rpl_name_const.test 2010-03-28 18:10:00 +0000
@@ -45,3 +45,4 @@ select * from t1 order by id;
connection master;
drop table t1;
drop procedure test_procedure;
+--sync_slave_with_master
=== modified file 'mysql-test/suite/rpl/t/rpl_optimize.test'
--- a/mysql-test/suite/rpl/t/rpl_optimize.test 2010-03-04 08:03:07 +0000
+++ b/mysql-test/suite/rpl/t/rpl_optimize.test 2010-03-31 19:12:21 +0000
@@ -15,6 +15,10 @@
-- source include/not_staging.inc
-- source include/master-slave.inc
+--disable_warnings
+drop tables if exists t1;
+--enable_warnings
+
CALL mtr.add_suppression('Statement may not be safe to log in statement format.');
create table t1 (a int not null auto_increment primary key, b int, key(b));
@@ -51,10 +55,9 @@ sync_with_master; # won't work if slave
connection master; # cleanup
drop table t1;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
# If the machine is so fast that slave syncs before OPTIMIZE
-# starts, this test wil demonstrate nothing but will pass.
+# starts, this test will demonstrate nothing but will pass.
# End of 4.1 tests
=== modified file 'mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test'
--- a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test 2007-12-12 10:14:59 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test 2010-03-28 18:10:00 +0000
@@ -53,6 +53,7 @@ UPDATE t1 SET a=99 WHERE a = 0;
SHOW BINLOG EVENTS;
DROP TABLE t1;
+--sync_slave_with_master
# BUG#17620: Replicate (Row Based) Fails when Query Cache enabled on
# slave
=== modified file 'mysql-test/suite/rpl/t/rpl_row_trig003.test'
--- a/mysql-test/suite/rpl/t/rpl_row_trig003.test 2007-12-06 15:27:10 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_trig003.test 2010-03-29 19:07:45 +0000
@@ -149,6 +149,8 @@ DROP TABLE IF EXISTS test.t2;
DROP TABLE IF EXISTS test.t3;
--enable_warnings
+sync_slave_with_master;
+
diff_files $MYSQLTEST_VARDIR/tmp/trg003_master.sql $MYSQLTEST_VARDIR/tmp/trg003_slave.sql;
# End of 5.0 test case
=== modified file 'mysql-test/t/bug47671-master.opt'
--- a/mysql-test/t/bug47671-master.opt 2009-11-25 06:55:49 +0000
+++ b/mysql-test/t/bug47671-master.opt 2010-03-28 18:10:00 +0000
@@ -1 +1 @@
---default-character-set=utf8 --skip-character-set-client-handshake
+--character-set-server=utf8 --skip-character-set-client-handshake
=== modified file 'mysql-test/t/ctype_latin1_de-master.opt'
--- a/mysql-test/t/ctype_latin1_de-master.opt 2003-05-21 23:57:27 +0000
+++ b/mysql-test/t/ctype_latin1_de-master.opt 2010-03-28 18:10:00 +0000
@@ -1 +1 @@
---default-character-set=latin1 --default-collation=latin1_german2_ci
+--character-set-server=latin1 --default-collation=latin1_german2_ci
=== modified file 'mysql-test/t/ctype_ucs2_def-master.opt'
--- a/mysql-test/t/ctype_ucs2_def-master.opt 2007-02-19 11:04:38 +0000
+++ b/mysql-test/t/ctype_ucs2_def-master.opt 2010-03-28 18:10:00 +0000
@@ -1 +1 @@
---default-collation=ucs2_unicode_ci --default-character-set=ucs2,latin1
+--default-collation=ucs2_unicode_ci --character-set-server=ucs2,latin1
=== modified file 'mysys/mf_keycache.c'
--- a/mysys/mf_keycache.c 2009-12-03 11:19:05 +0000
+++ b/mysys/mf_keycache.c 2010-03-30 12:36:49 +0000
@@ -3924,6 +3924,12 @@ restart:
uint next_status;
uint hash_requests;
+ LINT_INIT(next_hash_link);
+ LINT_INIT(next_diskpos);
+ LINT_INIT(next_file);
+ LINT_INIT(next_status);
+ LINT_INIT(hash_requests);
+
total_found++;
found++;
KEYCACHE_DBUG_ASSERT(found <= keycache->blocks_used);
=== modified file 'mysys/my_gethostbyname.c'
--- a/mysys/my_gethostbyname.c 2006-12-31 00:32:21 +0000
+++ b/mysys/my_gethostbyname.c 2010-03-30 12:36:49 +0000
@@ -91,9 +91,12 @@ extern pthread_mutex_t LOCK_gethostbynam
is finished with the structure.
*/
-struct hostent *my_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- int buflen, int *h_errnop)
+struct hostent *
+my_gethostbyname_r(const char *name,
+ struct hostent *result __attribute__((unused)),
+ char *buffer __attribute__((unused)),
+ int buflen__attribute__((unused)),
+ int *h_errnop)
{
struct hostent *hp;
pthread_mutex_lock(&LOCK_gethostbyname_r);
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2010-03-29 15:13:53 +0000
+++ b/sql-common/client.c 2010-04-01 09:04:26 +0000
@@ -2394,7 +2394,7 @@ static void client_mpvio_info(MYSQL_PLUG
*/
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
- char *data_plugin, const char *db)
+ const char *data_plugin, const char *db)
{
const char *auth_plugin_name;
auth_plugin_t *auth_plugin;
@@ -2540,7 +2540,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
char buff[NAME_LEN+USERNAME_LENGTH+100];
int scramble_data_len, pkt_scramble_len;
char *end, *host_info=0, *server_version_end, *pkt_end;
- char *scramble_data, *scramble_plugin;
+ char *scramble_data;
+ const char *scramble_plugin;
my_socket sock;
in_addr_t ip_addr;
struct sockaddr_in sock_addr;
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-03-25 13:33:39 +0000
+++ b/sql/handler.cc 2010-04-01 09:04:26 +0000
@@ -4252,7 +4252,7 @@ int handler::read_multi_range_first(KEY_
*/
int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
{
- int result;
+ int result= 0;
DBUG_ENTER("handler::read_multi_range_next");
/* We should not be called after the last call returned EOF. */
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2010-03-15 11:51:23 +0000
+++ b/sql/item.cc 2010-04-01 09:04:26 +0000
@@ -7040,7 +7040,7 @@ bool Item_cache_int::cache_value()
}
-void Item_cache_int::store(Item *item, longlong val_arg)
+void Item_cache_int::store_longlong(Item *item, longlong val_arg)
{
/* An explicit values is given, save it. */
value_cached= TRUE;
=== modified file 'sql/item.h'
--- a/sql/item.h 2010-03-15 11:51:23 +0000
+++ b/sql/item.h 2010-04-01 09:04:26 +0000
@@ -1132,7 +1132,8 @@ class Field_enumerator
{
public:
virtual void visit_field(Field *field)= 0;
- virtual ~Field_enumerator() {}; /* purecov: inspected */
+ virtual ~Field_enumerator() {}; /* purecov: inspected */
+ Field_enumerator() {} /* Remove gcc warning */
};
@@ -3148,7 +3149,7 @@ public:
Item_cache_int(enum_field_types field_type_arg):
Item_cache(field_type_arg), value(0) {}
- void store(Item *item, longlong val_arg);
+ void store_longlong(Item *item, longlong val_arg);
double val_real();
longlong val_int();
String* val_str(String *str);
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2010-03-04 08:03:07 +0000
+++ b/sql/item_cmpfunc.cc 2010-03-28 18:10:00 +0000
@@ -879,7 +879,7 @@ get_time_value(THD *thd, Item ***item_ar
Item_cache_int *cache= new Item_cache_int();
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
- cache->store(item, value);
+ cache->store_longlong(item, value);
*cache_arg= cache;
*item_arg= cache_arg;
}
@@ -917,13 +917,13 @@ int Arg_comparator::set_cmp_func(Item_re
cache->set_used_tables(1);
if (!(*a)->is_datetime())
{
- cache->store((*a), const_value);
+ cache->store_longlong((*a), const_value);
a_cache= cache;
a= (Item **)&a_cache;
}
else
{
- cache->store((*b), const_value);
+ cache->store_longlong((*b), const_value);
b_cache= cache;
b= (Item **)&b_cache;
}
@@ -1145,7 +1145,7 @@ get_datetime_value(THD *thd, Item ***ite
Item_cache_int *cache= new Item_cache_int(MYSQL_TYPE_DATETIME);
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
- cache->store(item, value);
+ cache->store_longlong(item, value);
*cache_arg= cache;
*item_arg= cache_arg;
}
=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc 2010-03-04 08:03:07 +0000
+++ b/sql/item_create.cc 2010-03-29 19:07:45 +0000
@@ -76,7 +76,7 @@ public:
@param thd The current thread
@return An item representing the function call
*/
- virtual Item *create(THD *thd) = 0;
+ virtual Item *create_builder(THD *thd) = 0;
protected:
/** Constructor. */
@@ -101,7 +101,7 @@ public:
@param arg1 The first argument of the function
@return An item representing the function call
*/
- virtual Item *create(THD *thd, Item *arg1) = 0;
+ virtual Item *create_1_arg(THD *thd, Item *arg1) = 0;
protected:
/** Constructor. */
@@ -127,7 +127,7 @@ public:
@param arg2 The second argument of the function
@return An item representing the function call
*/
- virtual Item *create(THD *thd, Item *arg1, Item *arg2) = 0;
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) = 0;
protected:
/** Constructor. */
@@ -154,7 +154,7 @@ public:
@param arg3 The third argument of the function
@return An item representing the function call
*/
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0;
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0;
protected:
/** Constructor. */
@@ -171,8 +171,8 @@ protected:
class Create_sp_func : public Create_qfunc
{
public:
- virtual Item *create(THD *thd, LEX_STRING db, LEX_STRING name,
- bool use_explicit_name, List<Item> *item_list);
+ virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ bool use_explicit_name, List<Item> *item_list);
static Create_sp_func s_singleton;
@@ -217,7 +217,7 @@ protected:
class Create_func_abs : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_abs s_singleton;
@@ -230,7 +230,7 @@ protected:
class Create_func_acos : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_acos s_singleton;
@@ -243,7 +243,7 @@ protected:
class Create_func_addtime : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_addtime s_singleton;
@@ -256,7 +256,7 @@ protected:
class Create_func_aes_encrypt : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_aes_encrypt s_singleton;
@@ -269,7 +269,7 @@ protected:
class Create_func_aes_decrypt : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_aes_decrypt s_singleton;
@@ -283,7 +283,7 @@ protected:
class Create_func_area : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_area s_singleton;
@@ -298,7 +298,7 @@ protected:
class Create_func_as_wkb : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_as_wkb s_singleton;
@@ -313,7 +313,7 @@ protected:
class Create_func_as_wkt : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_as_wkt s_singleton;
@@ -327,7 +327,7 @@ protected:
class Create_func_asin : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_asin s_singleton;
@@ -353,7 +353,7 @@ protected:
class Create_func_benchmark : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_benchmark s_singleton;
@@ -366,7 +366,7 @@ protected:
class Create_func_bin : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_bin s_singleton;
@@ -379,7 +379,7 @@ protected:
class Create_func_bit_count : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_bit_count s_singleton;
@@ -392,7 +392,7 @@ protected:
class Create_func_bit_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_bit_length s_singleton;
@@ -405,7 +405,7 @@ protected:
class Create_func_ceiling : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ceiling s_singleton;
@@ -419,7 +419,7 @@ protected:
class Create_func_centroid : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_centroid s_singleton;
@@ -433,7 +433,7 @@ protected:
class Create_func_char_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_char_length s_singleton;
@@ -446,7 +446,7 @@ protected:
class Create_func_coercibility : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_coercibility s_singleton;
@@ -459,7 +459,7 @@ protected:
class Create_func_compress : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_compress s_singleton;
@@ -498,7 +498,7 @@ protected:
class Create_func_connection_id : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_connection_id s_singleton;
@@ -512,7 +512,7 @@ protected:
class Create_func_contains : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_contains s_singleton;
@@ -526,7 +526,7 @@ protected:
class Create_func_conv : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_conv s_singleton;
@@ -539,7 +539,7 @@ protected:
class Create_func_convert_tz : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_convert_tz s_singleton;
@@ -552,7 +552,7 @@ protected:
class Create_func_cos : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_cos s_singleton;
@@ -565,7 +565,7 @@ protected:
class Create_func_cot : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_cot s_singleton;
@@ -578,7 +578,7 @@ protected:
class Create_func_crc32 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_crc32 s_singleton;
@@ -592,7 +592,7 @@ protected:
class Create_func_crosses : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_crosses s_singleton;
@@ -606,7 +606,7 @@ protected:
class Create_func_date_format : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_date_format s_singleton;
@@ -619,7 +619,7 @@ protected:
class Create_func_datediff : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_datediff s_singleton;
@@ -632,7 +632,7 @@ protected:
class Create_func_dayname : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayname s_singleton;
@@ -645,7 +645,7 @@ protected:
class Create_func_dayofmonth : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayofmonth s_singleton;
@@ -658,7 +658,7 @@ protected:
class Create_func_dayofweek : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayofweek s_singleton;
@@ -671,7 +671,7 @@ protected:
class Create_func_dayofyear : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dayofyear s_singleton;
@@ -684,7 +684,7 @@ protected:
class Create_func_decode : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_decode s_singleton;
@@ -697,7 +697,7 @@ protected:
class Create_func_degrees : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_degrees s_singleton;
@@ -737,7 +737,7 @@ protected:
class Create_func_dimension : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_dimension s_singleton;
@@ -752,7 +752,7 @@ protected:
class Create_func_disjoint : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_disjoint s_singleton;
@@ -779,7 +779,7 @@ protected:
class Create_func_encode : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_encode s_singleton;
@@ -806,7 +806,7 @@ protected:
class Create_func_endpoint : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_endpoint s_singleton;
@@ -821,7 +821,7 @@ protected:
class Create_func_envelope : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_envelope s_singleton;
@@ -836,7 +836,7 @@ protected:
class Create_func_equals : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_equals s_singleton;
@@ -850,7 +850,7 @@ protected:
class Create_func_exp : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_exp s_singleton;
@@ -877,7 +877,7 @@ protected:
class Create_func_exteriorring : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_exteriorring s_singleton;
@@ -904,7 +904,7 @@ protected:
class Create_func_find_in_set : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_find_in_set s_singleton;
@@ -917,7 +917,7 @@ protected:
class Create_func_floor : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_floor s_singleton;
@@ -930,7 +930,7 @@ protected:
class Create_func_format : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_format s_singleton;
@@ -943,7 +943,7 @@ protected:
class Create_func_found_rows : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_found_rows s_singleton;
@@ -956,7 +956,7 @@ protected:
class Create_func_from_days : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_from_days s_singleton;
@@ -1013,7 +1013,7 @@ protected:
class Create_func_geometry_type : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_geometry_type s_singleton;
@@ -1028,7 +1028,7 @@ protected:
class Create_func_geometryn : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_geometryn s_singleton;
@@ -1042,7 +1042,7 @@ protected:
class Create_func_get_lock : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_get_lock s_singleton;
@@ -1056,7 +1056,7 @@ protected:
class Create_func_glength : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_glength s_singleton;
@@ -1083,7 +1083,7 @@ protected:
class Create_func_hex : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_hex s_singleton;
@@ -1096,7 +1096,7 @@ protected:
class Create_func_ifnull : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_ifnull s_singleton;
@@ -1109,7 +1109,7 @@ protected:
class Create_func_inet_ntoa : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_inet_ntoa s_singleton;
@@ -1122,7 +1122,7 @@ protected:
class Create_func_inet_aton : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_inet_aton s_singleton;
@@ -1135,7 +1135,7 @@ protected:
class Create_func_instr : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_instr s_singleton;
@@ -1149,7 +1149,7 @@ protected:
class Create_func_interiorringn : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_interiorringn s_singleton;
@@ -1164,7 +1164,7 @@ protected:
class Create_func_intersects : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_intersects s_singleton;
@@ -1178,7 +1178,7 @@ protected:
class Create_func_is_free_lock : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_is_free_lock s_singleton;
@@ -1191,7 +1191,7 @@ protected:
class Create_func_is_used_lock : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_is_used_lock s_singleton;
@@ -1205,7 +1205,7 @@ protected:
class Create_func_isclosed : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_isclosed s_singleton;
@@ -1220,7 +1220,7 @@ protected:
class Create_func_isempty : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_isempty s_singleton;
@@ -1234,7 +1234,7 @@ protected:
class Create_func_isnull : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_isnull s_singleton;
@@ -1248,7 +1248,7 @@ protected:
class Create_func_issimple : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_issimple s_singleton;
@@ -1262,7 +1262,7 @@ protected:
class Create_func_last_day : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_last_day s_singleton;
@@ -1288,7 +1288,7 @@ protected:
class Create_func_lcase : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_lcase s_singleton;
@@ -1314,7 +1314,7 @@ protected:
class Create_func_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_length s_singleton;
@@ -1327,7 +1327,7 @@ protected:
class Create_func_ln : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ln s_singleton;
@@ -1340,7 +1340,7 @@ protected:
class Create_func_load_file : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_load_file s_singleton;
@@ -1379,7 +1379,7 @@ protected:
class Create_func_log10 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_log10 s_singleton;
@@ -1392,7 +1392,7 @@ protected:
class Create_func_log2 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_log2 s_singleton;
@@ -1405,7 +1405,7 @@ protected:
class Create_func_lpad : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_lpad s_singleton;
@@ -1418,7 +1418,7 @@ protected:
class Create_func_ltrim : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ltrim s_singleton;
@@ -1431,7 +1431,7 @@ protected:
class Create_func_makedate : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_makedate s_singleton;
@@ -1444,7 +1444,7 @@ protected:
class Create_func_maketime : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_maketime s_singleton;
@@ -1483,7 +1483,7 @@ protected:
class Create_func_md5 : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_md5 s_singleton;
@@ -1496,7 +1496,7 @@ protected:
class Create_func_monthname : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_monthname s_singleton;
@@ -1509,7 +1509,7 @@ protected:
class Create_func_name_const : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_name_const s_singleton;
@@ -1522,7 +1522,7 @@ protected:
class Create_func_nullif : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_nullif s_singleton;
@@ -1536,7 +1536,7 @@ protected:
class Create_func_numgeometries : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_numgeometries s_singleton;
@@ -1551,7 +1551,7 @@ protected:
class Create_func_numinteriorring : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_numinteriorring s_singleton;
@@ -1566,7 +1566,7 @@ protected:
class Create_func_numpoints : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_numpoints s_singleton;
@@ -1580,7 +1580,7 @@ protected:
class Create_func_oct : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_oct s_singleton;
@@ -1593,7 +1593,7 @@ protected:
class Create_func_ord : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ord s_singleton;
@@ -1607,7 +1607,7 @@ protected:
class Create_func_overlaps : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_overlaps s_singleton;
@@ -1621,7 +1621,7 @@ protected:
class Create_func_period_add : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_period_add s_singleton;
@@ -1634,7 +1634,7 @@ protected:
class Create_func_period_diff : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_period_diff s_singleton;
@@ -1647,7 +1647,7 @@ protected:
class Create_func_pi : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_pi s_singleton;
@@ -1661,7 +1661,7 @@ protected:
class Create_func_pointn : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_pointn s_singleton;
@@ -1675,7 +1675,7 @@ protected:
class Create_func_pow : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_pow s_singleton;
@@ -1688,7 +1688,7 @@ protected:
class Create_func_quote : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_quote s_singleton;
@@ -1701,7 +1701,7 @@ protected:
class Create_func_radians : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_radians s_singleton;
@@ -1727,7 +1727,7 @@ protected:
class Create_func_release_lock : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_release_lock s_singleton;
@@ -1740,7 +1740,7 @@ protected:
class Create_func_reverse : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_reverse s_singleton;
@@ -1766,7 +1766,7 @@ protected:
class Create_func_row_count : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_row_count s_singleton;
@@ -1779,7 +1779,7 @@ protected:
class Create_func_rpad : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_rpad s_singleton;
@@ -1792,7 +1792,7 @@ protected:
class Create_func_rtrim : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_rtrim s_singleton;
@@ -1805,7 +1805,7 @@ protected:
class Create_func_sec_to_time : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sec_to_time s_singleton;
@@ -1818,7 +1818,7 @@ protected:
class Create_func_sha : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sha s_singleton;
@@ -1831,7 +1831,7 @@ protected:
class Create_func_sign : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sign s_singleton;
@@ -1844,7 +1844,7 @@ protected:
class Create_func_sin : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sin s_singleton;
@@ -1857,7 +1857,7 @@ protected:
class Create_func_sleep : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sleep s_singleton;
@@ -1870,7 +1870,7 @@ protected:
class Create_func_soundex : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_soundex s_singleton;
@@ -1883,7 +1883,7 @@ protected:
class Create_func_space : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_space s_singleton;
@@ -1896,7 +1896,7 @@ protected:
class Create_func_sqrt : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_sqrt s_singleton;
@@ -1910,7 +1910,7 @@ protected:
class Create_func_srid : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_srid s_singleton;
@@ -1925,7 +1925,7 @@ protected:
class Create_func_startpoint : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_startpoint s_singleton;
@@ -1939,7 +1939,7 @@ protected:
class Create_func_str_to_date : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_str_to_date s_singleton;
@@ -1952,7 +1952,7 @@ protected:
class Create_func_strcmp : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_strcmp s_singleton;
@@ -1965,7 +1965,7 @@ protected:
class Create_func_substr_index : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_substr_index s_singleton;
@@ -1978,7 +1978,7 @@ protected:
class Create_func_subtime : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_subtime s_singleton;
@@ -1991,7 +1991,7 @@ protected:
class Create_func_tan : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_tan s_singleton;
@@ -2004,7 +2004,7 @@ protected:
class Create_func_time_format : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_time_format s_singleton;
@@ -2017,7 +2017,7 @@ protected:
class Create_func_time_to_sec : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_time_to_sec s_singleton;
@@ -2030,7 +2030,7 @@ protected:
class Create_func_timediff : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_timediff s_singleton;
@@ -2043,7 +2043,7 @@ protected:
class Create_func_to_days : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_to_days s_singleton;
@@ -2057,7 +2057,7 @@ protected:
class Create_func_touches : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_touches s_singleton;
@@ -2071,7 +2071,7 @@ protected:
class Create_func_ucase : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ucase s_singleton;
@@ -2084,7 +2084,7 @@ protected:
class Create_func_uncompress : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_uncompress s_singleton;
@@ -2097,7 +2097,7 @@ protected:
class Create_func_uncompressed_length : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_uncompressed_length s_singleton;
@@ -2110,7 +2110,7 @@ protected:
class Create_func_unhex : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_unhex s_singleton;
@@ -2136,7 +2136,7 @@ protected:
class Create_func_uuid : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_uuid s_singleton;
@@ -2149,7 +2149,7 @@ protected:
class Create_func_uuid_short : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_uuid_short s_singleton;
@@ -2162,7 +2162,7 @@ protected:
class Create_func_version : public Create_func_arg0
{
public:
- virtual Item *create(THD *thd);
+ virtual Item *create_builder(THD *thd);
static Create_func_version s_singleton;
@@ -2175,7 +2175,7 @@ protected:
class Create_func_weekday : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_weekday s_singleton;
@@ -2188,7 +2188,7 @@ protected:
class Create_func_weekofyear : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_weekofyear s_singleton;
@@ -2202,7 +2202,7 @@ protected:
class Create_func_within : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_within s_singleton;
@@ -2217,7 +2217,7 @@ protected:
class Create_func_x : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_x s_singleton;
@@ -2231,7 +2231,7 @@ protected:
class Create_func_xml_extractvalue : public Create_func_arg2
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
static Create_func_xml_extractvalue s_singleton;
@@ -2244,7 +2244,7 @@ protected:
class Create_func_xml_update : public Create_func_arg3
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_xml_update s_singleton;
@@ -2258,7 +2258,7 @@ protected:
class Create_func_y : public Create_func_arg1
{
public:
- virtual Item *create(THD *thd, Item *arg1);
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_y s_singleton;
@@ -2353,7 +2353,7 @@ Create_qfunc::create(THD *thd, LEX_STRIN
if (thd->lex->copy_db_to(&db.str, &db.length))
return NULL;
- return create(thd, db, name, false, item_list);
+ return create_with_db(thd, db, name, false, item_list);
}
@@ -2470,8 +2470,8 @@ Create_udf_func::create(THD *thd, udf_fu
Create_sp_func Create_sp_func::s_singleton;
Item*
-Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
- bool use_explicit_name, List<Item> *item_list)
+Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ bool use_explicit_name, List<Item> *item_list)
{
int arg_count= 0;
Item *func= NULL;
@@ -2538,7 +2538,7 @@ Create_func_arg0::create(THD *thd, LEX_S
return NULL;
}
- return create(thd);
+ return create_builder(thd);
}
@@ -2564,7 +2564,7 @@ Create_func_arg1::create(THD *thd, LEX_S
return NULL;
}
- return create(thd, param_1);
+ return create_1_arg(thd, param_1);
}
@@ -2592,7 +2592,7 @@ Create_func_arg2::create(THD *thd, LEX_S
return NULL;
}
- return create(thd, param_1, param_2);
+ return create_2_arg(thd, param_1, param_2);
}
@@ -2622,14 +2622,14 @@ Create_func_arg3::create(THD *thd, LEX_S
return NULL;
}
- return create(thd, param_1, param_2, param_3);
+ return create_3_arg(thd, param_1, param_2, param_3);
}
Create_func_abs Create_func_abs::s_singleton;
Item*
-Create_func_abs::create(THD *thd, Item *arg1)
+Create_func_abs::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_abs(arg1);
}
@@ -2638,7 +2638,7 @@ Create_func_abs::create(THD *thd, Item *
Create_func_acos Create_func_acos::s_singleton;
Item*
-Create_func_acos::create(THD *thd, Item *arg1)
+Create_func_acos::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_acos(arg1);
}
@@ -2647,7 +2647,7 @@ Create_func_acos::create(THD *thd, Item
Create_func_addtime Create_func_addtime::s_singleton;
Item*
-Create_func_addtime::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_addtime::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 0);
}
@@ -2656,7 +2656,7 @@ Create_func_addtime::create(THD *thd, It
Create_func_aes_encrypt Create_func_aes_encrypt::s_singleton;
Item*
-Create_func_aes_encrypt::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_aes_encrypt::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_aes_encrypt(arg1, arg2);
}
@@ -2665,7 +2665,7 @@ Create_func_aes_encrypt::create(THD *thd
Create_func_aes_decrypt Create_func_aes_decrypt::s_singleton;
Item*
-Create_func_aes_decrypt::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_aes_decrypt::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_aes_decrypt(arg1, arg2);
}
@@ -2675,7 +2675,7 @@ Create_func_aes_decrypt::create(THD *thd
Create_func_area Create_func_area::s_singleton;
Item*
-Create_func_area::create(THD *thd, Item *arg1)
+Create_func_area::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_area(arg1);
}
@@ -2686,7 +2686,7 @@ Create_func_area::create(THD *thd, Item
Create_func_as_wkb Create_func_as_wkb::s_singleton;
Item*
-Create_func_as_wkb::create(THD *thd, Item *arg1)
+Create_func_as_wkb::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_as_wkb(arg1);
}
@@ -2697,7 +2697,7 @@ Create_func_as_wkb::create(THD *thd, Ite
Create_func_as_wkt Create_func_as_wkt::s_singleton;
Item*
-Create_func_as_wkt::create(THD *thd, Item *arg1)
+Create_func_as_wkt::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_as_wkt(arg1);
}
@@ -2707,7 +2707,7 @@ Create_func_as_wkt::create(THD *thd, Ite
Create_func_asin Create_func_asin::s_singleton;
Item*
-Create_func_asin::create(THD *thd, Item *arg1)
+Create_func_asin::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_asin(arg1);
}
@@ -2753,7 +2753,7 @@ Create_func_atan::create_native(THD *thd
Create_func_benchmark Create_func_benchmark::s_singleton;
Item*
-Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_benchmark::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
return new (thd->mem_root) Item_func_benchmark(arg1, arg2);
@@ -2763,7 +2763,7 @@ Create_func_benchmark::create(THD *thd,
Create_func_bin Create_func_bin::s_singleton;
Item*
-Create_func_bin::create(THD *thd, Item *arg1)
+Create_func_bin::create_1_arg(THD *thd, Item *arg1)
{
Item *i10= new (thd->mem_root) Item_int((int32) 10,2);
Item *i2= new (thd->mem_root) Item_int((int32) 2,1);
@@ -2774,7 +2774,7 @@ Create_func_bin::create(THD *thd, Item *
Create_func_bit_count Create_func_bit_count::s_singleton;
Item*
-Create_func_bit_count::create(THD *thd, Item *arg1)
+Create_func_bit_count::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_bit_count(arg1);
}
@@ -2783,7 +2783,7 @@ Create_func_bit_count::create(THD *thd,
Create_func_bit_length Create_func_bit_length::s_singleton;
Item*
-Create_func_bit_length::create(THD *thd, Item *arg1)
+Create_func_bit_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_bit_length(arg1);
}
@@ -2792,7 +2792,7 @@ Create_func_bit_length::create(THD *thd,
Create_func_ceiling Create_func_ceiling::s_singleton;
Item*
-Create_func_ceiling::create(THD *thd, Item *arg1)
+Create_func_ceiling::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ceiling(arg1);
}
@@ -2802,7 +2802,7 @@ Create_func_ceiling::create(THD *thd, It
Create_func_centroid Create_func_centroid::s_singleton;
Item*
-Create_func_centroid::create(THD *thd, Item *arg1)
+Create_func_centroid::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_centroid(arg1);
}
@@ -2812,7 +2812,7 @@ Create_func_centroid::create(THD *thd, I
Create_func_char_length Create_func_char_length::s_singleton;
Item*
-Create_func_char_length::create(THD *thd, Item *arg1)
+Create_func_char_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_char_length(arg1);
}
@@ -2821,7 +2821,7 @@ Create_func_char_length::create(THD *thd
Create_func_coercibility Create_func_coercibility::s_singleton;
Item*
-Create_func_coercibility::create(THD *thd, Item *arg1)
+Create_func_coercibility::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_coercibility(arg1);
}
@@ -2873,7 +2873,7 @@ Create_func_concat_ws::create_native(THD
Create_func_compress Create_func_compress::s_singleton;
Item*
-Create_func_compress::create(THD *thd, Item *arg1)
+Create_func_compress::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_compress(arg1);
}
@@ -2882,7 +2882,7 @@ Create_func_compress::create(THD *thd, I
Create_func_connection_id Create_func_connection_id::s_singleton;
Item*
-Create_func_connection_id::create(THD *thd)
+Create_func_connection_id::create_builder(THD *thd)
{
thd->lex->safe_to_cache_query= 0;
return new (thd->mem_root) Item_func_connection_id();
@@ -2893,7 +2893,7 @@ Create_func_connection_id::create(THD *t
Create_func_contains Create_func_contains::s_singleton;
Item*
-Create_func_contains::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_contains::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_CONTAINS_FUNC);
@@ -2904,7 +2904,7 @@ Create_func_contains::create(THD *thd, I
Create_func_conv Create_func_conv::s_singleton;
Item*
-Create_func_conv::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_conv::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_conv(arg1, arg2, arg3);
}
@@ -2913,7 +2913,7 @@ Create_func_conv::create(THD *thd, Item
Create_func_convert_tz Create_func_convert_tz::s_singleton;
Item*
-Create_func_convert_tz::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_convert_tz::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_convert_tz(arg1, arg2, arg3);
}
@@ -2922,7 +2922,7 @@ Create_func_convert_tz::create(THD *thd,
Create_func_cos Create_func_cos::s_singleton;
Item*
-Create_func_cos::create(THD *thd, Item *arg1)
+Create_func_cos::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_cos(arg1);
}
@@ -2931,7 +2931,7 @@ Create_func_cos::create(THD *thd, Item *
Create_func_cot Create_func_cot::s_singleton;
Item*
-Create_func_cot::create(THD *thd, Item *arg1)
+Create_func_cot::create_1_arg(THD *thd, Item *arg1)
{
Item *i1= new (thd->mem_root) Item_int((char*) "1", 1, 1);
Item *i2= new (thd->mem_root) Item_func_tan(arg1);
@@ -2942,7 +2942,7 @@ Create_func_cot::create(THD *thd, Item *
Create_func_crc32 Create_func_crc32::s_singleton;
Item*
-Create_func_crc32::create(THD *thd, Item *arg1)
+Create_func_crc32::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_crc32(arg1);
}
@@ -2952,7 +2952,7 @@ Create_func_crc32::create(THD *thd, Item
Create_func_crosses Create_func_crosses::s_singleton;
Item*
-Create_func_crosses::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_crosses::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_CROSSES_FUNC);
@@ -2963,7 +2963,7 @@ Create_func_crosses::create(THD *thd, It
Create_func_date_format Create_func_date_format::s_singleton;
Item*
-Create_func_date_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_date_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_date_format(arg1, arg2, 0);
}
@@ -2972,7 +2972,7 @@ Create_func_date_format::create(THD *thd
Create_func_datediff Create_func_datediff::s_singleton;
Item*
-Create_func_datediff::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_datediff::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
Item *i1= new (thd->mem_root) Item_func_to_days(arg1);
Item *i2= new (thd->mem_root) Item_func_to_days(arg2);
@@ -2984,7 +2984,7 @@ Create_func_datediff::create(THD *thd, I
Create_func_dayname Create_func_dayname::s_singleton;
Item*
-Create_func_dayname::create(THD *thd, Item *arg1)
+Create_func_dayname::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dayname(arg1);
}
@@ -2993,7 +2993,7 @@ Create_func_dayname::create(THD *thd, It
Create_func_dayofmonth Create_func_dayofmonth::s_singleton;
Item*
-Create_func_dayofmonth::create(THD *thd, Item *arg1)
+Create_func_dayofmonth::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dayofmonth(arg1);
}
@@ -3002,7 +3002,7 @@ Create_func_dayofmonth::create(THD *thd,
Create_func_dayofweek Create_func_dayofweek::s_singleton;
Item*
-Create_func_dayofweek::create(THD *thd, Item *arg1)
+Create_func_dayofweek::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_weekday(arg1, 1);
}
@@ -3011,7 +3011,7 @@ Create_func_dayofweek::create(THD *thd,
Create_func_dayofyear Create_func_dayofyear::s_singleton;
Item*
-Create_func_dayofyear::create(THD *thd, Item *arg1)
+Create_func_dayofyear::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dayofyear(arg1);
}
@@ -3020,7 +3020,7 @@ Create_func_dayofyear::create(THD *thd,
Create_func_decode Create_func_decode::s_singleton;
Item*
-Create_func_decode::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_decode::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_decode(arg1, arg2);
}
@@ -3029,7 +3029,7 @@ Create_func_decode::create(THD *thd, Ite
Create_func_degrees Create_func_degrees::s_singleton;
Item*
-Create_func_degrees::create(THD *thd, Item *arg1)
+Create_func_degrees::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_units((char*) "degrees", arg1,
180/M_PI, 0.0);
@@ -3114,7 +3114,7 @@ Create_func_des_encrypt::create_native(T
Create_func_dimension Create_func_dimension::s_singleton;
Item*
-Create_func_dimension::create(THD *thd, Item *arg1)
+Create_func_dimension::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_dimension(arg1);
}
@@ -3125,7 +3125,7 @@ Create_func_dimension::create(THD *thd,
Create_func_disjoint Create_func_disjoint::s_singleton;
Item*
-Create_func_disjoint::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_DISJOINT_FUNC);
@@ -3157,7 +3157,7 @@ Create_func_elt::create_native(THD *thd,
Create_func_encode Create_func_encode::s_singleton;
Item*
-Create_func_encode::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_encode::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_encode(arg1, arg2);
}
@@ -3205,7 +3205,7 @@ Create_func_encrypt::create_native(THD *
Create_func_endpoint Create_func_endpoint::s_singleton;
Item*
-Create_func_endpoint::create(THD *thd, Item *arg1)
+Create_func_endpoint::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_spatial_decomp(arg1,
Item_func::SP_ENDPOINT);
@@ -3217,7 +3217,7 @@ Create_func_endpoint::create(THD *thd, I
Create_func_envelope Create_func_envelope::s_singleton;
Item*
-Create_func_envelope::create(THD *thd, Item *arg1)
+Create_func_envelope::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_envelope(arg1);
}
@@ -3228,7 +3228,7 @@ Create_func_envelope::create(THD *thd, I
Create_func_equals Create_func_equals::s_singleton;
Item*
-Create_func_equals::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_equals::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_EQUALS_FUNC);
@@ -3239,7 +3239,7 @@ Create_func_equals::create(THD *thd, Ite
Create_func_exp Create_func_exp::s_singleton;
Item*
-Create_func_exp::create(THD *thd, Item *arg1)
+Create_func_exp::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_exp(arg1);
}
@@ -3302,7 +3302,7 @@ Create_func_export_set::create_native(TH
Create_func_exteriorring Create_func_exteriorring::s_singleton;
Item*
-Create_func_exteriorring::create(THD *thd, Item *arg1)
+Create_func_exteriorring::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_spatial_decomp(arg1,
Item_func::SP_EXTERIORRING);
@@ -3334,7 +3334,7 @@ Create_func_field::create_native(THD *th
Create_func_find_in_set Create_func_find_in_set::s_singleton;
Item*
-Create_func_find_in_set::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_find_in_set::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_find_in_set(arg1, arg2);
}
@@ -3343,7 +3343,7 @@ Create_func_find_in_set::create(THD *thd
Create_func_floor Create_func_floor::s_singleton;
Item*
-Create_func_floor::create(THD *thd, Item *arg1)
+Create_func_floor::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_floor(arg1);
}
@@ -3352,7 +3352,7 @@ Create_func_floor::create(THD *thd, Item
Create_func_format Create_func_format::s_singleton;
Item*
-Create_func_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_format(arg1, arg2);
}
@@ -3361,7 +3361,7 @@ Create_func_format::create(THD *thd, Ite
Create_func_found_rows Create_func_found_rows::s_singleton;
Item*
-Create_func_found_rows::create(THD *thd)
+Create_func_found_rows::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -3372,7 +3372,7 @@ Create_func_found_rows::create(THD *thd)
Create_func_from_days Create_func_from_days::s_singleton;
Item*
-Create_func_from_days::create(THD *thd, Item *arg1)
+Create_func_from_days::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_from_days(arg1);
}
@@ -3500,7 +3500,7 @@ Create_func_geometry_from_wkb::create_na
Create_func_geometry_type Create_func_geometry_type::s_singleton;
Item*
-Create_func_geometry_type::create(THD *thd, Item *arg1)
+Create_func_geometry_type::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_geometry_type(arg1);
}
@@ -3511,7 +3511,7 @@ Create_func_geometry_type::create(THD *t
Create_func_geometryn Create_func_geometryn::s_singleton;
Item*
-Create_func_geometryn::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_geometryn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2,
Item_func::SP_GEOMETRYN);
@@ -3522,7 +3522,7 @@ Create_func_geometryn::create(THD *thd,
Create_func_get_lock Create_func_get_lock::s_singleton;
Item*
-Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_get_lock::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3534,7 +3534,7 @@ Create_func_get_lock::create(THD *thd, I
Create_func_glength Create_func_glength::s_singleton;
Item*
-Create_func_glength::create(THD *thd, Item *arg1)
+Create_func_glength::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_glength(arg1);
}
@@ -3565,7 +3565,7 @@ Create_func_greatest::create_native(THD
Create_func_hex Create_func_hex::s_singleton;
Item*
-Create_func_hex::create(THD *thd, Item *arg1)
+Create_func_hex::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_hex(arg1);
}
@@ -3574,7 +3574,7 @@ Create_func_hex::create(THD *thd, Item *
Create_func_ifnull Create_func_ifnull::s_singleton;
Item*
-Create_func_ifnull::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_ifnull::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_ifnull(arg1, arg2);
}
@@ -3583,7 +3583,7 @@ Create_func_ifnull::create(THD *thd, Ite
Create_func_inet_ntoa Create_func_inet_ntoa::s_singleton;
Item*
-Create_func_inet_ntoa::create(THD *thd, Item *arg1)
+Create_func_inet_ntoa::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_inet_ntoa(arg1);
}
@@ -3592,7 +3592,7 @@ Create_func_inet_ntoa::create(THD *thd,
Create_func_inet_aton Create_func_inet_aton::s_singleton;
Item*
-Create_func_inet_aton::create(THD *thd, Item *arg1)
+Create_func_inet_aton::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_inet_aton(arg1);
}
@@ -3601,7 +3601,7 @@ Create_func_inet_aton::create(THD *thd,
Create_func_instr Create_func_instr::s_singleton;
Item*
-Create_func_instr::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_instr::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_locate(arg1, arg2);
}
@@ -3611,7 +3611,7 @@ Create_func_instr::create(THD *thd, Item
Create_func_interiorringn Create_func_interiorringn::s_singleton;
Item*
-Create_func_interiorringn::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_interiorringn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2,
Item_func::SP_INTERIORRINGN);
@@ -3623,7 +3623,7 @@ Create_func_interiorringn::create(THD *t
Create_func_intersects Create_func_intersects::s_singleton;
Item*
-Create_func_intersects::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_INTERSECTS_FUNC);
@@ -3634,7 +3634,7 @@ Create_func_intersects::create(THD *thd,
Create_func_is_free_lock Create_func_is_free_lock::s_singleton;
Item*
-Create_func_is_free_lock::create(THD *thd, Item *arg1)
+Create_func_is_free_lock::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3645,7 +3645,7 @@ Create_func_is_free_lock::create(THD *th
Create_func_is_used_lock Create_func_is_used_lock::s_singleton;
Item*
-Create_func_is_used_lock::create(THD *thd, Item *arg1)
+Create_func_is_used_lock::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3657,7 +3657,7 @@ Create_func_is_used_lock::create(THD *th
Create_func_isclosed Create_func_isclosed::s_singleton;
Item*
-Create_func_isclosed::create(THD *thd, Item *arg1)
+Create_func_isclosed::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_isclosed(arg1);
}
@@ -3668,7 +3668,7 @@ Create_func_isclosed::create(THD *thd, I
Create_func_isempty Create_func_isempty::s_singleton;
Item*
-Create_func_isempty::create(THD *thd, Item *arg1)
+Create_func_isempty::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_isempty(arg1);
}
@@ -3678,7 +3678,7 @@ Create_func_isempty::create(THD *thd, It
Create_func_isnull Create_func_isnull::s_singleton;
Item*
-Create_func_isnull::create(THD *thd, Item *arg1)
+Create_func_isnull::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_isnull(arg1);
}
@@ -3688,7 +3688,7 @@ Create_func_isnull::create(THD *thd, Ite
Create_func_issimple Create_func_issimple::s_singleton;
Item*
-Create_func_issimple::create(THD *thd, Item *arg1)
+Create_func_issimple::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_issimple(arg1);
}
@@ -3698,7 +3698,7 @@ Create_func_issimple::create(THD *thd, I
Create_func_last_day Create_func_last_day::s_singleton;
Item*
-Create_func_last_day::create(THD *thd, Item *arg1)
+Create_func_last_day::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_last_day(arg1);
}
@@ -3744,7 +3744,7 @@ Create_func_last_insert_id::create_nativ
Create_func_lcase Create_func_lcase::s_singleton;
Item*
-Create_func_lcase::create(THD *thd, Item *arg1)
+Create_func_lcase::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_lcase(arg1);
}
@@ -3774,7 +3774,7 @@ Create_func_least::create_native(THD *th
Create_func_length Create_func_length::s_singleton;
Item*
-Create_func_length::create(THD *thd, Item *arg1)
+Create_func_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_length(arg1);
}
@@ -3783,7 +3783,7 @@ Create_func_length::create(THD *thd, Ite
Create_func_ln Create_func_ln::s_singleton;
Item*
-Create_func_ln::create(THD *thd, Item *arg1)
+Create_func_ln::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ln(arg1);
}
@@ -3792,7 +3792,7 @@ Create_func_ln::create(THD *thd, Item *a
Create_func_load_file Create_func_load_file::s_singleton;
Item*
-Create_func_load_file::create(THD *thd, Item *arg1)
+Create_func_load_file::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3881,7 +3881,7 @@ Create_func_log::create_native(THD *thd,
Create_func_log10 Create_func_log10::s_singleton;
Item*
-Create_func_log10::create(THD *thd, Item *arg1)
+Create_func_log10::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_log10(arg1);
}
@@ -3890,7 +3890,7 @@ Create_func_log10::create(THD *thd, Item
Create_func_log2 Create_func_log2::s_singleton;
Item*
-Create_func_log2::create(THD *thd, Item *arg1)
+Create_func_log2::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_log2(arg1);
}
@@ -3899,7 +3899,7 @@ Create_func_log2::create(THD *thd, Item
Create_func_lpad Create_func_lpad::s_singleton;
Item*
-Create_func_lpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_lpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_lpad(arg1, arg2, arg3);
}
@@ -3908,7 +3908,7 @@ Create_func_lpad::create(THD *thd, Item
Create_func_ltrim Create_func_ltrim::s_singleton;
Item*
-Create_func_ltrim::create(THD *thd, Item *arg1)
+Create_func_ltrim::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ltrim(arg1);
}
@@ -3917,7 +3917,7 @@ Create_func_ltrim::create(THD *thd, Item
Create_func_makedate Create_func_makedate::s_singleton;
Item*
-Create_func_makedate::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_makedate::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_makedate(arg1, arg2);
}
@@ -3926,7 +3926,7 @@ Create_func_makedate::create(THD *thd, I
Create_func_maketime Create_func_maketime::s_singleton;
Item*
-Create_func_maketime::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_maketime::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_maketime(arg1, arg2, arg3);
}
@@ -4001,7 +4001,7 @@ Create_func_master_pos_wait::create_nati
Create_func_md5 Create_func_md5::s_singleton;
Item*
-Create_func_md5::create(THD *thd, Item *arg1)
+Create_func_md5::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_md5(arg1);
}
@@ -4010,7 +4010,7 @@ Create_func_md5::create(THD *thd, Item *
Create_func_monthname Create_func_monthname::s_singleton;
Item*
-Create_func_monthname::create(THD *thd, Item *arg1)
+Create_func_monthname::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_monthname(arg1);
}
@@ -4019,7 +4019,7 @@ Create_func_monthname::create(THD *thd,
Create_func_name_const Create_func_name_const::s_singleton;
Item*
-Create_func_name_const::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_name_const::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_name_const(arg1, arg2);
}
@@ -4028,7 +4028,7 @@ Create_func_name_const::create(THD *thd,
Create_func_nullif Create_func_nullif::s_singleton;
Item*
-Create_func_nullif::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_nullif::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_nullif(arg1, arg2);
}
@@ -4038,7 +4038,7 @@ Create_func_nullif::create(THD *thd, Ite
Create_func_numgeometries Create_func_numgeometries::s_singleton;
Item*
-Create_func_numgeometries::create(THD *thd, Item *arg1)
+Create_func_numgeometries::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_numgeometries(arg1);
}
@@ -4049,7 +4049,7 @@ Create_func_numgeometries::create(THD *t
Create_func_numinteriorring Create_func_numinteriorring::s_singleton;
Item*
-Create_func_numinteriorring::create(THD *thd, Item *arg1)
+Create_func_numinteriorring::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_numinteriorring(arg1);
}
@@ -4060,7 +4060,7 @@ Create_func_numinteriorring::create(THD
Create_func_numpoints Create_func_numpoints::s_singleton;
Item*
-Create_func_numpoints::create(THD *thd, Item *arg1)
+Create_func_numpoints::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_numpoints(arg1);
}
@@ -4070,7 +4070,7 @@ Create_func_numpoints::create(THD *thd,
Create_func_oct Create_func_oct::s_singleton;
Item*
-Create_func_oct::create(THD *thd, Item *arg1)
+Create_func_oct::create_1_arg(THD *thd, Item *arg1)
{
Item *i10= new (thd->mem_root) Item_int((int32) 10,2);
Item *i8= new (thd->mem_root) Item_int((int32) 8,1);
@@ -4081,7 +4081,7 @@ Create_func_oct::create(THD *thd, Item *
Create_func_ord Create_func_ord::s_singleton;
Item*
-Create_func_ord::create(THD *thd, Item *arg1)
+Create_func_ord::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ord(arg1);
}
@@ -4091,7 +4091,7 @@ Create_func_ord::create(THD *thd, Item *
Create_func_overlaps Create_func_overlaps::s_singleton;
Item*
-Create_func_overlaps::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_overlaps::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_OVERLAPS_FUNC);
@@ -4102,7 +4102,7 @@ Create_func_overlaps::create(THD *thd, I
Create_func_period_add Create_func_period_add::s_singleton;
Item*
-Create_func_period_add::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_period_add::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_period_add(arg1, arg2);
}
@@ -4111,7 +4111,7 @@ Create_func_period_add::create(THD *thd,
Create_func_period_diff Create_func_period_diff::s_singleton;
Item*
-Create_func_period_diff::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_period_diff::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_period_diff(arg1, arg2);
}
@@ -4120,7 +4120,7 @@ Create_func_period_diff::create(THD *thd
Create_func_pi Create_func_pi::s_singleton;
Item*
-Create_func_pi::create(THD *thd)
+Create_func_pi::create_builder(THD *thd)
{
return new (thd->mem_root) Item_static_float_func("pi()", M_PI, 6, 8);
}
@@ -4130,7 +4130,7 @@ Create_func_pi::create(THD *thd)
Create_func_pointn Create_func_pointn::s_singleton;
Item*
-Create_func_pointn::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_pointn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2,
Item_func::SP_POINTN);
@@ -4141,7 +4141,7 @@ Create_func_pointn::create(THD *thd, Ite
Create_func_pow Create_func_pow::s_singleton;
Item*
-Create_func_pow::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_pow::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_pow(arg1, arg2);
}
@@ -4150,7 +4150,7 @@ Create_func_pow::create(THD *thd, Item *
Create_func_quote Create_func_quote::s_singleton;
Item*
-Create_func_quote::create(THD *thd, Item *arg1)
+Create_func_quote::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_quote(arg1);
}
@@ -4159,7 +4159,7 @@ Create_func_quote::create(THD *thd, Item
Create_func_radians Create_func_radians::s_singleton;
Item*
-Create_func_radians::create(THD *thd, Item *arg1)
+Create_func_radians::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_units((char*) "radians", arg1,
M_PI/180, 0.0);
@@ -4216,7 +4216,7 @@ Create_func_rand::create_native(THD *thd
Create_func_release_lock Create_func_release_lock::s_singleton;
Item*
-Create_func_release_lock::create(THD *thd, Item *arg1)
+Create_func_release_lock::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -4227,7 +4227,7 @@ Create_func_release_lock::create(THD *th
Create_func_reverse Create_func_reverse::s_singleton;
Item*
-Create_func_reverse::create(THD *thd, Item *arg1)
+Create_func_reverse::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_reverse(arg1);
}
@@ -4274,7 +4274,7 @@ Create_func_round::create_native(THD *th
Create_func_row_count Create_func_row_count::s_singleton;
Item*
-Create_func_row_count::create(THD *thd)
+Create_func_row_count::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -4285,7 +4285,7 @@ Create_func_row_count::create(THD *thd)
Create_func_rpad Create_func_rpad::s_singleton;
Item*
-Create_func_rpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_rpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_rpad(arg1, arg2, arg3);
}
@@ -4294,7 +4294,7 @@ Create_func_rpad::create(THD *thd, Item
Create_func_rtrim Create_func_rtrim::s_singleton;
Item*
-Create_func_rtrim::create(THD *thd, Item *arg1)
+Create_func_rtrim::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_rtrim(arg1);
}
@@ -4303,7 +4303,7 @@ Create_func_rtrim::create(THD *thd, Item
Create_func_sec_to_time Create_func_sec_to_time::s_singleton;
Item*
-Create_func_sec_to_time::create(THD *thd, Item *arg1)
+Create_func_sec_to_time::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sec_to_time(arg1);
}
@@ -4312,7 +4312,7 @@ Create_func_sec_to_time::create(THD *thd
Create_func_sha Create_func_sha::s_singleton;
Item*
-Create_func_sha::create(THD *thd, Item *arg1)
+Create_func_sha::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sha(arg1);
}
@@ -4321,7 +4321,7 @@ Create_func_sha::create(THD *thd, Item *
Create_func_sign Create_func_sign::s_singleton;
Item*
-Create_func_sign::create(THD *thd, Item *arg1)
+Create_func_sign::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sign(arg1);
}
@@ -4330,7 +4330,7 @@ Create_func_sign::create(THD *thd, Item
Create_func_sin Create_func_sin::s_singleton;
Item*
-Create_func_sin::create(THD *thd, Item *arg1)
+Create_func_sin::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sin(arg1);
}
@@ -4339,7 +4339,7 @@ Create_func_sin::create(THD *thd, Item *
Create_func_sleep Create_func_sleep::s_singleton;
Item*
-Create_func_sleep::create(THD *thd, Item *arg1)
+Create_func_sleep::create_1_arg(THD *thd, Item *arg1)
{
thd->lex->set_stmt_unsafe();
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -4350,7 +4350,7 @@ Create_func_sleep::create(THD *thd, Item
Create_func_soundex Create_func_soundex::s_singleton;
Item*
-Create_func_soundex::create(THD *thd, Item *arg1)
+Create_func_soundex::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_soundex(arg1);
}
@@ -4359,7 +4359,7 @@ Create_func_soundex::create(THD *thd, It
Create_func_space Create_func_space::s_singleton;
Item*
-Create_func_space::create(THD *thd, Item *arg1)
+Create_func_space::create_1_arg(THD *thd, Item *arg1)
{
/**
TODO: Fix Bug#23637
@@ -4387,7 +4387,7 @@ Create_func_space::create(THD *thd, Item
Create_func_sqrt Create_func_sqrt::s_singleton;
Item*
-Create_func_sqrt::create(THD *thd, Item *arg1)
+Create_func_sqrt::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_sqrt(arg1);
}
@@ -4397,7 +4397,7 @@ Create_func_sqrt::create(THD *thd, Item
Create_func_srid Create_func_srid::s_singleton;
Item*
-Create_func_srid::create(THD *thd, Item *arg1)
+Create_func_srid::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_srid(arg1);
}
@@ -4408,7 +4408,7 @@ Create_func_srid::create(THD *thd, Item
Create_func_startpoint Create_func_startpoint::s_singleton;
Item*
-Create_func_startpoint::create(THD *thd, Item *arg1)
+Create_func_startpoint::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_spatial_decomp(arg1,
Item_func::SP_STARTPOINT);
@@ -4419,7 +4419,7 @@ Create_func_startpoint::create(THD *thd,
Create_func_str_to_date Create_func_str_to_date::s_singleton;
Item*
-Create_func_str_to_date::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_str_to_date::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_str_to_date(arg1, arg2);
}
@@ -4428,7 +4428,7 @@ Create_func_str_to_date::create(THD *thd
Create_func_strcmp Create_func_strcmp::s_singleton;
Item*
-Create_func_strcmp::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_strcmp::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_strcmp(arg1, arg2);
}
@@ -4437,7 +4437,7 @@ Create_func_strcmp::create(THD *thd, Ite
Create_func_substr_index Create_func_substr_index::s_singleton;
Item*
-Create_func_substr_index::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_substr_index::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_substr_index(arg1, arg2, arg3);
}
@@ -4446,7 +4446,7 @@ Create_func_substr_index::create(THD *th
Create_func_subtime Create_func_subtime::s_singleton;
Item*
-Create_func_subtime::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_subtime::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 1);
}
@@ -4455,7 +4455,7 @@ Create_func_subtime::create(THD *thd, It
Create_func_tan Create_func_tan::s_singleton;
Item*
-Create_func_tan::create(THD *thd, Item *arg1)
+Create_func_tan::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_tan(arg1);
}
@@ -4464,7 +4464,7 @@ Create_func_tan::create(THD *thd, Item *
Create_func_time_format Create_func_time_format::s_singleton;
Item*
-Create_func_time_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_time_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_date_format(arg1, arg2, 1);
}
@@ -4473,7 +4473,7 @@ Create_func_time_format::create(THD *thd
Create_func_time_to_sec Create_func_time_to_sec::s_singleton;
Item*
-Create_func_time_to_sec::create(THD *thd, Item *arg1)
+Create_func_time_to_sec::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_time_to_sec(arg1);
}
@@ -4482,7 +4482,7 @@ Create_func_time_to_sec::create(THD *thd
Create_func_timediff Create_func_timediff::s_singleton;
Item*
-Create_func_timediff::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_timediff::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_timediff(arg1, arg2);
}
@@ -4491,7 +4491,7 @@ Create_func_timediff::create(THD *thd, I
Create_func_to_days Create_func_to_days::s_singleton;
Item*
-Create_func_to_days::create(THD *thd, Item *arg1)
+Create_func_to_days::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_to_days(arg1);
}
@@ -4501,7 +4501,7 @@ Create_func_to_days::create(THD *thd, It
Create_func_touches Create_func_touches::s_singleton;
Item*
-Create_func_touches::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_touches::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_TOUCHES_FUNC);
@@ -4512,7 +4512,7 @@ Create_func_touches::create(THD *thd, It
Create_func_ucase Create_func_ucase::s_singleton;
Item*
-Create_func_ucase::create(THD *thd, Item *arg1)
+Create_func_ucase::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ucase(arg1);
}
@@ -4521,7 +4521,7 @@ Create_func_ucase::create(THD *thd, Item
Create_func_uncompress Create_func_uncompress::s_singleton;
Item*
-Create_func_uncompress::create(THD *thd, Item *arg1)
+Create_func_uncompress::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_uncompress(arg1);
}
@@ -4530,7 +4530,7 @@ Create_func_uncompress::create(THD *thd,
Create_func_uncompressed_length Create_func_uncompressed_length::s_singleton;
Item*
-Create_func_uncompressed_length::create(THD *thd, Item *arg1)
+Create_func_uncompressed_length::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_uncompressed_length(arg1);
}
@@ -4539,7 +4539,7 @@ Create_func_uncompressed_length::create(
Create_func_unhex Create_func_unhex::s_singleton;
Item*
-Create_func_unhex::create(THD *thd, Item *arg1)
+Create_func_unhex::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_unhex(arg1);
}
@@ -4584,7 +4584,7 @@ Create_func_unix_timestamp::create_nativ
Create_func_uuid Create_func_uuid::s_singleton;
Item*
-Create_func_uuid::create(THD *thd)
+Create_func_uuid::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -4595,7 +4595,7 @@ Create_func_uuid::create(THD *thd)
Create_func_uuid_short Create_func_uuid_short::s_singleton;
Item*
-Create_func_uuid_short::create(THD *thd)
+Create_func_uuid_short::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
thd->lex->safe_to_cache_query= 0;
@@ -4606,7 +4606,7 @@ Create_func_uuid_short::create(THD *thd)
Create_func_version Create_func_version::s_singleton;
Item*
-Create_func_version::create(THD *thd)
+Create_func_version::create_builder(THD *thd)
{
thd->lex->set_stmt_unsafe();
return new (thd->mem_root) Item_static_string_func("version()",
@@ -4620,7 +4620,7 @@ Create_func_version::create(THD *thd)
Create_func_weekday Create_func_weekday::s_singleton;
Item*
-Create_func_weekday::create(THD *thd, Item *arg1)
+Create_func_weekday::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_weekday(arg1, 0);
}
@@ -4629,7 +4629,7 @@ Create_func_weekday::create(THD *thd, It
Create_func_weekofyear Create_func_weekofyear::s_singleton;
Item*
-Create_func_weekofyear::create(THD *thd, Item *arg1)
+Create_func_weekofyear::create_1_arg(THD *thd, Item *arg1)
{
Item *i1= new (thd->mem_root) Item_int((char*) "0", 3, 1);
return new (thd->mem_root) Item_func_week(arg1, i1);
@@ -4640,7 +4640,7 @@ Create_func_weekofyear::create(THD *thd,
Create_func_within Create_func_within::s_singleton;
Item*
-Create_func_within::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_within::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_WITHIN_FUNC);
@@ -4652,7 +4652,7 @@ Create_func_within::create(THD *thd, Ite
Create_func_x Create_func_x::s_singleton;
Item*
-Create_func_x::create(THD *thd, Item *arg1)
+Create_func_x::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_x(arg1);
}
@@ -4662,7 +4662,7 @@ Create_func_x::create(THD *thd, Item *ar
Create_func_xml_extractvalue Create_func_xml_extractvalue::s_singleton;
Item*
-Create_func_xml_extractvalue::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_xml_extractvalue::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
return new (thd->mem_root) Item_func_xml_extractvalue(arg1, arg2);
}
@@ -4671,7 +4671,7 @@ Create_func_xml_extractvalue::create(THD
Create_func_xml_update Create_func_xml_update::s_singleton;
Item*
-Create_func_xml_update::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_xml_update::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
{
return new (thd->mem_root) Item_func_xml_update(arg1, arg2, arg3);
}
@@ -4681,7 +4681,7 @@ Create_func_xml_update::create(THD *thd,
Create_func_y Create_func_y::s_singleton;
Item*
-Create_func_y::create(THD *thd, Item *arg1)
+Create_func_y::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_y(arg1);
}
=== modified file 'sql/item_create.h'
--- a/sql/item_create.h 2007-08-15 13:43:08 +0000
+++ b/sql/item_create.h 2010-03-28 18:10:00 +0000
@@ -91,8 +91,9 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call
*/
- virtual Item* create(THD *thd, LEX_STRING db, LEX_STRING name,
- bool use_explicit_name, List<Item> *item_list) = 0;
+ virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ bool use_explicit_name,
+ List<Item> *item_list) = 0;
protected:
/** Constructor. */
=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc 2010-01-15 15:27:55 +0000
+++ b/sql/item_sum.cc 2010-03-28 18:10:00 +0000
@@ -642,7 +642,7 @@ Item_sum_hybrid::fix_fields(THD *thd, It
default:
DBUG_ASSERT(0);
};
- setup(args[0], NULL);
+ setup_item(args[0], NULL);
/* MIN/MAX can return NULL for empty set indepedent of the used column */
maybe_null= 1;
unsigned_flag=item->unsigned_flag;
@@ -676,7 +676,7 @@ Item_sum_hybrid::fix_fields(THD *thd, It
of the original MIN/MAX object and it is saved in this object's cache.
*/
-void Item_sum_hybrid::setup(Item *item, Item *value_arg)
+void Item_sum_hybrid::setup_item(Item *item, Item *value_arg)
{
value= Item_cache::get_cache(item);
value->setup(item);
@@ -1646,7 +1646,7 @@ void Item_sum_hybrid::no_rows_in_result(
Item *Item_sum_min::copy_or_same(THD* thd)
{
Item_sum_min *item= new (thd->mem_root) Item_sum_min(thd, this);
- item->setup(args[0], value);
+ item->setup_item(args[0], value);
return item;
}
@@ -1669,7 +1669,7 @@ bool Item_sum_min::add()
Item *Item_sum_max::copy_or_same(THD* thd)
{
Item_sum_max *item= new (thd->mem_root) Item_sum_max(thd, this);
- item->setup(args[0], value);
+ item->setup_item(args[0], value);
return item;
}
=== modified file 'sql/item_sum.h'
--- a/sql/item_sum.h 2010-02-01 06:14:12 +0000
+++ b/sql/item_sum.h 2010-04-01 09:04:26 +0000
@@ -870,7 +870,7 @@ protected:
was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
- void setup(Item *item, Item *value_arg);
+ void setup_item(Item *item, Item *value_arg);
void clear();
double val_real();
longlong val_int();
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-03-15 11:51:23 +0000
+++ b/sql/log.cc 2010-04-01 09:04:26 +0000
@@ -5424,7 +5424,7 @@ int TC_LOG_MMAP::open(const char *opt_na
pg->state=POOL;
pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST);
pthread_cond_init (&pg->cond, 0);
- pg->start=(my_xid *)(data + i*tc_log_page_size);
+ pg->ptr= pg->start=(my_xid *)(data + i*tc_log_page_size);
pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
pg->end=pg->start + pg->size;
}
@@ -5659,7 +5659,15 @@ int TC_LOG_MMAP::sync()
/* marking 'syncing' slot free */
pthread_mutex_lock(&LOCK_sync);
syncing=0;
- pthread_cond_signal(&active->cond); // wake up a new syncer
+ /*
+ we check the "active" pointer without LOCK_active. Still, it's safe -
+ "active" can change from NULL to not NULL any time, but it
+ will take LOCK_sync before waiting on active->cond. That is, it can never
+ miss a signal.
+ And "active" can change to NULL only after LOCK_sync, so this is safe too.
+ */
+ if (active)
+ pthread_cond_signal(&active->cond); // wake up a new syncer
pthread_mutex_unlock(&LOCK_sync);
return err;
}
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-29 15:13:53 +0000
+++ b/sql/mysqld.cc 2010-04-01 09:04:26 +0000
@@ -8371,6 +8371,8 @@ mysqld_get_one_option(int optid,
case (int) OPT_INIT_RPL_ROLE:
{
int role;
+ LINT_INIT(role);
+
if (!find_opt_type(argument, &rpl_role_typelib, opt->name, &role))
{
rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
@@ -8427,6 +8429,8 @@ mysqld_get_one_option(int optid,
case OPT_BINLOG_FORMAT:
{
int id;
+ LINT_INIT(id);
+
if (!find_opt_type(argument, &binlog_format_typelib, opt->name, &id))
{
global_system_variables.binlog_format= opt_binlog_format_id= id - 1;
@@ -8677,6 +8681,8 @@ mysqld_get_one_option(int optid,
else
{
int type;
+ LINT_INIT(type);
+
if (!find_opt_type(argument, &delay_key_write_typelib, opt->name, &type))
delay_key_write_options= (uint) type-1;
}
@@ -8688,6 +8694,8 @@ mysqld_get_one_option(int optid,
case OPT_TX_ISOLATION:
{
int type;
+ LINT_INIT(type);
+
if (!find_opt_type(argument, &tx_isolation_typelib, opt->name, &type))
global_system_variables.tx_isolation= (type-1);
break;
@@ -8775,6 +8783,7 @@ mysqld_get_one_option(int optid,
ulong method_conv;
int method;
LINT_INIT(method_conv);
+ LINT_INIT(method);
myisam_stats_method_str= argument;
if (!find_opt_type(argument, &myisam_stats_method_typelib,
@@ -8837,6 +8846,7 @@ mysqld_get_one_option(int optid,
case OPT_THREAD_HANDLING:
{
int id;
+ LINT_INIT(id);
if (!find_opt_type(argument, &thread_handling_typelib, opt->name, &id))
global_system_variables.thread_handling= id - 1;
opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling];
=== modified file 'sql/net_serv.cc'
--- a/sql/net_serv.cc 2010-02-23 12:04:58 +0000
+++ b/sql/net_serv.cc 2010-03-29 19:07:45 +0000
@@ -279,7 +279,7 @@ static int net_data_is_ready(my_socket s
@param clear_buffer if <> 0, then clear all data from comm buff
*/
-void net_clear(NET *net, my_bool clear_buffer)
+void net_clear(NET *net, my_bool clear_buffer __attribute__((unused)))
{
#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)
size_t count;
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-03-15 11:51:23 +0000
+++ b/sql/set_var.cc 2010-04-01 09:04:26 +0000
@@ -1266,16 +1266,16 @@ uchar *sys_var_set::value_ptr(THD *thd,
void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type)
{
- slave_exec_mode_options= 0;
- bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
+ slave_exec_mode_options= (ULL(1) << SLAVE_EXEC_MODE_STRICT);
}
bool sys_var_set_slave_mode::check(THD *thd, set_var *var)
{
bool rc= sys_var_set::check(thd, var);
if (!rc &&
- bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_STRICT) == 1 &&
- bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
+ test_all_bits(var->save_result.ulong_value,
+ ((ULL(1) << SLAVE_EXEC_MODE_STRICT) |
+ (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))))
{
rc= true;
my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), "");
@@ -1297,15 +1297,16 @@ void fix_slave_exec_mode(enum_var_type t
DBUG_ENTER("fix_slave_exec_mode");
compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT
> SLAVE_EXEC_MODE_LAST_BIT - 1);
- if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT) == 1 &&
- bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
+ if (test_all_bits(slave_exec_mode_options,
+ ((ULL(1) << SLAVE_EXEC_MODE_STRICT) |
+ (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT))))
{
sql_print_error("Ambiguous slave modes combination."
" STRICT will be used");
- bit_do_clear(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT);
+ slave_exec_mode_options&= ~(ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT);
}
- if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 0)
- bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
+ if (!(slave_exec_mode_options & (ULL(1) << SLAVE_EXEC_MODE_IDEMPOTENT)))
+ slave_exec_mode_options|= (ULL(1)<< SLAVE_EXEC_MODE_STRICT);
DBUG_VOID_RETURN;
}
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sp_head.cc 2010-04-01 09:04:26 +0000
@@ -2089,6 +2089,8 @@ sp_head::reset_lex(THD *thd)
sublex->dec= NULL;
sublex->interval_list.empty();
sublex->type= 0;
+ sublex->uint_geom_type= 0;
+ sublex->vcol_info= 0;
DBUG_RETURN(FALSE);
}
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-31 18:37:45 +0000
+++ b/sql/sql_acl.cc 2010-04-01 09:04:26 +0000
@@ -536,6 +536,9 @@ static my_bool acl_load(THD *thd, TABLE_
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
+ char *password;
+ uint password_len;
+
bzero(&user, sizeof(user));
update_hostname(&user.host, get_field(&mem, table->field[0]));
user.user= get_field(&mem, table->field[1]);
@@ -548,8 +551,8 @@ static my_bool acl_load(THD *thd, TABLE_
continue;
}
- char *password= get_field(thd->mem_root, table->field[2]);
- uint password_len= password ? strlen(password) : 0;
+ password= get_field(&mem, table->field[2]);
+ password_len= password ? strlen(password) : 0;
user.auth_string.str= password ? password : const_cast<char*>("");
user.auth_string.length= password_len;
set_user_salt(&user, password, password_len);
@@ -7826,15 +7829,15 @@ static int do_auth_once(THD *thd, LEX_ST
bool unlock_plugin= false;
plugin_ref plugin;
+#ifdef EMBEDDED_LIBRARY
+ plugin= native_password_plugin;
+#else
if (auth_plugin_name->str == native_password_plugin_name.str)
plugin= native_password_plugin;
- else
-#ifndef EMBEDDED_LIBRARY
- if (auth_plugin_name->str == old_password_plugin_name.str)
+ else if (auth_plugin_name->str == old_password_plugin_name.str)
plugin= old_password_plugin;
- else
- if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
- MYSQL_AUTHENTICATION_PLUGIN)))
+ else if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
+ MYSQL_AUTHENTICATION_PLUGIN)))
unlock_plugin= true;
#endif
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-29 15:13:53 +0000
+++ b/sql/sql_class.h 2010-04-01 09:04:26 +0000
@@ -63,6 +63,7 @@ public:
bool report_error(THD *thd);
bool is_invalidated() const { return m_invalidated; }
void reset_reprepare_observer() { m_invalidated= FALSE; }
+ Reprepare_observer() {} /* Remove gcc warning */
private:
bool m_invalidated;
};
@@ -1117,6 +1118,7 @@ public:
/* Ignore error */
return TRUE;
}
+ Dummy_error_handler() {} /* Remove gcc warning */
};
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_table.cc 2010-04-01 09:04:26 +0000
@@ -5704,6 +5704,10 @@ compare_tables(TABLE *table,
*/
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */
+
+ /* Set default value for return value (to ensure it's always set) */
+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
+
/* Create the prepared information. */
if (mysql_prepare_create_table(thd, create_info,
&tmp_alter_info,
@@ -5762,7 +5766,6 @@ compare_tables(TABLE *table,
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
{
DBUG_PRINT("info", ("Basic checks -> ALTER_TABLE_DATA_CHANGED"));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
@@ -5792,7 +5795,6 @@ compare_tables(TABLE *table,
{
DBUG_PRINT("info", ("NULL behaviour difference in field '%s' -> "
"ALTER_TABLE_DATA_CHANGED", new_field->field_name));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
@@ -5828,7 +5830,6 @@ compare_tables(TABLE *table,
{
DBUG_PRINT("info", ("!field_is_equal('%s') -> ALTER_TABLE_DATA_CHANGED",
new_field->field_name));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
// Clear indexed marker
@@ -5963,7 +5964,6 @@ compare_tables(TABLE *table,
{
DBUG_PRINT("info", ("check_if_incompatible_data() -> "
"ALTER_TABLE_DATA_CHANGED"));
- *need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
}
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2010-03-04 08:03:07 +0000
+++ b/sql/sql_view.cc 2010-03-30 12:36:49 +0000
@@ -1034,10 +1034,12 @@ bool mysql_make_view(THD *thd, File_pars
bool parse_status;
bool result, view_is_mergeable;
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));
+ LINT_INIT(parse_status);
+ LINT_INIT(view_select);
+
if (table->view)
{
/*
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-03-29 15:13:53 +0000
+++ b/sql/sql_yacc.yy 2010-04-01 09:04:26 +0000
@@ -2342,6 +2342,7 @@ sp_init_param:
lex->interval_list.empty();
lex->uint_geom_type= 0;
+ lex->vcol_info= 0;
}
;
@@ -8190,7 +8191,7 @@ function_call_generic:
builder= find_qualified_function_builder(thd);
DBUG_ASSERT(builder);
- item= builder->create(thd, $1, $3, true, $5);
+ item= builder->create_with_db(thd, $1, $3, true, $5);
if (! ($$= item))
{
=== modified file 'storage/example/ha_example.h'
--- a/storage/example/ha_example.h 2007-08-13 13:11:25 +0000
+++ b/storage/example/ha_example.h 2010-03-28 18:10:00 +0000
@@ -155,7 +155,8 @@ public:
/** @brief
This method will never be called if you do not implement indexes.
*/
- virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
+ virtual double read_time(uint index, uint ranges, ha_rows rows)
+ { return (double) rows / 20.0+1; }
/*
Everything below are methods that we implement in ha_example.cc.
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-03-30 12:35:15 +0000
+++ b/storage/maria/ma_loghandler.c 2010-04-01 09:04:26 +0000
@@ -1274,6 +1274,8 @@ static my_bool translog_set_lsn_for_file
for (file= from_file; file <= to_file; file++)
{
LOGHANDLER_FILE_INFO info;
+ LINT_INIT(info.max_lsn);
+
File fd= open_logfile_by_number_no_cache(file);
LINT_INIT_STRUCT(info);
if ((fd < 0) ||
@@ -3968,6 +3970,7 @@ my_bool translog_init_with_table(const c
{
LOGHANDLER_FILE_INFO info;
LINT_INIT_STRUCT(info);
+
/*
Accessing &log_descriptor.open_files without mutex is safe
because it is initialization
=== modified file 'storage/maria/ma_search.c'
--- a/storage/maria/ma_search.c 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ma_search.c 2010-04-01 09:04:26 +0000
@@ -76,8 +76,8 @@ int _ma_search(register MARIA_HA *info,
bmove512(info->keyread_buff, page_buff, info->s->block_size);
/* Save position for a possible read next / previous */
- info->int_keypos= info->keyread_buff + (ulonglong) info->int_keypos;
- info->int_maxpos= info->keyread_buff + (ulonglong) info->int_maxpos;
+ info->int_keypos= info->keyread_buff + info->keypos_offset;
+ info->int_maxpos= info->keyread_buff + info->maxpos_offset;
info->int_keytree_version= key->keyinfo->version;
info->last_search_keypage= info->last_keypage;
info->page_changed= 0;
@@ -214,8 +214,8 @@ static int _ma_search_no_save(register M
info->cur_row.trid= _ma_trid_from_key(&info->last_key);
/* Store offset to key */
- info->int_keypos= (uchar*) (keypos - page.buff);
- info->int_maxpos= (uchar*) (maxpos - page.buff);
+ info->keypos_offset= (uint) (keypos - page.buff);
+ info->maxpos_offset= (uint) (maxpos - page.buff);
info->int_nod_flag= nod_flag;
info->last_keypage= pos;
*res_page_link= page_link;
=== modified file 'storage/maria/maria_def.h'
--- a/storage/maria/maria_def.h 2010-03-09 19:22:24 +0000
+++ b/storage/maria/maria_def.h 2010-03-28 18:10:00 +0000
@@ -506,8 +506,10 @@ struct st_maria_handler
uchar *first_mbr_key; /* Searhed spatial key */
uchar *rec_buff; /* Temp buffer for recordpack */
uchar *blob_buff; /* Temp buffer for blobs */
- uchar *int_keypos, /* Save position for next/previous */
- *int_maxpos; /* -""- */
+ uchar *int_keypos; /* Save position for next/previous */
+ uchar *int_maxpos; /* -""- */
+ uint keypos_offset; /* Tmp storage for offset int_keypos */
+ uint maxpos_offset; /* Tmp storage for offset int_maxpos */
uchar *update_field_data; /* Used by update in rows-in-block */
uint int_nod_flag; /* -""- */
uint32 int_keytree_version; /* -""- */
=== modified file 'storage/myisam/ft_stopwords.c'
--- a/storage/myisam/ft_stopwords.c 2010-03-10 10:32:14 +0000
+++ b/storage/myisam/ft_stopwords.c 2010-03-28 18:10:00 +0000
@@ -44,9 +44,10 @@ static void FT_STOPWORD_free(FT_STOPWORD
static int ft_add_stopword(const char *w)
{
FT_STOPWORD sw;
- return !w ||
- (((sw.len= (uint) strlen(sw.pos=(const uchar *)w)) >= ft_min_word_len) &&
- (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL));
+ return (!w ||
+ (((sw.len= (uint) strlen((char*) (sw.pos=(const uchar *)w))) >=
+ ft_min_word_len) &&
+ (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL)));
}
int ft_init_stopwords()
=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc 2010-03-04 08:03:07 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc 2010-03-30 12:36:49 +0000
@@ -382,7 +382,7 @@ static MI_INFO *myisammrg_attach_childre
my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
}
DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx my_errno: %d",
- my_errno ? NULL : (long) myisam, my_errno));
+ my_errno ? 0L : (long) myisam, my_errno));
err:
DBUG_RETURN(my_errno ? NULL : myisam);
=== modified file 'storage/myisammrg/myrg_open.c'
--- a/storage/myisammrg/myrg_open.c 2009-09-23 13:21:29 +0000
+++ b/storage/myisammrg/myrg_open.c 2010-03-30 12:36:49 +0000
@@ -239,6 +239,7 @@ MYRG_INFO *myrg_parent_open(const char *
rc= 1;
errpos= 0;
bzero((char*) &file_cache, sizeof(file_cache));
+ LINT_INIT(m_info);
/* Open MERGE meta file. */
if ((fd= my_open(fn_format(parent_name_buff, parent_name, "", MYRG_NAME_EXT,
=== modified file 'storage/xtradb/include/page0page.h'
--- a/storage/xtradb/include/page0page.h 2010-01-06 12:00:14 +0000
+++ b/storage/xtradb/include/page0page.h 2010-03-28 18:10:00 +0000
@@ -517,7 +517,7 @@ UNIV_INLINE
rec_t*
page_rec_get_next(
/*==============*/
- rec_t* rec); /*!< in: pointer to record */
+ const rec_t* rec); /*!< in: pointer to record */
/************************************************************//**
Gets the pointer to the next record on the page.
@return pointer to next record */
=== modified file 'storage/xtradb/include/page0page.ic'
--- a/storage/xtradb/include/page0page.ic 2010-01-06 12:00:14 +0000
+++ b/storage/xtradb/include/page0page.ic 2010-03-28 18:10:00 +0000
@@ -731,7 +731,7 @@ UNIV_INLINE
rec_t*
page_rec_get_next(
/*==============*/
- rec_t* rec) /*!< in: pointer to record */
+ const rec_t* rec) /*!< in: pointer to record */
{
return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec)));
}
=== modified file 'storage/xtradb/include/ut0lst.h'
--- a/storage/xtradb/include/ut0lst.h 2009-09-07 10:22:53 +0000
+++ b/storage/xtradb/include/ut0lst.h 2010-03-30 12:36:49 +0000
@@ -158,7 +158,7 @@ Inserts a NODE2 after NODE1 in a list.
/** Invalidate the pointers in a list node.
@param NAME list name
@param N pointer to the node that was removed */
-# define UT_LIST_REMOVE_CLEAR(NAME, N) while (0)
+# define UT_LIST_REMOVE_CLEAR(NAME, N) {} while (0)
#endif
/*******************************************************************//**
=== modified file 'strings/ctype-ucs2.c'
--- a/strings/ctype-ucs2.c 2010-03-15 11:51:23 +0000
+++ b/strings/ctype-ucs2.c 2010-04-01 09:04:26 +0000
@@ -203,7 +203,7 @@ static int my_strnncoll_ucs2(CHARSET_INF
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
@@ -317,7 +317,7 @@ static int my_strncasecmp_ucs2(CHARSET_I
const char *s, const char *t, size_t len)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const char *se=s+len;
const char *te=t+len;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
@@ -1384,7 +1384,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
=== modified file 'strings/ctype-utf8.c'
--- a/strings/ctype-utf8.c 2010-01-06 19:20:16 +0000
+++ b/strings/ctype-utf8.c 2010-04-01 09:04:26 +0000
@@ -2308,7 +2308,7 @@ static int my_strnncoll_utf8(CHARSET_INF
my_bool t_is_prefix)
{
int s_res,t_res;
- my_wc_t UNINIT_VAR(s_wc), t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
@@ -2378,7 +2378,7 @@ static int my_strnncollsp_utf8(CHARSET_I
my_bool diff_if_only_endspace_difference)
{
int s_res, t_res, res;
- my_wc_t UNINIT_VAR(s_wc),t_wc;
+ my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se= s+slen, *te= t+tlen;
MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
=== modified file 'strings/my_vsnprintf.c'
--- a/strings/my_vsnprintf.c 2010-03-03 14:44:14 +0000
+++ b/strings/my_vsnprintf.c 2010-04-01 09:04:26 +0000
@@ -400,16 +400,18 @@ start:
case 's':
{
char *par= args_arr[print_arr[i].arg_idx].str_arg;
- width= (print_arr[i].flags & WIDTH_ARG) ?
- args_arr[print_arr[i].width].longlong_arg : print_arr[i].width;
+ width= ((print_arr[i].flags & WIDTH_ARG) ?
+ (uint) args_arr[print_arr[i].width].longlong_arg :
+ (uint) print_arr[i].width);
to= process_str_arg(cs, to, end, width, par, print_arr[i].flags);
break;
}
case 'b':
{
char *par = args_arr[print_arr[i].arg_idx].str_arg;
- width= (print_arr[i].flags & WIDTH_ARG) ?
- args_arr[print_arr[i].width].longlong_arg : print_arr[i].width;
+ width= ((print_arr[i].flags & WIDTH_ARG) ?
+ (uint) args_arr[print_arr[i].width].longlong_arg :
+ (uint) print_arr[i].width);
to= process_bin_arg(to, end, width, par);
break;
}
@@ -428,8 +430,9 @@ start:
{
/* Integer parameter */
longlong larg;
- length= (print_arr[i].flags & LENGTH_ARG) ?
- args_arr[print_arr[i].length].longlong_arg : print_arr[i].length;
+ length= ((print_arr[i].flags & LENGTH_ARG) ?
+ args_arr[print_arr[i].length].longlong_arg :
+ (longlong) print_arr[i].length);
if (args_arr[print_arr[i].arg_idx].have_longlong)
larg = args_arr[print_arr[i].arg_idx].longlong_arg;
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-03-10 10:32:14 +0000
+++ b/support-files/compiler_warnings.supp 2010-03-31 19:12:21 +0000
@@ -39,6 +39,7 @@ sync/sync0rw\.c: unused parameter
sync/sync0sync\.c: unused parameter
sync/sync0sync\.c: unused variable
ut/ut0ut\.c: ignoring return value of
+srv/srv0srv\.c: value computed is not used
#
# bdb is not critical to keep up to date
@@ -53,6 +54,12 @@ db_vrfy.c : .*comparison is always false
# readline is not maintained by us
#
.*/cmd-line-utils/readline/.* : .*
+readline\.c : unused parameter
+term\.c : unused parameter
+vi\.c : unused parameter
+common\.c : unused parameter
+term\.c : *.*
+
#
# Ignore some warnings in libevent, which is not maintained by us.
@@ -66,6 +73,16 @@ db_vrfy.c : .*comparison is always false
/usr/share/aclocal/audiofile.m4 : .*
#
+# Ignore strict-aliasing warnings (for now)
+#
+.*: break strict-aliasing rules
+
+#
+# Ignore not important declaration warnings
+#
+.*: only defines private constructors and has no friends
+
+#
# Ignore all conversion warnings on windows 64
# (Is safe as we are not yet supporting strings >= 2G)
#
@@ -100,6 +117,11 @@ db_vrfy.c : .*comparison is always false
storage/maria/ma_pagecache.c: .*'info_check_pin' defined but not used
#
+# Pbxt
+#
+xaction_xt\.cc: may be used uninitialized in this function
+
+#
# I think these are due to mix of C and C++.
#
storage/pbxt/ : typedef.*was ignored in this declaration
@@ -112,6 +134,7 @@ include/runtime.hpp: .*pure_error.*
.*/extra/yassl/taocrypt/src/blowfish\.cpp: array subscript is above array bounds
.*/extra/yassl/taocrypt/src/file\.cpp: ignoring return value
.*/extra/yassl/taocrypt/src/integer\.cpp: control reaches end of non-void function
+mySTL/algorithm\.hpp: is used uninitialized in this function
#
# Groff warnings on OpenSUSE.
@@ -123,18 +146,18 @@ include/runtime.hpp: .*pure_error.*
#
listener.cc : .*conversion from 'SOCKET' to 'int'.*
net_serv.cc : .*conversion from 'SOCKET' to 'int'.*
-set_var.cc: right-hand operand of comma has no effect : 1000-1400
-
# allow a little moving space for the warning below
-mi_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600
-ma_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 550-650
+mi_packrec\.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600
+ma_packrec\.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 550-650
#
# Wrong compiler warnings
#
.* : .*no matching operator delete found; memory will not be freed if initialization throws an exception.*
-ctype-simple.c : .*unary minus operator applied to unsigned type, result still unsigned.*
+ctype-simple\.c : .*unary minus operator applied to unsigned type, result still unsigned.*
# Wrong warning due to GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29478
-regexec\.c : .*passing argument 3 of.*matcher.* discards qualifiers from pointer target type.*
+regexec\.c : passing argument 3 of.*matcher.* discards qualifiers from pointer target type
+libmysql\.c: passing argument 2 of .*memcpy.* discards qualifiers from pointer target type : 3000-4000
+storage/xtradb/dict/dict0dict\.c: passing argument 1 of .*strcpy.* discards qualifiers from pointer target type : 2500-3500
=== modified file 'unittest/mysys/waiting_threads-t.c'
--- a/unittest/mysys/waiting_threads-t.c 2010-01-28 14:49:14 +0000
+++ b/unittest/mysys/waiting_threads-t.c 2010-03-30 12:36:49 +0000
@@ -258,7 +258,7 @@ void do_tests()
#define test_kill_strategy(X) \
diag("kill strategy: " #X); \
DBUG_EXECUTE("reset_file", \
- { rewind(DBUG_FILE); (void) ftruncate(fileno(DBUG_FILE), 0); }); \
+ { rewind(DBUG_FILE); my_chsize(fileno(DBUG_FILE), 0, 0, MYF(MY_WME)); }); \
DBUG_PRINT("info", ("kill strategy: " #X)); \
kill_strategy=X; \
do_one_test();
1
0

[Maria-developers] Updated (by Guest): Table elimination (17)
by worklog-noreply@askmonty.org 01 Apr '10
by worklog-noreply@askmonty.org 01 Apr '10
01 Apr '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Table elimination
CREATION DATE..: Sun, 10 May 2009, 19:57
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 17 (http://askmonty.org/worklog/?tid=17)
VERSION........: Server-9.x
STATUS.........: Assigned
PRIORITY.......: 60
WORKED HOURS...: 1
ESTIMATE.......: 3 (hours remain)
ORIG. ESTIMATE.: 3
PROGRESS NOTES:
-=-=(Guest - Thu, 01 Apr 2010, 01:56)=-=-
New attachment: '16_bitMICRO-PROCESSOR.htm'
-=-=(Guest - Wed, 24 Mar 2010, 05:58)=-=-
Status updated.
--- /tmp/wklog.17.old.13223 2010-03-24 05:58:26.000000000 +0000
+++ /tmp/wklog.17.new.13223 2010-03-24 05:58:26.000000000 +0000
@@ -1 +1 @@
-In-Progress
+Assigned
-=-=(Guest - Wed, 24 Mar 2010, 05:58)=-=-
Privacy level updated.
--- /tmp/wklog.17.old.13223 2010-03-24 05:58:26.000000000 +0000
+++ /tmp/wklog.17.new.13223 2010-03-24 05:58:26.000000000 +0000
@@ -1 +1 @@
-n
+y
-=-=(Guest - Wed, 28 Oct 2009, 02:01)=-=-
Version updated.
--- /tmp/wklog.17.old.24041 2009-10-28 02:01:58.000000000 +0200
+++ /tmp/wklog.17.new.24041 2009-10-28 02:01:58.000000000 +0200
@@ -1 +1 @@
-9.x
+Server-9.x
-=-=(Guest - Sun, 16 Aug 2009, 16:16)=-=-
Category updated.
--- /tmp/wklog.17.old.24882 2009-08-16 16:16:49.000000000 +0300
+++ /tmp/wklog.17.new.24882 2009-08-16 16:16:49.000000000 +0300
@@ -1 +1 @@
-Client-BackLog
+Server-Sprint
-=-=(Guest - Sun, 16 Aug 2009, 16:16)=-=-
Version updated.
--- /tmp/wklog.17.old.24882 2009-08-16 16:16:49.000000000 +0300
+++ /tmp/wklog.17.new.24882 2009-08-16 16:16:49.000000000 +0300
@@ -1 +1 @@
-Server-5.1
+9.x
-=-=(Guest - Wed, 29 Jul 2009, 21:41)=-=-
Low Level Design modified.
--- /tmp/wklog.17.old.26011 2009-07-29 21:41:04.000000000 +0300
+++ /tmp/wklog.17.new.26011 2009-07-29 21:41:04.000000000 +0300
@@ -2,163 +2,146 @@
~maria-captains/maria/maria-5.1-table-elimination tree.
<contents>
-1. Conditions for removal
-1.1 Quick check if there are candidates
-2. Removal operation properties
-3. Removal operation
-4. User interface
-5. Tests and benchmarks
-6. Todo, issues to resolve
-6.1 To resolve
-6.2 Resolved
-7. Additional issues
+1. Elimination criteria
+2. No outside references check
+2.1 Quick check if there are tables with no outside references
+3. One-match check
+3.1 Functional dependency source #1: Potential eq_ref access
+3.2 Functional dependency source #2: col2=func(col1)
+3.3 Functional dependency source #3: One or zero records in the table
+3.4 Functional dependency check implementation
+3.4.1 Equality collection: Option1
+3.4.2 Equality collection: Option2
+3.4.3 Functional dependency propagation - option 1
+3.4.4 Functional dependency propagation - option 2
+4. Removal operation properties
+5. Removal operation
+6. User interface
+6.1 @@optimizer_switch flag
+6.2 EXPLAIN [EXTENDED]
+7. Miscellaneous adjustments
+7.1 Fix used_tables() of aggregate functions
+7.2 Make subquery predicates collect their outer references
+8. Other concerns
+8.1 Relationship with outer->inner joins converter
+8.2 Relationship with prepared statements
+8.3 Relationship with constant table detection
+9. Tests and benchmarks
</contents>
It's not really about elimination of tables, it's about elimination of inner
sides of outer joins.
-1. Conditions for removal
--------------------------
-We can eliminate an inner side of outer join if:
-1. For each record combination of outer tables, it will always produce
- exactly one record.
-2. There are no references to columns of the inner tables anywhere else in
+1. Elimination criteria
+=======================
+We can eliminate inner side of an outer join nest if:
+
+1. There are no references to columns of the inner tables anywhere else in
the query.
+2. For each record combination of outer tables, it will always produce
+ exactly one matching record combination.
+
+Most of effort in this WL entry is checking these two conditions.
-#1 means that every table inside the outer join nest is:
- - is a constant table:
- = because it can be accessed via eq_ref(const) access, or
- = it is a zero-rows or one-row MyISAM-like table [MARK1]
- - has an eq_ref access method candidate.
-
-#2 means that WHERE clause, ON clauses of embedding outer joins, ORDER BY,
- GROUP BY and HAVING do not refer to the inner tables of the outer join
- nest.
-
-1.1 Quick check if there are candidates
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Before we start to enumerate join nests, here is a quick way to check if
-there *can be* something to be removed:
+2. No outside references check
+==============================
+Criterion #1 means that the WHERE clause, ON clauses of embedding/subsequent
+outer joins, ORDER BY, GROUP BY and HAVING must have no references to inner
+tables of the outer join nest we're trying to remove.
+
+For multi-table UPDATE/DELETE we also must not remove tables that we're
+updating/deleting from or tables that are used in UPDATE's SET clause.
+
+2.1 Quick check if there are tables with no outside references
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Before we start searching for outer join nests that could be eliminated,
+we'll do a quick and cheap check if there possibly could be something that
+could be eliminated:
- if ((tables used in select_list |
+ if (there are outer joins &&
+ (tables used in select_list |
tables used in group/order by UNION |
- tables used in where) != bitmap_of_all_tables)
+ tables used in where) != bitmap_of_all_join_tables)
{
attempt table elimination;
}
-2. Removal operation properties
--------------------------------
-* There is always one way to remove (no choice to remove either this or that)
-* It is always better to remove as much tables as possible (at least within
- our cost model).
-Thus, no need for any cost calculations/etc. It's an unconditional rewrite.
-3. Removal operation
---------------------
-* Remove the outer join nest's nested join structure (i.e. get the
- outer join's TABLE_LIST object $OJ and remove it from $OJ->embedding,
- $OJ->embedding->nested_join. Update table_map's of all ancestor nested
- joins). [MARK2]
+3. One-match check
+==================
+We can eliminate inner side of outer join if it will always generate exactly
+one matching record combination.
-* Move the tables and their JOIN_TABs to front like it is done with const
- tables, with exception that if eliminated outer join nest was within
- another outer join nest, that shouldn't prevent us from moving away the
- eliminated tables.
+By definition of OUTER JOIN, a NULL-complemented record combination will be
+generated when the inner side of outer join has not produced any matches.
-* Update join->table_count and all-join-tables bitmap.
+What remains to be checked is that there is no possiblity that inner side of
+the outer join could produce more than one matching record combination.
-* That's it. Nothing else?
+We'll refer to one-match property as "functional dependency":
-4. User interface
------------------
-* We'll add an @@optimizer switch flag for table elimination. Tentative
- name: 'table_elimination'.
- (Note ^^ utility of the above questioned ^, as table elimination can never
- be worse than no elimination. We're leaning towards not adding the flag)
-
-* EXPLAIN will not show the removed tables at all. This will allow to check
- if tables were removed, and also will behave nicely with anchor model and
- VIEWs: stuff that user doesn't care about just won't be there.
+- A outer join nest is functionally dependent [wrt outer tables] if it will
+ produce one matching record combination per each record combination of
+ outer tables
-5. Tests and benchmarks
------------------------
-Create a benchmark in sql-bench which checks if the DBMS has table
-elimination.
-[According to Monty] Run
- - queries that would use elimination
- - queries that are very similar to one above (so that they would have same
- QEP, execution cost, etc) but cannot use table elimination.
-then compare run times and make a conclusion about whether dbms supports table
-elimination.
+- A table is functionally dependent wrt certain set of dependency tables, if
+ record combination of dependency tables uniquely identifies zero or one
+ matching record in the table
-6. Todo, issues to resolve
---------------------------
+- Definitions of functional dependency of keys (=column tuples) and columns are
+ apparent.
-6.1 To resolve
-~~~~~~~~~~~~~~
-- Relationship with prepared statements.
- On one hand, it's natural to desire to make table elimination a
- once-per-statement operation, like outer->inner join conversion. We'll have
- to limit the applicability by removing [MARK1] as that can change during
- lifetime of the statement.
-
- The other option is to do table elimination every time. This will require to
- rework operation [MARK2] to be undoable.
-
- I'm leaning towards doing the former. With anchor modeling, it is unlikely
- that we'll meet outer joins which have N inner tables of which some are 1-row
- MyISAM tables that do not have primary key.
-
-6.2 Resolved
-~~~~~~~~~~~~
-* outer->inner join conversion is not a problem for table elimination.
- We make outer->inner conversions based on predicates in WHERE. If the WHERE
- referred to an inner table (requirement for OJ->IJ conversion) then table
- elimination would not be applicable anyway.
-
-* For Multi-table UPDATEs/DELETEs, need to also analyze the SET clause:
- - affected tables must not be eliminated
- - tables that are used on the right side of the SET x=y assignments must
- not be eliminated either.
+Our goal is to prove that the entire join nest is functionally-dependent.
-* Aggregate functions used to report that they depend on all tables, that is,
+Join nest is functionally dependent (on the otside tables) if each of its
+elements (those can be either base tables or join nests) is functionally
+dependent.
- item_agg_func->used_tables() == (1ULL << join->tables) - 1
+Functional dependency is transitive: if table A is f-dependent on the outer
+tables and table B is f.dependent on {A, outer_tables} then B is functionally
+dependent on the outer tables.
+
+Subsequent sections list cases when we can declare a table to be
+functionally-dependent.
+
+3.1 Functional dependency source #1: Potential eq_ref access
+------------------------------------------------------------
+This is the most practically-important case. Taking the example from the HLD
+of this WL entry:
+
+ select
+ A.colA
+ from
+ tableA A
+ left outer join
+ tableB B
+ on
+ B.id = A.id;
- always. Fixed it, now aggregate function reports it depends on
- tables that its arguments depend on. In particular, COUNT(*) reports
- that it depends on no tables (item_count_star->used_tables()==0).
- One consequence of that is that "item->used_tables()==0" is not
- equivalent to "item->const_item()==true" anymore (not sure if it's
- "anymore" or this has been already happening).
-
-* EXPLAIN EXTENDED warning text was generated after the JOIN object has
- been discarded. This didn't allow to use information about join plan
- when printing the warning. Fixed this by keeping the JOIN objects until
- we've printed the warning (have also an intent to remove the const
- tables from the join output).
-
-7. Additional issues
---------------------
-* We remove ON clauses within outer join nests. If these clauses contain
- subqueries, they probably should be gone from EXPLAIN output also?
- Yes. Current approach: when removing an outer join nest, walk the ON clause
- and mark subselects as eliminated. Then let EXPLAIN code check if the
- SELECT was eliminated before the printing (EXPLAIN is generated by doing
- a recursive descent, so the check will also cause children of eliminated
- selects not to be printed)
-
-* Table elimination is performed after constant table detection (but before
- the range analysis). Constant tables are technically different from
- eliminated ones (e.g. the former are shown in EXPLAIN and the latter aren't).
- Considering we've already done the join_read_const_table() call, is there any
- real difference between constant table and eliminated one? If there is, should
- we mark const tables also as eliminated?
- from user/EXPLAIN point of view: no. constant table is the one that we read
- one record from. eliminated table is the one that we don't acccess at all.
+and generalizing it: a table TBL is functionally-dependent if the ON
+expression allows to construct a potential eq_ref access to table TBL that
+uses only outer or functionally-dependent tables.
+
+In other words: table TBL will have one match if the ON expression can be
+converted into this form
+
+ TBL.unique_key=func(one_match_tables) AND .. remainder ...
+
+(with appropriate extension for multi-part keys), where
+
+ one_match_tables= {
+ tables that are not on the inner side of the outer join in question, and
+ functionally dependent tables
+ }
+
+Note that this will cover constant tables, except those that are constant because
+they have 0/1 record or are partitioned and have no used partitions.
+
+
+3.2 Functional dependency source #2: col2=func(col1)
+----------------------------------------------------
+This comes from the second example in the HLS:
-* What is described above will not be able to eliminate this outer join
create unique index idx on tableB (id, fromDate);
...
left outer join
@@ -169,32 +152,331 @@
B.fromDate = (select max(sub.fromDate)
from tableB sub where sub.id = A.id);
- This is because condition "B.fromDate= func(tableB)" cannot be used.
- Reason#1: update_ref_and_keys() does not consider such conditions to
- be of any use (and indeed they are not usable for ref access)
- so they are not put into KEYUSE array.
- Reason#2: even if they were put there, we would need to be able to tell
- between predicates like
- B.fromDate= func(B.id) // guarantees only one matching row as
- // B.id is already bound by B.id=A.id
- // hence B.fromDate becomes bound too.
- and
- "B.fromDate= func(B.*)" // Can potentially have many matching
- // records.
- We need to
- - Have update_ref_and_keys() create KEYUSE elements for such equalities
- - Have eliminate_tables() and friends make a more accurate check.
- The right check is to check whether all parts of a unique key are bound.
- If we have keypartX to be bound, then t.keypartY=func(keypartX) makes
- keypartY to be bound.
- The difficulty here is that correlated subquery predicate cannot tell what
- columns it depends on (it only remembers tables).
- Traversing the predicate is expensive and complicated.
- We're leaning towards making each subquery predicate have a List<Item> with
- items that
- - are in the current select
- - and it depends on.
- This list will be useful in certain other subquery optimizations as well,
- it is cheap to collect it in fix_fields() phase, so it will be collected
- for every subquery predicate.
+Here it is apparent that tableB can be eliminated. It is not possible to
+construct eq_ref access to tableB, though, because for the second part of the
+primary key (fromDate column) we only got a condition in this form:
+
+ B.fromDate= func(tableB)
+
+(we write "func(tableB)" because ref optimizer can only determine which tables
+the right part of the equality depends on).
+
+In general case, equality like this doesn't guarantee functional dependency.
+For example, if func() == { return fromDate;}, i.e the ON expression is
+
+ ... ON B.id = A.id and B.fromDate = B.fromDate
+
+then that would allow table B to have multiple matches per record of table A.
+
+In order to be able to distinguish between these two cases, we'll need to go
+down to column level:
+
+- A table is functionally dependent if it has a unique key that's functionally
+ dependent
+
+- A unique key is functionally dependent when all of its columns are
+ functionally dependent
+
+- A table column is functionally dependent if the ON clause allows to extract
+ an AND-part in this form:
+
+ tbl.column = f(functionally-dependent columns or columns of outer tables)
+
+3.3 Functional dependency source #3: One or zero records in the table
+---------------------------------------------------------------------
+A table with one or zero records cannot generate more than one matching
+record. This source is of lesser importance as one/zero-record tables are only
+MyISAM tables.
+
+3.4 Functional dependency check implementation
+----------------------------------------------
+As shown above, we need something similar to KEYUSE structures, but not
+exactly that (we need things that current ref optimizer considers unusable and
+don't need things that it considers usable).
+
+3.4.1 Equality collection: Option1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We could
+- extend KEYUSE structures to store all kinds of equalities we need
+- change update_ref_and_keys() and co. to collect equalities both for ref
+ access and for table elimination
+ = [possibly] Improve [eq_]ref access to be able to use equalities in
+ form keypart2=func(keypart1)
+- process the KEYUSE array both by table elimination and by ref access
+ optimizer.
+
++ This requires less effort.
+- Code will have to be changed all over sql_select.cc
+- update_ref_and_keys() and co. already do several unrelated things. Hooking
+ up table elimination will make it even worse.
+
+3.4.2 Equality collection: Option2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Alternatively, we could process the WHERE clause totally on our own.
++ Table elimination is standalone and easy to detach module.
+- Some code duplication with update_ref_and_keys() and co.
+
+Having got the equalities, we'll to propagate functional dependency property
+to unique keys, tables and, ultimately, join nests.
+
+3.4.3 Functional dependency propagation - option 1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Borrow the approach used in constant table detection code:
+
+ do
+ {
+ converted= FALSE;
+ for each table T in join nest
+ {
+ if (check_if_functionally_dependent(T))
+ converted= TRUE;
+ }
+ } while (converted == TRUE);
+
+ check_if_functionally_dependent(T)
+ {
+ if (T has eq_ref access based on func_dep_tables)
+ return TRUE;
+
+ Apply the same do-while loop-based approach to available equalities
+ T.column1=func(other columns)
+ to spread the set of functionally-dependent columns. The goal is to get
+ all columns of a certain unique key to be bound.
+ }
+
+
+3.4.4 Functional dependency propagation - option 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Analyze the ON expression(s) and build a list of
+
+ tbl.field = expr(...)
+
+equalities. tbl here is a table that belongs to a join nest that could
+potentially be eliminated.
+
+besides those, add to the list
+ - An element for each unique key in the table that needs to be eliminated
+ - An element for each table that needs to be eliminated
+ - An element for each join nest that can be eliminated (i.e. has no
+ references from outside).
+
+Then, setup "reverse dependencies": each element should have pointers to
+elements that are functionally dependent on it:
+
+- "tbl.field=expr(...)" equality is functionally dependent on all fields that
+ are used in "expr(...)" (here we take into account only fields that belong
+ to tables that can potentially be eliminated).
+- a unique key is dependent on all of its components
+- a table is dependent on all of its unique keys
+- a join nest is dependent on all tables that it contains
+
+These pointers are stored in form of one bitmap, such that:
+
+ "X depends on Y" == test( bitmap[(X's number)*n_objects + (Y's number)] )
+
+Each object also stores a number of dependencies it needs to be satisfied
+before it itself is satisfied:
+
+- "tbl.field=expr(...)" needs all its underlying fields (if a field is
+ referenced many times it is counted only once)
+
+- a unique key needs all of its key parts
+
+- a table needs only one of its unique keys
+
+- a join nest needs all of its tables
+
+(TODO: so what do we do when we've marked a table as constant? We'll need to
+update the "field=expr(....)" elements that use fields of that table. And the
+problem is that we won't know how much to decrement from the counters of those
+elements.
+
+Solution#1: switch to table_map() based approach.
+Solution#2: introduce separate elements for each involved field.
+ field will depend on its table,
+ "field=expr" will depend on fields.
+)
+
+Besides the above, let each element have a pointer to another element, so that
+we can have a linked list of elements.
+
+After the above structures have been created, we start the main algorithm.
+
+The first step is to create a list of functionally-dependent elements. We walk
+across array of dependencies and mark those elements that are already bound
+(i.e. their dependencies are satisfied). At the moment those immediately-bound
+are only "field=expr" dependencies that don't refer to any columns that are
+not bound.
+
+The second step is the loop
+
+ while (bound_list is not empty)
+ {
+ Take the first bound element F off the list.
+ Use the bitmap to find out what other elements depended on it
+ for each such element E
+ {
+ if (E becomes bound after F is bound)
+ add E to the list;
+ }
+ }
+
+The last step is to walk through elements that represent the join nests. Those
+that are bound can be eliminated.
+
+4. Removal operation properties
+===============================
+* There is always one way to remove (no choice to remove either this or that)
+* It is always better to remove as much tables as possible (at least within
+ our cost model).
+Thus, no need for any cost calculations/etc. It's an unconditional rewrite.
+
+
+5. Removal operation
+====================
+(This depends a lot on whether we make table elimination a one-off rewrite or
+conditional)
+
+At the moment table elimination is re-done for each join re-execution, hence
+the removal operation is designed not to modify any statement's permanent
+members.
+
+* Remove the outer join nest's nested join structure (i.e. get the
+ outer join's TABLE_LIST object $OJ and remove it from $OJ->embedding,
+ $OJ->embedding->nested_join. Update table_map's of all ancestor nested
+ joins). [MARK2]
+
+* Move the tables and their JOIN_TABs to the front of join order, like it is
+ done with const tables, with exception that if eliminated outer join nest
+ was within another outer join nest, that shouldn't prevent us from moving
+ away the eliminated tables.
+
+* Update join->table_count and all-join-tables bitmap.
+ ^ TODO: not true anymore ^
+
+* That's it. Nothing else?
+
+6. User interface
+=================
+
+6.1 @@optimizer_switch flag
+---------------------------
+Argument againist adding the flag:
+* It is always better to perform table elimination than not to do it.
+
+Arguments for the flag:
+* It is always theoretically possible that the new code will cause unintended
+ slowdowns.
+* Having the flag is useful for QA and comparative benchmarking.
+
+Decision so far: add the flag under #ifdef. Make the flag be present in debug
+builds.
+
+6.2 EXPLAIN [EXTENDED]
+----------------------
+There are two possible options:
+1. Show eliminated tables, like we do with const tables.
+2. Do not show eliminated tables.
+
+We chose option 2, because:
+- the table is not accessed at all (besides locking it)
+- it is more natural for anchor model user - when he's querying an anchor-
+ and attributes view, he doesn't care about the unused attributes.
+
+EXPLAIN EXTENDED+SHOW WARNINGS won't show the removed table either.
+
+NOTE: Before this WL, the warning text was generated after all JOIN objects
+have been destroyed. This didn't allow to use information about join plan
+when printing the warning. We've fixed this by keeping the JOIN objects until
+the warning text has been generated.
+
+Table elimination removes inner sides of outer join, and logically the ON
+clause is also removed. If this clause has any subqueries, they will be
+also removed from EXPLAIN output.
+
+An exception to the above is that if we eliminate a derived table, it will
+still be shown in EXPLAIN output. This comes from the fact that the FROM
+subqueries are evaluated before table elimination is invoked.
+TODO: Is the above ok or still remove parts of FROM subqueries?
+
+7. Miscellaneous adjustments
+============================
+
+7.1 Fix used_tables() of aggregate functions
+--------------------------------------------
+Aggregate functions used to report that they depend on all tables, that is,
+
+ item_agg_func->used_tables() == (1ULL << join->tables) - 1
+
+always. Fixed it, now aggregate function reports that it depends on the
+tables that its arguments depend on. In particular, COUNT(*) reports that it
+depends on no tables (item_count_star->used_tables()==0). One consequence of
+that is that "item->used_tables()==0" is not equivalent to
+"item->const_item()==true" anymore (not sure if it's "anymore" or this has
+been already so for some items).
+
+7.2 Make subquery predicates collect their outer references
+-----------------------------------------------------------
+Per-column functional dependency analysis requires us to take a
+
+ tbl.field = func(...)
+
+equality and tell which columns of which tables are referred from func(...)
+expression. For scalar expressions, this is accomplished by Item::walk()-based
+traversal. It should be reasonably cheap (the only practical Item that can be
+expensive to traverse seems to be a special case of "col IN (const1,const2,
+...)". check if we traverse the long list for such items).
+
+For correlated subqueries, traversal can be expensive, it is cheaper to make
+each subquery item have a list of its outer references. The list can be
+collected at fix_fields() stage with very little extra cost, and then it could
+be used for other optimizations.
+
+
+8. Other concerns
+=================
+
+8.1 Relationship with outer->inner joins converter
+--------------------------------------------------
+One could suspect that outer->inner join conversion could get in the way
+of table elimination by changing outer joins (which could be eliminated)
+to inner (which we will not try to eliminate).
+This concern is not valid: we make outer->inner conversions based on
+predicates in WHERE. If the WHERE referred to an inner table (this is a
+requirement for the conversion) then table elimination would not be
+applicable anyway.
+
+8.2 Relationship with prepared statements
+-----------------------------------------
+On one hand, it's natural to desire to make table elimination a
+once-per-statement operation, like outer->inner join conversion. We'll have
+to limit the applicability by removing [MARK1] as that can change during
+lifetime of the statement.
+
+The other option is to do table elimination every time. This will require to
+rework operation [MARK2] to be undoable.
+
+
+8.3 Relationship with constant table detection
+----------------------------------------------
+Table elimination is performed after constant table detection (but before
+the range analysis). Constant tables are technically different from
+eliminated ones (e.g. the former are shown in EXPLAIN and the latter aren't).
+Considering we've already done the join_read_const_table() call, is there any
+real difference between constant table and eliminated one? If there is, should
+we mark const tables also as eliminated?
+from user/EXPLAIN point of view: no. constant table is the one that we read
+one record from. eliminated table is the one that we don't acccess at all.
+TODO
+
+9. Tests and benchmarks
+=======================
+Create a benchmark in sql-bench which checks if the DBMS has table
+elimination.
+[According to Monty] Run
+ - query Q1 that would use elimination
+ - query Q2 that is very similar to Q1 (so that they would have same
+ QEP, execution cost, etc) but cannot use table elimination.
+then compare run times and make a conclusion about whether the used dbms
+supports table elimination.
-=-=(Guest - Thu, 23 Jul 2009, 20:07)=-=-
Dependency created: 29 now depends on 17
-=-=(Monty - Thu, 23 Jul 2009, 09:19)=-=-
Version updated.
--- /tmp/wklog.17.old.24090 2009-07-23 09:19:32.000000000 +0300
+++ /tmp/wklog.17.new.24090 2009-07-23 09:19:32.000000000 +0300
@@ -1 +1 @@
-Server-9.x
+Server-5.1
-=-=(Guest - Mon, 20 Jul 2009, 14:28)=-=-
deukje weg
Worked 1 hour and estimate 3 hours remain (original estimate increased by 4 hours).
------------------------------------------------------------
-=-=(View All Progress Notes, 32 total)=-=-
http://askmonty.org/worklog/index.pl?tid=17&nolimit=1
DESCRIPTION:
Eliminate not needed tables from SELECT queries..
This will speed up some views and automatically generated queries.
Example:
CREATE TABLE B (id int primary key);
select
A.colA
from
tableA A
left outer join
tableB B
on
B.id = A.id;
In this case we can remove table B and the join from the query.
HIGH-LEVEL SPECIFICATION:
Here is an extended explanation of table elimination.
Table elimination is a feature found in some modern query optimizers, of
which Microsoft SQL Server 2005/2008 seems to have the most advanced
implementation. Oracle 11g has also been confirmed to use table
elimination but not to the same extent.
Basically, what table elimination does, is to remove tables from the
execution plan when it is unnecessary to include them. This can, of
course, only happen if the right circumstances arise. Let us for example
look at the following query:
select
A.colA
from
tableA A
left outer join
tableB B
on
B.id = A.id;
When using A as the left table we ensure that the query will return at
least as many rows as there are in that table. For rows where the join
condition (B.id = A.id) is not met the selected column (A.colA) will
still contain it's original value. The not seen B.* row would contain all NULL:s.
However, the result set could actually contain more rows than what is
found in tableA if there are duplicates of the column B.id in tableB. If
A contains a row [1, "val1"] and B the rows [1, "other1a"],[1, "other1b"]
then two rows will match in the join condition. The only way to know
what the result will look like is to actually touch both tables during
execution.
Instead, let's say that tableB contains rows that make it possible to
place a unique constraint on the column B.id, for example and often the
case a primary key. In this situation we know that we will get exactly
as many rows as there are in tableA, since joining with tableB cannot
introduce any duplicates. If further, as in the example query, we do not
select any columns from tableB, touching that table during execution is
unnecessary. We can remove the whole join operation from the execution
plan.
Both SQL Server 2005/2008 and Oracle 11g will deploy table elimination
in the case described above. Let us look at a more advanced query, where
Oracle fails.
select
A.colA
from
tableA A
left outer join
tableB B
on
B.id = A.id
and
B.fromDate = (
select
max(sub.fromDate)
from
tableB sub
where
sub.id = A.id
);
In this example we have added another join condition, which ensures
that we only pick the matching row from tableB having the latest
fromDate. In this case tableB will contain duplicates of the column
B.id, so in order to ensure uniqueness the primary key has to contain
the fromDate column as well. In other words the primary key of tableB
is (B.id, B.fromDate).
Furthermore, since the subselect ensures that we only pick the latest
B.fromDate for a given B.id we know that at most one row will match
the join condition. We will again have the situation where joining
with tableB cannot affect the number of rows in the result set. Since
we do not select any columns from tableB, the whole join operation can
be eliminated from the execution plan.
SQL Server 2005/2008 will deploy table elimination in this situation as
well. We have not found a way to make Oracle 11g use it for this type of
query. Queries like these arise in two situations. Either when you have
denormalized model consisting of a fact table with several related
dimension tables, or when you have a highly normalized model where each
attribute is stored in its own table. The example with the subselect is
common whenever you store historized/versioned data.
LOW-LEVEL DESIGN:
The code (currently in development) is at lp:
~maria-captains/maria/maria-5.1-table-elimination tree.
<contents>
1. Elimination criteria
2. No outside references check
2.1 Quick check if there are tables with no outside references
3. One-match check
3.1 Functional dependency source #1: Potential eq_ref access
3.2 Functional dependency source #2: col2=func(col1)
3.3 Functional dependency source #3: One or zero records in the table
3.4 Functional dependency check implementation
3.4.1 Equality collection: Option1
3.4.2 Equality collection: Option2
3.4.3 Functional dependency propagation - option 1
3.4.4 Functional dependency propagation - option 2
4. Removal operation properties
5. Removal operation
6. User interface
6.1 @@optimizer_switch flag
6.2 EXPLAIN [EXTENDED]
7. Miscellaneous adjustments
7.1 Fix used_tables() of aggregate functions
7.2 Make subquery predicates collect their outer references
8. Other concerns
8.1 Relationship with outer->inner joins converter
8.2 Relationship with prepared statements
8.3 Relationship with constant table detection
9. Tests and benchmarks
</contents>
It's not really about elimination of tables, it's about elimination of inner
sides of outer joins.
1. Elimination criteria
=======================
We can eliminate inner side of an outer join nest if:
1. There are no references to columns of the inner tables anywhere else in
the query.
2. For each record combination of outer tables, it will always produce
exactly one matching record combination.
Most of effort in this WL entry is checking these two conditions.
2. No outside references check
==============================
Criterion #1 means that the WHERE clause, ON clauses of embedding/subsequent
outer joins, ORDER BY, GROUP BY and HAVING must have no references to inner
tables of the outer join nest we're trying to remove.
For multi-table UPDATE/DELETE we also must not remove tables that we're
updating/deleting from or tables that are used in UPDATE's SET clause.
2.1 Quick check if there are tables with no outside references
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before we start searching for outer join nests that could be eliminated,
we'll do a quick and cheap check if there possibly could be something that
could be eliminated:
if (there are outer joins &&
(tables used in select_list |
tables used in group/order by UNION |
tables used in where) != bitmap_of_all_join_tables)
{
attempt table elimination;
}
3. One-match check
==================
We can eliminate inner side of outer join if it will always generate exactly
one matching record combination.
By definition of OUTER JOIN, a NULL-complemented record combination will be
generated when the inner side of outer join has not produced any matches.
What remains to be checked is that there is no possiblity that inner side of
the outer join could produce more than one matching record combination.
We'll refer to one-match property as "functional dependency":
- A outer join nest is functionally dependent [wrt outer tables] if it will
produce one matching record combination per each record combination of
outer tables
- A table is functionally dependent wrt certain set of dependency tables, if
record combination of dependency tables uniquely identifies zero or one
matching record in the table
- Definitions of functional dependency of keys (=column tuples) and columns are
apparent.
Our goal is to prove that the entire join nest is functionally-dependent.
Join nest is functionally dependent (on the otside tables) if each of its
elements (those can be either base tables or join nests) is functionally
dependent.
Functional dependency is transitive: if table A is f-dependent on the outer
tables and table B is f.dependent on {A, outer_tables} then B is functionally
dependent on the outer tables.
Subsequent sections list cases when we can declare a table to be
functionally-dependent.
3.1 Functional dependency source #1: Potential eq_ref access
------------------------------------------------------------
This is the most practically-important case. Taking the example from the HLD
of this WL entry:
select
A.colA
from
tableA A
left outer join
tableB B
on
B.id = A.id;
and generalizing it: a table TBL is functionally-dependent if the ON
expression allows to construct a potential eq_ref access to table TBL that
uses only outer or functionally-dependent tables.
In other words: table TBL will have one match if the ON expression can be
converted into this form
TBL.unique_key=func(one_match_tables) AND .. remainder ...
(with appropriate extension for multi-part keys), where
one_match_tables= {
tables that are not on the inner side of the outer join in question, and
functionally dependent tables
}
Note that this will cover constant tables, except those that are constant because
they have 0/1 record or are partitioned and have no used partitions.
3.2 Functional dependency source #2: col2=func(col1)
----------------------------------------------------
This comes from the second example in the HLS:
create unique index idx on tableB (id, fromDate);
...
left outer join
tableB B
on
B.id = A.id
and
B.fromDate = (select max(sub.fromDate)
from tableB sub where sub.id = A.id);
Here it is apparent that tableB can be eliminated. It is not possible to
construct eq_ref access to tableB, though, because for the second part of the
primary key (fromDate column) we only got a condition in this form:
B.fromDate= func(tableB)
(we write "func(tableB)" because ref optimizer can only determine which tables
the right part of the equality depends on).
In general case, equality like this doesn't guarantee functional dependency.
For example, if func() == { return fromDate;}, i.e the ON expression is
... ON B.id = A.id and B.fromDate = B.fromDate
then that would allow table B to have multiple matches per record of table A.
In order to be able to distinguish between these two cases, we'll need to go
down to column level:
- A table is functionally dependent if it has a unique key that's functionally
dependent
- A unique key is functionally dependent when all of its columns are
functionally dependent
- A table column is functionally dependent if the ON clause allows to extract
an AND-part in this form:
tbl.column = f(functionally-dependent columns or columns of outer tables)
3.3 Functional dependency source #3: One or zero records in the table
---------------------------------------------------------------------
A table with one or zero records cannot generate more than one matching
record. This source is of lesser importance as one/zero-record tables are only
MyISAM tables.
3.4 Functional dependency check implementation
----------------------------------------------
As shown above, we need something similar to KEYUSE structures, but not
exactly that (we need things that current ref optimizer considers unusable and
don't need things that it considers usable).
3.4.1 Equality collection: Option1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We could
- extend KEYUSE structures to store all kinds of equalities we need
- change update_ref_and_keys() and co. to collect equalities both for ref
access and for table elimination
= [possibly] Improve [eq_]ref access to be able to use equalities in
form keypart2=func(keypart1)
- process the KEYUSE array both by table elimination and by ref access
optimizer.
+ This requires less effort.
- Code will have to be changed all over sql_select.cc
- update_ref_and_keys() and co. already do several unrelated things. Hooking
up table elimination will make it even worse.
3.4.2 Equality collection: Option2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alternatively, we could process the WHERE clause totally on our own.
+ Table elimination is standalone and easy to detach module.
- Some code duplication with update_ref_and_keys() and co.
Having got the equalities, we'll to propagate functional dependency property
to unique keys, tables and, ultimately, join nests.
3.4.3 Functional dependency propagation - option 1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Borrow the approach used in constant table detection code:
do
{
converted= FALSE;
for each table T in join nest
{
if (check_if_functionally_dependent(T))
converted= TRUE;
}
} while (converted == TRUE);
check_if_functionally_dependent(T)
{
if (T has eq_ref access based on func_dep_tables)
return TRUE;
Apply the same do-while loop-based approach to available equalities
T.column1=func(other columns)
to spread the set of functionally-dependent columns. The goal is to get
all columns of a certain unique key to be bound.
}
3.4.4 Functional dependency propagation - option 2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Analyze the ON expression(s) and build a list of
tbl.field = expr(...)
equalities. tbl here is a table that belongs to a join nest that could
potentially be eliminated.
besides those, add to the list
- An element for each unique key in the table that needs to be eliminated
- An element for each table that needs to be eliminated
- An element for each join nest that can be eliminated (i.e. has no
references from outside).
Then, setup "reverse dependencies": each element should have pointers to
elements that are functionally dependent on it:
- "tbl.field=expr(...)" equality is functionally dependent on all fields that
are used in "expr(...)" (here we take into account only fields that belong
to tables that can potentially be eliminated).
- a unique key is dependent on all of its components
- a table is dependent on all of its unique keys
- a join nest is dependent on all tables that it contains
These pointers are stored in form of one bitmap, such that:
"X depends on Y" == test( bitmap[(X's number)*n_objects + (Y's number)] )
Each object also stores a number of dependencies it needs to be satisfied
before it itself is satisfied:
- "tbl.field=expr(...)" needs all its underlying fields (if a field is
referenced many times it is counted only once)
- a unique key needs all of its key parts
- a table needs only one of its unique keys
- a join nest needs all of its tables
(TODO: so what do we do when we've marked a table as constant? We'll need to
update the "field=expr(....)" elements that use fields of that table. And the
problem is that we won't know how much to decrement from the counters of those
elements.
Solution#1: switch to table_map() based approach.
Solution#2: introduce separate elements for each involved field.
field will depend on its table,
"field=expr" will depend on fields.
)
Besides the above, let each element have a pointer to another element, so that
we can have a linked list of elements.
After the above structures have been created, we start the main algorithm.
The first step is to create a list of functionally-dependent elements. We walk
across array of dependencies and mark those elements that are already bound
(i.e. their dependencies are satisfied). At the moment those immediately-bound
are only "field=expr" dependencies that don't refer to any columns that are
not bound.
The second step is the loop
while (bound_list is not empty)
{
Take the first bound element F off the list.
Use the bitmap to find out what other elements depended on it
for each such element E
{
if (E becomes bound after F is bound)
add E to the list;
}
}
The last step is to walk through elements that represent the join nests. Those
that are bound can be eliminated.
4. Removal operation properties
===============================
* There is always one way to remove (no choice to remove either this or that)
* It is always better to remove as much tables as possible (at least within
our cost model).
Thus, no need for any cost calculations/etc. It's an unconditional rewrite.
5. Removal operation
====================
(This depends a lot on whether we make table elimination a one-off rewrite or
conditional)
At the moment table elimination is re-done for each join re-execution, hence
the removal operation is designed not to modify any statement's permanent
members.
* Remove the outer join nest's nested join structure (i.e. get the
outer join's TABLE_LIST object $OJ and remove it from $OJ->embedding,
$OJ->embedding->nested_join. Update table_map's of all ancestor nested
joins). [MARK2]
* Move the tables and their JOIN_TABs to the front of join order, like it is
done with const tables, with exception that if eliminated outer join nest
was within another outer join nest, that shouldn't prevent us from moving
away the eliminated tables.
* Update join->table_count and all-join-tables bitmap.
^ TODO: not true anymore ^
* That's it. Nothing else?
6. User interface
=================
6.1 @@optimizer_switch flag
---------------------------
Argument againist adding the flag:
* It is always better to perform table elimination than not to do it.
Arguments for the flag:
* It is always theoretically possible that the new code will cause unintended
slowdowns.
* Having the flag is useful for QA and comparative benchmarking.
Decision so far: add the flag under #ifdef. Make the flag be present in debug
builds.
6.2 EXPLAIN [EXTENDED]
----------------------
There are two possible options:
1. Show eliminated tables, like we do with const tables.
2. Do not show eliminated tables.
We chose option 2, because:
- the table is not accessed at all (besides locking it)
- it is more natural for anchor model user - when he's querying an anchor-
and attributes view, he doesn't care about the unused attributes.
EXPLAIN EXTENDED+SHOW WARNINGS won't show the removed table either.
NOTE: Before this WL, the warning text was generated after all JOIN objects
have been destroyed. This didn't allow to use information about join plan
when printing the warning. We've fixed this by keeping the JOIN objects until
the warning text has been generated.
Table elimination removes inner sides of outer join, and logically the ON
clause is also removed. If this clause has any subqueries, they will be
also removed from EXPLAIN output.
An exception to the above is that if we eliminate a derived table, it will
still be shown in EXPLAIN output. This comes from the fact that the FROM
subqueries are evaluated before table elimination is invoked.
TODO: Is the above ok or still remove parts of FROM subqueries?
7. Miscellaneous adjustments
============================
7.1 Fix used_tables() of aggregate functions
--------------------------------------------
Aggregate functions used to report that they depend on all tables, that is,
item_agg_func->used_tables() == (1ULL << join->tables) - 1
always. Fixed it, now aggregate function reports that it depends on the
tables that its arguments depend on. In particular, COUNT(*) reports that it
depends on no tables (item_count_star->used_tables()==0). One consequence of
that is that "item->used_tables()==0" is not equivalent to
"item->const_item()==true" anymore (not sure if it's "anymore" or this has
been already so for some items).
7.2 Make subquery predicates collect their outer references
-----------------------------------------------------------
Per-column functional dependency analysis requires us to take a
tbl.field = func(...)
equality and tell which columns of which tables are referred from func(...)
expression. For scalar expressions, this is accomplished by Item::walk()-based
traversal. It should be reasonably cheap (the only practical Item that can be
expensive to traverse seems to be a special case of "col IN (const1,const2,
...)". check if we traverse the long list for such items).
For correlated subqueries, traversal can be expensive, it is cheaper to make
each subquery item have a list of its outer references. The list can be
collected at fix_fields() stage with very little extra cost, and then it could
be used for other optimizations.
8. Other concerns
=================
8.1 Relationship with outer->inner joins converter
--------------------------------------------------
One could suspect that outer->inner join conversion could get in the way
of table elimination by changing outer joins (which could be eliminated)
to inner (which we will not try to eliminate).
This concern is not valid: we make outer->inner conversions based on
predicates in WHERE. If the WHERE referred to an inner table (this is a
requirement for the conversion) then table elimination would not be
applicable anyway.
8.2 Relationship with prepared statements
-----------------------------------------
On one hand, it's natural to desire to make table elimination a
once-per-statement operation, like outer->inner join conversion. We'll have
to limit the applicability by removing [MARK1] as that can change during
lifetime of the statement.
The other option is to do table elimination every time. This will require to
rework operation [MARK2] to be undoable.
8.3 Relationship with constant table detection
----------------------------------------------
Table elimination is performed after constant table detection (but before
the range analysis). Constant tables are technically different from
eliminated ones (e.g. the former are shown in EXPLAIN and the latter aren't).
Considering we've already done the join_read_const_table() call, is there any
real difference between constant table and eliminated one? If there is, should
we mark const tables also as eliminated?
from user/EXPLAIN point of view: no. constant table is the one that we read
one record from. eliminated table is the one that we don't acccess at all.
TODO
9. Tests and benchmarks
=======================
Create a benchmark in sql-bench which checks if the DBMS has table
elimination.
[According to Monty] Run
- query Q1 that would use elimination
- query Q2 that is very similar to Q1 (so that they would have same
QEP, execution cost, etc) but cannot use table elimination.
then compare run times and make a conclusion about whether the used dbms
supports table elimination.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2746)
by Igor Babaev 31 Mar '10
by Igor Babaev 31 Mar '10
31 Mar '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100331231003-9gvmv2y8384kbqfa
2746 Igor Babaev 2010-03-31
Made the results of the key_cache test to be platform independent.
modified:
mysql-test/r/key_cache.result
mysql-test/t/key_cache.test
=== modified file 'mysql-test/r/key_cache.result'
--- a/mysql-test/r/key_cache.result 2010-03-31 18:45:41 +0000
+++ b/mysql-test/r/key_cache.result 2010-03-31 23:37:28 +0000
@@ -388,7 +388,7 @@ i int, a char(10), key k1(i), key k2(a))
select @@key_cache_partitions;
@@key_cache_partitions
0
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
@@ -416,18 +416,18 @@ Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t2 where a='zzzz';
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 29 0 32 9
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 29 0 32 9
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
@@ -435,10 +435,8 @@ set global key_cache_partitions=2;
select @@key_cache_partitions;
@@key_cache_partitions
2
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 0 # 0 0 0 0 0
-default 2 2 1048576 1024 0 # 0 0 0 0 0
default 2 NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
@@ -465,27 +463,22 @@ Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 # # 0 10 0 13 4
-default 2 2 1048576 1024 # # 0 12 0 13 2
-default 2 NULL 2097152 1024 # # 0 22 0 26 6
-small NULL NULL 1048576 1024 # # 0 1 0 2 1
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 # # 0 10 0 13 4
-default 2 2 1048576 1024 # # 0 12 0 13 2
-default 2 NULL 2097152 1024 # # 0 22 0 26 6
-small NULL NULL 1048576 1024 # # 0 1 0 2 1
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
set global key_cache_partitions=1;
select @@key_cache_partitions;
@@key_cache_partitions
1
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 0 # 0 0 0 0 0
default 1 NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
@@ -512,23 +505,20 @@ Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 4 # 0 22 0 26 6
default 1 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 4 # 0 22 0 26 6
default 1 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
flush tables;
flush status;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 4 # 0 0 0 0 0
default 1 NULL 2097152 1024 4 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
set global key_buffer_size=32*1024;
@@ -539,10 +529,8 @@ set global key_cache_partitions=2;
select @@key_cache_partitions;
@@key_cache_partitions
2
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 0 # 0 0 0 0 0
-default 2 2 16384 1024 0 # 0 0 0 0 0
default 2 NULL 32768 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
@@ -560,10 +548,8 @@ p i a
4 3 zzzz
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 1 # 0 12 0 13 2
-default 2 2 16384 1024 3 # 0 10 0 13 4
default 2 NULL 32768 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
insert into t1(a) select a from t1;
@@ -582,10 +568,8 @@ insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 1951 # 1976 43
-default 2 2 16384 1024 # # 0 4782 # 1708 60
default 2 NULL 32768 1024 # # 0 6733 # 3684 103
small NULL NULL 1048576 1024 # # 0 0 # 0 0
select * from t1 where p between 1010 and 1020 ;
@@ -603,20 +587,16 @@ p i a
1018 2 pppp
1019 2 yyyy
1020 3 zzzz
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 1954 # 1976 43
-default 2 2 16384 1024 # # 0 4796 # 1708 60
default 2 NULL 32768 1024 # # 0 6750 # 3684 103
small NULL NULL 1048576 1024 # # 0 0 # 0 0
flush tables;
flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 940 10 939 10
-default 2 2 16384 1024 # # 0 2136 8 613 8
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=256*1024;
@@ -627,29 +607,14 @@ set global keycache1.key_cache_partition
select @@keycache1.key_cache_partitions;
@@keycache1.key_cache_partitions
7
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 940 10 939 10
-default 2 2 16384 1024 # # 0 2136 8 613 8
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 0 0 0 0
-keycache1 7 2 37449 2048 # # 0 0 0 0 0
-keycache1 7 3 37449 2048 # # 0 0 0 0 0
-keycache1 7 4 37449 2048 # # 0 0 0 0 0
-keycache1 7 5 37449 2048 # # 0 0 0 0 0
-keycache1 7 6 37449 2048 # # 0 0 0 0 0
-keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 0 0 0 0
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 0 # 0 0 0 0 0
-keycache1 7 2 37449 2048 0 # 0 0 0 0 0
-keycache1 7 3 37449 2048 0 # 0 0 0 0 0
-keycache1 7 4 37449 2048 0 # 0 0 0 0 0
-keycache1 7 5 37449 2048 0 # 0 0 0 0 0
-keycache1 7 6 37449 2048 0 # 0 0 0 0 0
-keycache1 7 7 37449 2048 0 # 0 0 0 0 0
keycache1 7 NULL 262143 2048 0 # 0 0 0 0 0
cache index t1 key (`primary`) in keycache1;
Table Op Msg_type Msg_text
@@ -682,61 +647,35 @@ id select_type table type possible_keys
select count(*) from t1, t2 where t1.p = t2.i;
count(*)
256
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 2 1 0 0
-keycache1 7 2 37449 2048 # # 0 7 1 0 0
-keycache1 7 3 37449 2048 # # 0 0 0 0 0
-keycache1 7 4 37449 2048 # # 0 5 1 0 0
-keycache1 7 5 37449 2048 # # 0 0 0 0 0
-keycache1 7 6 37449 2048 # # 0 0 0 0 0
-keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 14 3 0 0
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 1 # 0 2 1 0 0
-keycache1 7 2 37449 2048 1 # 0 7 1 0 0
-keycache1 7 3 37449 2048 0 # 0 0 0 0 0
-keycache1 7 4 37449 2048 1 # 0 5 1 0 0
-keycache1 7 5 37449 2048 0 # 0 0 0 0 0
-keycache1 7 6 37449 2048 0 # 0 0 0 0 0
-keycache1 7 7 37449 2048 0 # 0 0 0 0 0
keycache1 7 NULL 262143 2048 3 # 0 14 3 0 0
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+3000, i=2 where a='qqqq';
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 3 # 0 44 3 43 2
-keycache1 7 2 37449 2048 4 # 0 61 4 51 1
-keycache1 7 3 37449 2048 4 # 0 177 4 176 3
-keycache1 7 4 37449 2048 4 # 0 122 4 119 3
-keycache1 7 5 37449 2048 4 # 0 840 4 335 4
-keycache1 7 6 37449 2048 3 # 0 627 3 133 3
-keycache1 7 7 37449 2048 3 # 0 211 3 214 3
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy');
-select * from information_schema.key_caches where key_cache_name like "keycache2";
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 3 # 0 44 3 43 2
-keycache1 7 2 37449 2048 4 # 0 61 4 51 1
-keycache1 7 3 37449 2048 4 # 0 177 4 176 3
-keycache1 7 4 37449 2048 4 # 0 122 4 119 3
-keycache1 7 5 37449 2048 4 # 0 840 4 335 4
-keycache1 7 6 37449 2048 3 # 0 627 3 133 3
-keycache1 7 7 37449 2048 3 # 0 211 3 214 3
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
cache index t2 in keycache1;
@@ -774,127 +713,77 @@ id select_type table type possible_keys
select a from t2 where a='yyyy' and i=3 ;
a
yyyy
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 85 6 68 3
-keycache1 7 2 37449 2048 # # 0 122 6 102 2
-keycache1 7 3 37449 2048 # # 0 271 8 254 6
-keycache1 7 4 37449 2048 # # 0 179 6 170 4
-keycache1 7 5 37449 2048 # # 0 1445 7 416 6
-keycache1 7 6 37449 2048 # # 0 863 6 345 5
-keycache1 7 7 37449 2048 # # 0 236 4 239 4
keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 1 1 1 1
-keycache1 7 2 37449 2048 # # 0 1 1 0 0
-keycache1 7 3 37449 2048 # # 0 0 0 0 0
-keycache1 7 4 37449 2048 # # 0 1 1 1 1
-keycache1 7 5 37449 2048 # # 0 1 1 0 0
-keycache1 7 6 37449 2048 # # 0 2 2 1 1
-keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 3 1 87381 8192 # # 0 1 1 1 1
-keycache1 3 2 87381 8192 # # 0 3 2 1 1
-keycache1 3 3 87381 8192 # # 0 2 2 1 1
keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=64*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=2*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 3 1 21845 2048 # # 0 0 0 0 0
-keycache1 3 2 21845 2048 # # 0 0 0 0 0
-keycache1 3 3 21845 2048 # # 0 0 0 0 0
keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=0;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=0;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=128*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 1 1 131072 8192 # # 0 0 0 0 0
keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 18724 1024 # # 0 0 0 0 0
-keycache1 7 2 18724 1024 # # 0 0 0 0 0
-keycache1 7 3 18724 1024 # # 0 0 0 0 0
-keycache1 7 4 18724 1024 # # 0 0 0 0 0
-keycache1 7 5 18724 1024 # # 0 0 0 0 0
-keycache1 7 6 18724 1024 # # 0 0 0 0 0
-keycache1 7 7 18724 1024 # # 0 0 0 0 0
keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
drop table t1,t2;
=== modified file 'mysql-test/t/key_cache.test'
--- a/mysql-test/t/key_cache.test 2010-03-31 18:45:41 +0000
+++ b/mysql-test/t/key_cache.test 2010-03-31 23:37:28 +0000
@@ -272,7 +272,7 @@ create table t2 (
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -285,16 +285,16 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
delete from t2 where a='zzzz';
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# For the key cache with 2 partitions execute the same sequence of
# statements as for the simple cache above.
@@ -304,7 +304,7 @@ select * from information_schema.key_cac
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -316,20 +316,20 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
---replace_column 6 # 7 #
-select * from information_schema.key_caches;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
---replace_column 6 # 7 #
-select * from information_schema.key_caches;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
# Check that we can work with one partition with the same results
set global key_cache_partitions=1;
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -342,16 +342,16 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
flush tables; flush status;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# Switch back to 2 partitions
@@ -360,7 +360,7 @@ select @@key_buffer_size;
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -371,7 +371,7 @@ update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# Add more rows to tables t1 and t2
@@ -394,18 +394,18 @@ insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
--replace_column 6 # 7 # 10 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
select * from t1 where p between 1010 and 1020 ;
select * from t2 where p between 1010 and 1020 ;
--replace_column 6 # 7 # 10 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
flush tables; flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# Now test how we can work with 7 partitions
@@ -415,9 +415,10 @@ set global keycache1.key_cache_partition
select @@keycache1.key_cache_partitions;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
cache index t1 key (`primary`) in keycache1;
@@ -429,22 +430,26 @@ explain select count(*) from t1, t2 wher
select count(*) from t1, t2 where t1.p = t2.i;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
cache index t2 in keycache1;
update t2 set p=p+3000, i=2 where a='qqqq';
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
insert into t2 values (2000, 3, 'yyyy');
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "keycache2";
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and partition_number is null;
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
cache index t2 in keycache1;
update t2 set p=p+5000 where a='zzzz';
@@ -456,49 +461,49 @@ select i from t2 where a='yyyy' and i=3;
explain select a from t2 where a='yyyy' and i=3;
select a from t2 where a='yyyy' and i=3 ;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=64*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=2*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=128*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
drop table t1,t2;
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2745)
by Igor Babaev 31 Mar '10
by Igor Babaev 31 Mar '10
31 Mar '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100331184541-cigkg2yokjzve1mk
2745 Igor Babaev 2010-03-31 [merge]
Merge with the latest changes og 5.2.
removed:
include/mysql/plugin.h.pp
added:
include/mysql/client_plugin.h
include/mysql/client_plugin.h.pp
include/mysql/plugin_auth.h
include/mysql/plugin_auth.h.pp
include/mysql/plugin_auth_common.h
plugin/auth/
plugin/auth/Makefile.am
plugin/auth/auth_socket.c
plugin/auth/dialog.c
plugin/auth/plug.in
sql-common/client_plugin.c
modified:
.bzrignore
Makefile.am
client/CMakeLists.txt
client/Makefile.am
client/client_priv.h
client/mysql.cc
client/mysqltest.cc
config/ac-macros/plugins.m4
configure.in
include/Makefile.am
include/errmsg.h
include/m_ctype.h
include/my_global.h
include/my_no_pthread.h
include/my_sys.h
include/mysql.h
include/mysql.h.pp
include/mysql/plugin.h
include/mysql_com.h
include/sql_common.h
libmysql/CMakeLists.txt
libmysql/Makefile.shared
libmysql/client_settings.h
libmysql/errmsg.c
libmysql/libmysql.c
libmysqld/Makefile.am
libmysqld/embedded_priv.h
libmysqld/lib_sql.cc
libmysqld/libmysqld.c
mysql-test/mysql-test-run.pl
mysql-test/r/change_user.result
mysql-test/r/grant.result
mysql-test/r/grant2.result
mysql-test/r/ps.result
mysql-test/r/sp_notembedded.result
mysql-test/r/system_mysql_db.result
mysql-test/suite/funcs_1/r/is_columns_mysql.result
mysql-test/suite/funcs_1/r/is_user_privileges.result
mysql-test/suite/pbxt/r/grant.result
mysql-test/suite/rpl/r/rpl_ignore_table.result
mysql-test/suite/rpl/r/rpl_stm_000001.result
mysql-test/t/change_user.test
mysql-test/valgrind.supp
mysys/Makefile.am
scripts/mysql_system_tables.sql
scripts/mysql_system_tables_data.sql
scripts/mysql_system_tables_fix.sql
server-tools/instance-manager/Makefile.am
server-tools/instance-manager/user_map.cc
sql-common/Makefile.am
sql-common/client.c
sql/CMakeLists.txt
sql/Makefile.am
sql/client_settings.h
sql/ha_ndbcluster.cc
sql/ha_ndbcluster_binlog.cc
sql/lex.h
sql/mysql_priv.h
sql/mysqld.cc
sql/password.c
sql/protocol.cc
sql/protocol.h
sql/sql_acl.cc
sql/sql_acl.h
sql/sql_builtin.cc.in
sql/sql_class.cc
sql/sql_class.h
sql/sql_connect.cc
sql/sql_insert.cc
sql/sql_lex.h
sql/sql_parse.cc
sql/sql_plugin.cc
sql/sql_yacc.yy
sql/structs.h
sql/table.cc
storage/maria/ma_loghandler.c
storage/pbxt/src/ha_pbxt.cc
tests/mysql_client_test.c
=== modified file '.bzrignore'
--- a/.bzrignore 2010-02-01 06:14:12 +0000
+++ b/.bzrignore 2010-03-29 15:13:53 +0000
@@ -1931,3 +1931,6 @@ client/rpl_filter.cc
client/rpl_filter.h
client/sql_list.cc
client/sql_list.h
+libmysqld/client_plugin.c
+sql/client_plugin.c
+*.dgcov
=== modified file 'Makefile.am'
--- a/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/Makefile.am 2010-03-29 15:13:53 +0000
@@ -140,14 +140,14 @@ smoke:
test-full: test test-nr test-ps
test-force:
- $(MAKE) force=--force test
+ $(MAKE) -k force=--force test
test-force-full:
- $(MAKE) force=--force test-full
+ $(MAKE) -k force=--force test-full
#used by autopush.pl to run memory based tests
test-force-mem:
- $(MAKE) force=--force mem=--mem test
+ $(MAKE) -k force=--force mem=--mem test
test-bt:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@@ -261,7 +261,7 @@ test-fast-prepare:
$(MAKE) subset=--ps-protocol test-fast
test-full-qa:
- $(MAKE) force=--force test-pr \
+ $(MAKE) -k force=--force test-pr \
test-binlog-statement test-ext test-fast-view \
test-fast-cursor test-unit
@@ -271,12 +271,13 @@ test-full-qa:
# after which TEST_PREPROCESSOR_HEADER will be used.
#
-API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \
- $(top_srcdir)/include/mysql.h
-
-TEST_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \
- $(top_srcdir)/sql/mysql_priv.h \
- $(top_srcdir)/include/mysql.h
+API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql.h \
+ $(top_srcdir)/include/mysql/client_plugin.h \
+ $(top_srcdir)/include/mysql/plugin_auth.h
+
+TEST_PREPROCESSOR_HEADER = $(API_PREPROCESSOR_HEADER) \
+ $(top_srcdir)/sql/mysql_priv.h
+
#
# Rules for checking that the abi/api has not changed.
=== modified file 'client/CMakeLists.txt'
--- a/client/CMakeLists.txt 2009-09-04 05:54:16 +0000
+++ b/client/CMakeLists.txt 2010-03-29 15:13:53 +0000
@@ -83,3 +83,5 @@ IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("echo" "asInvoker")
ENDIF(EMBED_MANIFESTS)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
+
=== modified file 'client/Makefile.am'
--- a/client/Makefile.am 2009-12-08 21:47:54 +0000
+++ b/client/Makefile.am 2010-03-29 15:13:53 +0000
@@ -100,8 +100,8 @@ mysql_upgrade_SOURCES= mysql_up
# Fix for mit-threads
DEFS = -DMYSQL_CLIENT_NO_THREADS \
- -DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \
- -DMYSQL_DATADIR="\"$(localstatedir)\""
+ -DDEFAULT_MYSQL_HOME='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(localstatedir)"'
sql_src=log_event.h mysql_priv.h rpl_constants.h \
rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
=== modified file 'client/client_priv.h'
--- a/client/client_priv.h 2010-03-15 11:51:23 +0000
+++ b/client/client_priv.h 2010-03-29 15:13:53 +0000
@@ -93,5 +93,7 @@ enum options_client
OPT_FIRST_SLAVE,
OPT_ALL,
OPT_REWRITE_DB,
- OPT_MAX_CLIENT_OPTION
+ OPT_PLUGIN_DIR,
+ OPT_DEFAULT_PLUGIN,
+ OPT_MAX_CLIENT_OPTION /* should be always the last */
};
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2010-03-04 08:03:07 +0000
+++ b/client/mysql.cc 2010-03-29 15:13:53 +0000
@@ -167,6 +167,7 @@ static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char mysql_charsets_dir[FN_REFLEN+1];
+static char *opt_plugin_dir= 0, *opt_default_auth;
static const char *xmlmeta[] = {
"&", "&",
"<", "<",
@@ -1542,6 +1543,13 @@ static struct my_option my_long_options[
{"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
(uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_PLUGIN_DIR,
+ "Default authentication client-side plugin to use.",
+ (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -4238,6 +4246,56 @@ char *get_arg(char *line, my_bool get_ne
}
+/**
+ An example of mysql_authentication_dialog_ask callback.
+
+ The C function with the name "mysql_authentication_dialog_ask", if exists,
+ will be used by the "dialog" client authentication plugin when user
+ input is needed. This function should be of mysql_authentication_dialog_ask_t
+ type. If the function does not exists, a built-in implementation will be
+ used.
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - normal string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+
+extern "C" char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ char *s=buf;
+
+ fputs("[mariadb] ", stdout);
+ fputs(prompt, stdout);
+ fputs(" ", stdout);
+
+ if (type == 2) /* password */
+ {
+ s= get_tty_password("");
+ strnmov(buf, s, buf_len);
+ buf[buf_len-1]= 0;
+ my_free(s, MYF(0));
+ }
+ else
+ {
+ fgets(buf, buf_len-1, stdin);
+ if (buf[0] && (s= strend(buf))[-1] == '\n')
+ s[-1]= 0;
+ }
+
+ return buf;
+}
+
static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
@@ -4283,6 +4341,13 @@ sql_real_connect(char *host,char *databa
}
if (default_charset_used)
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc 2010-01-28 14:49:14 +0000
+++ b/client/mysqltest.cc 2010-02-19 08:08:05 +0000
@@ -36,6 +36,7 @@
#include "client_priv.h"
#include <mysql_version.h>
#include <mysqld_error.h>
+#include <sql_common.h>
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -3610,13 +3611,15 @@ void do_change_user(struct st_command *c
}
if (!ds_user.length)
+ {
dynstr_set(&ds_user, mysql->user);
- if (!ds_passwd.length)
- dynstr_set(&ds_passwd, mysql->passwd);
+ if (!ds_passwd.length)
+ dynstr_set(&ds_passwd, mysql->passwd);
- if (!ds_db.length)
- dynstr_set(&ds_db, mysql->db);
+ if (!ds_db.length)
+ dynstr_set(&ds_db, mysql->db);
+ }
DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
=== modified file 'config/ac-macros/plugins.m4'
--- a/config/ac-macros/plugins.m4 2009-12-22 10:33:20 +0000
+++ b/config/ac-macros/plugins.m4 2010-03-29 15:14:28 +0000
@@ -38,6 +38,7 @@ AC_DEFUN([_MYSQL_PLUGIN],[
_MYSQL_PLUGAPPEND([__mysql_plugin_list__],[$1])
m4_define([MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]), [$3])
m4_define([MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]), [$4])
+ m4_ifdef([_AC_ENABLE_IF], [_AC_ENABLE_IF([with],[plugin-$1])])
_MYSQL_PLUGAPPEND_META([$1], $5)
ifelse(m4_bregexp(__mysql_include__,[/plug\.in$]),-1,[],[
MYSQL_PLUGIN_DIRECTORY([$1],
=== modified file 'configure.in'
--- a/configure.in 2010-03-18 12:08:39 +0000
+++ b/configure.in 2010-03-29 15:13:53 +0000
@@ -1605,9 +1605,8 @@ case "$with_mysqld_ldflags " in
;;
*)
- # Check for dlopen, needed for user definable functions
+ # Check for dlopen, needed for user definable functions and plugins
# This must be checked after threads on AIX
- # We only need this for mysqld, not for the clients.
my_save_LIBS="$LIBS"
LIBS=""
=== modified file 'include/Makefile.am'
--- a/include/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/include/Makefile.am 2010-03-29 15:13:53 +0000
@@ -24,6 +24,8 @@ pkginclude_HEADERS = $(HEADERS_ABI) my_d
my_xml.h mysql_embed.h mysql/services.h \
mysql/service_my_snprintf.h mysql/service_thd_alloc.h \
my_pthread.h my_no_pthread.h \
+ mysql/plugin_auth.h mysql/client_plugin.h \
+ mysql/plugin_auth_common.h \
decimal.h errmsg.h my_global.h my_net.h \
my_getopt.h sslopt-longopts.h my_dir.h \
sslopt-vars.h sslopt-case.h sql_common.h keycache.h \
@@ -42,7 +44,7 @@ noinst_HEADERS = config-win.h config-net
atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \
atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \
wqueue.h waiting_threads.h
-EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp
+EXTRA_DIST = mysql.h.pp mysql/plugin_auth.h.pp mysql/client_plugin.h.pp
# Remove built files and the symlinked directories
CLEANFILES = $(BUILT_SOURCES) readline openssl
=== modified file 'include/errmsg.h'
--- a/include/errmsg.h 2008-05-20 16:36:26 +0000
+++ b/include/errmsg.h 2010-03-29 15:13:53 +0000
@@ -97,6 +97,7 @@ extern const char *client_errors[]; /* E
#define CR_SERVER_LOST_EXTENDED 2055
#define CR_STMT_CLOSED 2056
#define CR_NEW_STMT_METADATA 2057
-#define CR_ERROR_LAST /*Copy last error nr:*/ 2057
+#define CR_AUTH_PLUGIN_CANNOT_LOAD 2058
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2058
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
=== modified file 'include/m_ctype.h'
--- a/include/m_ctype.h 2010-01-06 19:20:16 +0000
+++ b/include/m_ctype.h 2010-03-31 18:37:45 +0000
@@ -291,7 +291,7 @@ struct charset_info_st
const uint16 *const *sort_order_big;
const uint16 *tab_to_uni;
MY_UNI_IDX *tab_from_uni;
- const MY_UNICASE_INFO *const *caseinfo;
+ MY_UNICASE_INFO *const *caseinfo;
const uchar *state_map;
const uchar *ident_map;
uint strxfrm_multiply;
=== modified file 'include/my_global.h'
--- a/include/my_global.h 2010-03-10 10:32:14 +0000
+++ b/include/my_global.h 2010-03-29 15:13:53 +0000
@@ -578,6 +578,14 @@ int __void__;
#define IF_VALGRIND(A,B) (B)
#endif
+#ifdef _WIN32
+#define SO_EXT ".dll"
+#elif defined(__APPLE__)
+#define SO_EXT ".dylib"
+#else
+#define SO_EXT ".so"
+#endif
+
/*
Suppress uninitialized variable warning without generating code.
@@ -1522,10 +1530,12 @@ do { doubleget_union _tmp; \
#endif
#ifndef HAVE_DLERROR
-#define dlerror() ""
+#define dlerror() "No support for dynamic loading (static build?)"
+#define dlopen(A,B) 0
+#define dlsym(A,B) 0
+#define dlclose(A) 0
#endif
-
#ifndef __NETWARE__
/*
* Include standard definitions of operator new and delete.
=== modified file 'include/my_no_pthread.h'
--- a/include/my_no_pthread.h 2009-12-12 18:11:25 +0000
+++ b/include/my_no_pthread.h 2010-03-29 15:13:53 +0000
@@ -46,6 +46,7 @@
#define rw_wrlock(A)
#define rw_unlock(A)
#define rwlock_destroy(A)
+#define safe_mutex_assert_owner(mp)
typedef int my_pthread_once_t;
#define MY_PTHREAD_ONCE_INIT 0
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2010-03-15 11:51:23 +0000
+++ b/include/my_sys.h 2010-03-29 15:13:53 +0000
@@ -210,7 +210,7 @@ extern void my_large_free(uchar * ptr, m
#define my_alloca(SZ) alloca((size_t) (SZ))
#define my_afree(PTR) {}
#else
-#define my_alloca(SZ) my_malloc(SZ,MYF(0))
+#define my_alloca(SZ) my_malloc(SZ,MYF(MY_FAE))
#define my_afree(PTR) my_free(PTR,MYF(MY_WME))
#endif /* HAVE_ALLOCA */
@@ -870,6 +870,10 @@ extern void set_prealloc_root(MEM_ROOT *
extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
size_t prealloc_size);
extern char *strdup_root(MEM_ROOT *root,const char *str);
+static inline char *safe_strdup_root(MEM_ROOT *root, const char *str)
+{
+ return str ? strdup_root(root, str) : 0;
+}
extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len);
extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len);
extern int get_defaults_options(int argc, char **argv,
=== modified file 'include/mysql.h'
--- a/include/mysql.h 2010-02-01 06:14:12 +0000
+++ b/include/mysql.h 2010-03-29 15:13:53 +0000
@@ -167,9 +167,15 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
};
+/**
+ @todo remove the "extension", move st_mysql_options completely
+ out of mysql.h
+*/
+struct st_mysql_options_extention;
+
struct st_mysql_options {
unsigned int connect_timeout, read_timeout, write_timeout;
unsigned int port, protocol;
@@ -217,7 +223,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
- void *extension;
+ struct st_mysql_options_extention *extension;
};
enum mysql_status
@@ -752,38 +758,6 @@ enum enum_stmt_attr_type
};
-typedef struct st_mysql_methods
-{
- my_bool (*read_query_result)(MYSQL *mysql);
- my_bool (*advanced_command)(MYSQL *mysql,
- enum enum_server_command command,
- const unsigned char *header,
- unsigned long header_length,
- const unsigned char *arg,
- unsigned long arg_length,
- my_bool skip_check,
- MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields);
- MYSQL_RES * (*use_result)(MYSQL *mysql);
- void (*fetch_lengths)(unsigned long *to,
- MYSQL_ROW column, unsigned int field_count);
- void (*flush_use_result)(MYSQL *mysql);
-#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
- MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
- my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
- int (*stmt_execute)(MYSQL_STMT *stmt);
- int (*read_binary_rows)(MYSQL_STMT *stmt);
- int (*unbuffered_fetch)(MYSQL *mysql, char **row);
- void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistics)(MYSQL *mysql);
- my_bool (*next_result)(MYSQL *mysql);
- int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
- int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
-#endif
-} MYSQL_METHODS;
-
-
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
@@ -846,18 +820,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql,
#endif
#define HAVE_MYSQL_REAL_CONNECT
-/*
- The following functions are mainly exported because of mysqlbinlog;
- They are not for general usage
-*/
-
-#define simple_command(mysql, command, arg, length, skip_check) \
- (*(mysql)->methods->advanced_command)(mysql, command, 0, \
- 0, arg, length, skip_check, NULL)
-#define stmt_command(mysql, command, arg, length, stmt) \
- (*(mysql)->methods->advanced_command)(mysql, command, 0, \
- 0, arg, length, 1, stmt)
-
#ifdef __NETWARE__
#pragma pack(pop) /* restore alignment */
#endif
=== modified file 'include/mysql.h.pp'
--- a/include/mysql.h.pp 2010-03-15 11:51:23 +0000
+++ b/include/mysql.h.pp 2010-03-29 15:13:53 +0000
@@ -128,13 +128,13 @@ void create_random_string(char *to, unsi
void hash_password(unsigned long *to, const char *password, unsigned int password_len);
void make_scrambled_password_323(char *to, const char *password);
void scramble_323(char *to, const char *message, const char *password);
-my_bool check_scramble_323(const char *, const char *message,
+my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
-my_bool check_scramble(const char *reply, const char *message,
+my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
@@ -258,8 +258,9 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
};
+struct st_mysql_options_extention;
struct st_mysql_options {
unsigned int connect_timeout, read_timeout, write_timeout;
unsigned int port, protocol;
@@ -289,7 +290,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
- void *extension;
+ struct st_mysql_options_extention *extension;
};
enum mysql_status
{
@@ -601,34 +602,6 @@ enum enum_stmt_attr_type
STMT_ATTR_CURSOR_TYPE,
STMT_ATTR_PREFETCH_ROWS
};
-typedef struct st_mysql_methods
-{
- my_bool (*read_query_result)(MYSQL *mysql);
- my_bool (*advanced_command)(MYSQL *mysql,
- enum enum_server_command command,
- const unsigned char *header,
- unsigned long header_length,
- const unsigned char *arg,
- unsigned long arg_length,
- my_bool skip_check,
- MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields);
- MYSQL_RES * (*use_result)(MYSQL *mysql);
- void (*fetch_lengths)(unsigned long *to,
- MYSQL_ROW column, unsigned int field_count);
- void (*flush_use_result)(MYSQL *mysql);
- MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
- my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
- int (*stmt_execute)(MYSQL_STMT *stmt);
- int (*read_binary_rows)(MYSQL_STMT *stmt);
- int (*unbuffered_fetch)(MYSQL *mysql, char **row);
- void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistics)(MYSQL *mysql);
- my_bool (*next_result)(MYSQL *mysql);
- int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
- int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
-} MYSQL_METHODS;
MYSQL_STMT * mysql_stmt_init(MYSQL *mysql);
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
=== added file 'include/mysql/client_plugin.h'
--- a/include/mysql/client_plugin.h 1970-01-01 00:00:00 +0000
+++ b/include/mysql/client_plugin.h 2010-03-29 15:13:53 +0000
@@ -0,0 +1,164 @@
+#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ MySQL Client Plugin API
+
+ This file defines the API for plugins that work on the client side
+*/
+#define MYSQL_CLIENT_PLUGIN_INCLUDED
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* known plugin types */
+#define MYSQL_CLIENT_reserved1 0
+#define MYSQL_CLIENT_reserved2 1
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
+
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
+
+#define MYSQL_CLIENT_MAX_PLUGINS 3
+
+#define mysql_declare_client_plugin(X) \
+ struct st_mysql_client_plugin_ ## X \
+ _mysql_client_plugin_declaration_ = { \
+ MYSQL_CLIENT_ ## X ## _PLUGIN, \
+ MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION,
+#define mysql_end_client_plugin }
+
+/* generic plugin header structure */
+#define MYSQL_CLIENT_PLUGIN_HEADER \
+ int type; \
+ unsigned int interface_version; \
+ const char *name; \
+ const char *author; \
+ const char *desc; \
+ unsigned int version[3]; \
+ int (*init)(char *, size_t, int, va_list); \
+ int (*deinit)();
+
+struct st_mysql_client_plugin
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+};
+
+struct st_mysql;
+
+/******** authentication plugin specific declarations *********/
+#include <mysql/plugin_auth_common.h>
+
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+
+/**
+ type of the mysql_authentication_dialog_ask function
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - ordinary string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+/******** using plugins ************/
+
+/**
+ loads a plugin and initializes it
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param ... arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+
+/**
+ loads a plugin and initializes it, taking va_list as an argument
+
+ This is the same as mysql_load_plugin, but take va_list instead of
+ a list of arguments.
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param args arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+
+/**
+ finds an already loaded plugin by name, or loads it, if necessary
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+
+/**
+ adds a plugin structure to the list of loaded plugins
+
+ This is useful if an application has the necessary functionality
+ (for example, a special load data handler) statically linked into
+ the application binary. It can use this function to register the plugin
+ directly, avoiding the need to factor it out into a shared object.
+
+ @param mysql MYSQL structure. It is only used for error reporting
+ @param plugin an st_mysql_client_plugin structure to register
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
+
+#endif
+
=== added file 'include/mysql/client_plugin.h.pp'
--- a/include/mysql/client_plugin.h.pp 1970-01-01 00:00:00 +0000
+++ b/include/mysql/client_plugin.h.pp 2010-03-29 15:13:53 +0000
@@ -0,0 +1,41 @@
+#include <stdarg.h>
+#include <stdlib.h>
+struct st_mysql_client_plugin
+{
+ int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; int (*init)(char *, size_t, int, va_list); int (*deinit)();
+};
+struct st_mysql;
+#include <mysql/plugin_auth_common.h>
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket;
+} MYSQL_PLUGIN_VIO_INFO;
+typedef struct st_plugin_vio
+{
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+} MYSQL_PLUGIN_VIO;
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; int (*init)(char *, size_t, int, va_list); int (*deinit)();
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h 2010-03-03 14:44:14 +0000
+++ b/include/mysql/plugin.h 2010-03-29 15:13:53 +0000
@@ -67,7 +67,10 @@ typedef struct st_mysql_xid MYSQL_XID;
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */
#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */
-#define MYSQL_MAX_PLUGIN_TYPE_NUM 5 /* The number of plugin types */
+#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */
+#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */
+#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */
+#define MYSQL_MAX_PLUGIN_TYPE_NUM 8 /* The number of plugin types */
/* We use the following strings to define licenses for plugins */
#define PLUGIN_LICENSE_PROPRIETARY 0
=== removed file 'include/mysql/plugin.h.pp'
--- a/include/mysql/plugin.h.pp 2010-03-03 14:44:14 +0000
+++ b/include/mysql/plugin.h.pp 1970-01-01 00:00:00 +0000
@@ -1,163 +0,0 @@
-#include <mysql/services.h>
-#include <mysql/service_my_snprintf.h>
-#include <stdarg.h>
-#include <stdlib.h>
-extern struct my_snprintf_service_st {
- size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
- size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
-} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
-size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
-#include <mysql/service_thd_alloc.h>
-#include <stdlib.h>
-struct st_mysql_lex_string
-{
- char *str;
- size_t length;
-};
-typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
-extern struct thd_alloc_service_st {
- void *(*thd_alloc_func)(void*, unsigned int);
- void *(*thd_calloc_func)(void*, unsigned int);
- char *(*thd_strdup_func)(void*, const char *);
- char *(*thd_strmake_func)(void*, const char *, unsigned int);
- void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
- const char *, unsigned int, int);
-} *thd_alloc_service;
-void *thd_alloc(void* thd, unsigned int size);
-void *thd_calloc(void* thd, unsigned int size);
-char *thd_strdup(void* thd, const char *str);
-char *thd_strmake(void* thd, const char *str, unsigned int size);
-void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
-struct st_mysql_xid {
- long formatID;
- long gtrid_length;
- long bqual_length;
- char data[128];
-};
-typedef struct st_mysql_xid MYSQL_XID;
-enum enum_mysql_show_type
-{
- SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
- SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
- SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
- SHOW_always_last
-};
-struct st_mysql_show_var {
- const char *name;
- char *value;
- enum enum_mysql_show_type type;
-};
-typedef int (*mysql_show_var_func)(void*, struct st_mysql_show_var*, char *);
-struct st_mysql_sys_var;
-struct st_mysql_value;
-typedef int (*mysql_var_check_func)(void* thd,
- struct st_mysql_sys_var *var,
- void *save, struct st_mysql_value *value);
-typedef void (*mysql_var_update_func)(void* thd,
- struct st_mysql_sys_var *var,
- void *var_ptr, const void *save);
-struct st_mysql_plugin
-{
- int type;
- void *info;
- const char *name;
- const char *author;
- const char *descr;
- int license;
- int (*init)(void *);
- int (*deinit)(void *);
- unsigned int version;
- struct st_mysql_show_var *status_vars;
- struct st_mysql_sys_var **system_vars;
- void * __reserved1;
-};
-enum enum_ftparser_mode
-{
- MYSQL_FTPARSER_SIMPLE_MODE= 0,
- MYSQL_FTPARSER_WITH_STOPWORDS= 1,
- MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
-};
-enum enum_ft_token_type
-{
- FT_TOKEN_EOF= 0,
- FT_TOKEN_WORD= 1,
- FT_TOKEN_LEFT_PAREN= 2,
- FT_TOKEN_RIGHT_PAREN= 3,
- FT_TOKEN_STOPWORD= 4
-};
-typedef struct st_mysql_ftparser_boolean_info
-{
- enum enum_ft_token_type type;
- int yesno;
- int weight_adjust;
- char wasign;
- char trunc;
- char prev;
- char *quot;
-} MYSQL_FTPARSER_BOOLEAN_INFO;
-typedef int mysql_ft_size_t;
-typedef struct st_mysql_ftparser_param
-{
- int (*mysql_parse)(struct st_mysql_ftparser_param *,
- const unsigned char *doc, mysql_ft_size_t doc_len);
- int (*mysql_add_word)(struct st_mysql_ftparser_param *,
- const unsigned char *word, mysql_ft_size_t word_len,
- MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
- void *ftparser_state;
- void *mysql_ftparam;
- const struct charset_info_st *cs;
- const unsigned char *doc;
- mysql_ft_size_t length;
- unsigned int flags;
- enum enum_ftparser_mode mode;
-} MYSQL_FTPARSER_PARAM;
-struct st_mysql_ftparser
-{
- int interface_version;
- int (*parse)(MYSQL_FTPARSER_PARAM *param);
- int (*init)(MYSQL_FTPARSER_PARAM *param);
- int (*deinit)(MYSQL_FTPARSER_PARAM *param);
-};
-struct st_mysql_storage_engine
-{
- int interface_version;
-};
-struct handlerton;
-struct st_mysql_daemon
-{
- int interface_version;
-};
-struct st_mysql_information_schema
-{
- int interface_version;
-};
-struct st_mysql_value
-{
- int (*value_type)(struct st_mysql_value *);
- const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length);
- int (*val_real)(struct st_mysql_value *, double *realbuf);
- int (*val_int)(struct st_mysql_value *, long long *intbuf);
-};
-int thd_in_lock_tables(const void* thd);
-int thd_tablespace_op(const void* thd);
-long long thd_test_options(const void* thd, long long test_options);
-int thd_sql_command(const void* thd);
-void **thd_ha_data(const void* thd, const struct handlerton *hton);
-int thd_tx_isolation(const void* thd);
-char *thd_security_context(void* thd, char *buffer, unsigned int length,
- unsigned int max_query_len);
-void thd_inc_row_count(void* thd);
-const char *set_thd_proc_info(void*, const char * info, const char *func,
- const char *file, const unsigned int line);
-int mysql_tmpfile(const char *prefix);
-int thd_killed(const void* thd);
-unsigned long thd_get_thread_id(const void* thd);
-void thd_get_xid(const void* thd, MYSQL_XID *xid);
-void mysql_query_cache_invalidate4(void* thd,
- const char *key, unsigned int key_length,
- int using_trx);
=== added file 'include/mysql/plugin_auth.h'
--- a/include/mysql/plugin_auth.h 1970-01-01 00:00:00 +0000
+++ b/include/mysql/plugin_auth.h 2010-03-29 15:13:53 +0000
@@ -0,0 +1,83 @@
+#ifndef MYSQL_PLUGIN_AUTH_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Authentication Plugin API.
+
+ This file defines the API for server authentication plugins.
+*/
+
+#define MYSQL_PLUGIN_AUTH_INCLUDED
+
+#include <mysql/plugin.h>
+
+#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0100
+
+#include <mysql/plugin_auth_common.h>
+
+/**
+ Provides server plugin access to authentication information
+*/
+typedef struct st_mysql_server_auth_info
+{
+ /**
+ User name as sent by the client and shown in USER().
+ NULL if the client packet with the user name was not received yet.
+ */
+ const char *user_name;
+ /**
+ A corresponding column value from the mysql.user table for the
+ matching account name
+ */
+ const char *auth_string;
+
+ /**
+ Matching account name as found in the mysql.user table.
+ A plugin can override it with another name that will be
+ used by MySQL for authorization, and shown in CURRENT_USER()
+ */
+ char authenticated_as[MYSQL_USERNAME_LENGTH+1];
+ /**
+ This only affects the "Authentication failed. Password used: %s"
+ error message. If set, %s will be YES, otherwise - NO.
+ Set it as appropriate or ignore at will.
+ */
+ int password_used;
+} MYSQL_SERVER_AUTH_INFO;
+
+/**
+ Server authentication plugin descriptor
+*/
+struct st_mysql_auth
+{
+ int interface_version; /**< version plugin uses */
+ /**
+ A plugin that a client must use for authentication with this server
+ plugin. Can be NULL to mean "any plugin".
+ */
+ const char *client_auth_plugin;
+ /**
+ Function provided by the plugin which should perform authentication (using
+ the vio functions if necessary) and return 0 if successful. The plugin can
+ also fill the info.authenticated_as field if a different username should be
+ used for authorization.
+ */
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
+};
+#endif
+
=== added file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp 1970-01-01 00:00:00 +0000
+++ b/include/mysql/plugin_auth.h.pp 2010-03-29 15:13:53 +0000
@@ -0,0 +1,193 @@
+#include <mysql/plugin.h>
+#include <mysql/services.h>
+#include <mysql/service_my_snprintf.h>
+#include <stdarg.h>
+#include <stdlib.h>
+extern struct my_snprintf_service_st {
+ size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
+ size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
+} *my_snprintf_service;
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
+#include <mysql/service_thd_alloc.h>
+#include <stdlib.h>
+struct st_mysql_lex_string
+{
+ char *str;
+ size_t length;
+};
+typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+extern struct thd_alloc_service_st {
+ void *(*thd_alloc_func)(void*, unsigned int);
+ void *(*thd_calloc_func)(void*, unsigned int);
+ char *(*thd_strdup_func)(void*, const char *);
+ char *(*thd_strmake_func)(void*, const char *, unsigned int);
+ void *(*thd_memdup_func)(void*, const void*, unsigned int);
+ MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ const char *, unsigned int, int);
+} *thd_alloc_service;
+void *thd_alloc(void* thd, unsigned int size);
+void *thd_calloc(void* thd, unsigned int size);
+char *thd_strdup(void* thd, const char *str);
+char *thd_strmake(void* thd, const char *str, unsigned int size);
+void *thd_memdup(void* thd, const void* str, unsigned int size);
+MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
+struct st_mysql_xid {
+ long formatID;
+ long gtrid_length;
+ long bqual_length;
+ char data[128];
+};
+typedef struct st_mysql_xid MYSQL_XID;
+enum enum_mysql_show_type
+{
+ SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
+ SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
+ SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
+ SHOW_always_last
+};
+struct st_mysql_show_var {
+ const char *name;
+ char *value;
+ enum enum_mysql_show_type type;
+};
+typedef int (*mysql_show_var_func)(void*, struct st_mysql_show_var*, char *);
+struct st_mysql_sys_var;
+struct st_mysql_value;
+typedef int (*mysql_var_check_func)(void* thd,
+ struct st_mysql_sys_var *var,
+ void *save, struct st_mysql_value *value);
+typedef void (*mysql_var_update_func)(void* thd,
+ struct st_mysql_sys_var *var,
+ void *var_ptr, const void *save);
+struct st_mysql_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ void * __reserved1;
+};
+enum enum_ftparser_mode
+{
+ MYSQL_FTPARSER_SIMPLE_MODE= 0,
+ MYSQL_FTPARSER_WITH_STOPWORDS= 1,
+ MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
+};
+enum enum_ft_token_type
+{
+ FT_TOKEN_EOF= 0,
+ FT_TOKEN_WORD= 1,
+ FT_TOKEN_LEFT_PAREN= 2,
+ FT_TOKEN_RIGHT_PAREN= 3,
+ FT_TOKEN_STOPWORD= 4
+};
+typedef struct st_mysql_ftparser_boolean_info
+{
+ enum enum_ft_token_type type;
+ int yesno;
+ int weight_adjust;
+ char wasign;
+ char trunc;
+ char prev;
+ char *quot;
+} MYSQL_FTPARSER_BOOLEAN_INFO;
+typedef int mysql_ft_size_t;
+typedef struct st_mysql_ftparser_param
+{
+ int (*mysql_parse)(struct st_mysql_ftparser_param *,
+ const unsigned char *doc, mysql_ft_size_t doc_len);
+ int (*mysql_add_word)(struct st_mysql_ftparser_param *,
+ const unsigned char *word, mysql_ft_size_t word_len,
+ MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
+ void *ftparser_state;
+ void *mysql_ftparam;
+ const struct charset_info_st *cs;
+ const unsigned char *doc;
+ mysql_ft_size_t length;
+ unsigned int flags;
+ enum enum_ftparser_mode mode;
+} MYSQL_FTPARSER_PARAM;
+struct st_mysql_ftparser
+{
+ int interface_version;
+ int (*parse)(MYSQL_FTPARSER_PARAM *param);
+ int (*init)(MYSQL_FTPARSER_PARAM *param);
+ int (*deinit)(MYSQL_FTPARSER_PARAM *param);
+};
+struct st_mysql_storage_engine
+{
+ int interface_version;
+};
+struct handlerton;
+struct st_mysql_daemon
+{
+ int interface_version;
+};
+struct st_mysql_information_schema
+{
+ int interface_version;
+};
+struct st_mysql_value
+{
+ int (*value_type)(struct st_mysql_value *);
+ const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length);
+ int (*val_real)(struct st_mysql_value *, double *realbuf);
+ int (*val_int)(struct st_mysql_value *, long long *intbuf);
+};
+int thd_in_lock_tables(const void* thd);
+int thd_tablespace_op(const void* thd);
+long long thd_test_options(const void* thd, long long test_options);
+int thd_sql_command(const void* thd);
+void **thd_ha_data(const void* thd, const struct handlerton *hton);
+int thd_tx_isolation(const void* thd);
+char *thd_security_context(void* thd, char *buffer, unsigned int length,
+ unsigned int max_query_len);
+void thd_inc_row_count(void* thd);
+const char *set_thd_proc_info(void*, const char * info, const char *func,
+ const char *file, const unsigned int line);
+int mysql_tmpfile(const char *prefix);
+int thd_killed(const void* thd);
+unsigned long thd_get_thread_id(const void* thd);
+void thd_get_xid(const void* thd, MYSQL_XID *xid);
+void mysql_query_cache_invalidate4(void* thd,
+ const char *key, unsigned int key_length,
+ int using_trx);
+#include <mysql/plugin_auth_common.h>
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket;
+} MYSQL_PLUGIN_VIO_INFO;
+typedef struct st_plugin_vio
+{
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+} MYSQL_PLUGIN_VIO;
+typedef struct st_mysql_server_auth_info
+{
+ const char *user_name;
+ const char *auth_string;
+ char authenticated_as[48 +1];
+ int password_used;
+} MYSQL_SERVER_AUTH_INFO;
+struct st_mysql_auth
+{
+ int interface_version;
+ const char *client_auth_plugin;
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
+};
=== added file 'include/mysql/plugin_auth_common.h'
--- a/include/mysql/plugin_auth_common.h 1970-01-01 00:00:00 +0000
+++ b/include/mysql/plugin_auth_common.h 2010-03-29 15:13:53 +0000
@@ -0,0 +1,105 @@
+#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ This file defines constants and data structures that are the same for
+ both client- and server-side authentication plugins.
+*/
+#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+
+/** the max allowed length for a user name */
+#define MYSQL_USERNAME_LENGTH 48
+
+/**
+ return values of the plugin authenticate_user() method.
+*/
+
+/**
+ Authentication failed. Additionally, all other CR_xxx values
+ (libmysql error code) can be used too.
+
+ The client plugin may set the error code and the error message directly
+ in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error
+ code was returned, an error message in the MYSQL structure will be
+ overwritten. If CR_ERROR is returned without setting the error in MYSQL,
+ CR_UNKNOWN_ERROR will be user.
+*/
+#define CR_ERROR 0
+/**
+ Authentication (client part) was successful. It does not mean that the
+ authentication as a whole was successful, usually it only means
+ that the client was able to send the user name and the password to the
+ server. If CR_OK is returned, the libmysql reads the next packet expecting
+ it to be one of OK, ERROR, or CHANGE_PLUGIN packets.
+*/
+#define CR_OK -1
+/**
+ Authentication was successful.
+ It means that the client has done its part successfully and also that
+ a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN).
+ In this case, libmysql will not read a packet from the server,
+ but it will use the data at mysql->net.read_pos.
+
+ A plugin may return this value if the number of roundtrips in the
+ authentication protocol is not known in advance, and the client plugin
+ needs to read one packet more to determine if the authentication is finished
+ or not.
+*/
+#define CR_OK_HANDSHAKE_COMPLETE -2
+
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket; /**< it's set, if the protocol is SOCKET or TCP */
+#ifdef _WIN32
+ HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
+#endif
+} MYSQL_PLUGIN_VIO_INFO;
+
+/**
+ Provides plugin access to communication channel
+*/
+typedef struct st_plugin_vio
+{
+ /**
+ Plugin provides a pointer reference and this function sets it to the
+ contents of any incoming packet. Returns the packet length, or -1 if
+ the plugin should terminate.
+ */
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+
+ /**
+ Plugin provides a buffer with data and the length and this
+ function sends it as a packet. Returns 0 on success, 1 on failure.
+ */
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+
+ /**
+ Fills in a st_plugin_vio_info structure, providing the information
+ about the connection.
+ */
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+
+} MYSQL_PLUGIN_VIO;
+
+#endif
+
=== modified file 'include/mysql_com.h'
--- a/include/mysql_com.h 2010-03-15 11:51:23 +0000
+++ b/include/mysql_com.h 2010-03-29 15:13:53 +0000
@@ -152,9 +152,17 @@ enum enum_server_command
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
+#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */
+
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
+#ifdef HAVE_COMPRESS
+#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS
+#else
+#define CAN_CLIENT_COMPRESS 0
+#endif
+
/* Gather all possible capabilites (flags) supported by the server */
#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \
CLIENT_FOUND_ROWS | \
@@ -175,7 +183,8 @@ enum enum_server_command
CLIENT_MULTI_STATEMENTS | \
CLIENT_MULTI_RESULTS | \
CLIENT_SSL_VERIFY_SERVER_CERT | \
- CLIENT_REMEMBER_OPTIONS)
+ CLIENT_REMEMBER_OPTIONS | \
+ CLIENT_PLUGIN_AUTH)
/*
Switch off the flags that are optional and depending on build flags
@@ -488,14 +497,14 @@ void create_random_string(char *to, unsi
void hash_password(unsigned long *to, const char *password, unsigned int password_len);
void make_scrambled_password_323(char *to, const char *password);
void scramble_323(char *to, const char *message, const char *password);
-my_bool check_scramble_323(const char *, const char *message,
+my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
-my_bool check_scramble(const char *reply, const char *message,
+my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
=== modified file 'include/sql_common.h'
--- a/include/sql_common.h 2008-02-27 09:00:59 +0000
+++ b/include/sql_common.h 2010-03-29 15:13:53 +0000
@@ -1,3 +1,4 @@
+#ifndef SQL_COMMON_INCLUDED
/* Copyright (C) 2003-2004, 2006 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -13,14 +14,60 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#define SQL_COMMON_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mysql.h>
extern const char *unknown_sqlstate;
extern const char *cant_connect_sqlstate;
extern const char *not_error_sqlstate;
-#ifdef __cplusplus
-extern "C" {
+struct st_mysql_options_extention {
+ char *plugin_dir;
+ char *default_auth;
+};
+
+typedef struct st_mysql_methods
+{
+ my_bool (*read_query_result)(MYSQL *mysql);
+ my_bool (*advanced_command)(MYSQL *mysql,
+ enum enum_server_command command,
+ const unsigned char *header,
+ unsigned long header_length,
+ const unsigned char *arg,
+ unsigned long arg_length,
+ my_bool skip_check,
+ MYSQL_STMT *stmt);
+ MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ unsigned int fields);
+ MYSQL_RES * (*use_result)(MYSQL *mysql);
+ void (*fetch_lengths)(unsigned long *to,
+ MYSQL_ROW column, unsigned int field_count);
+ void (*flush_use_result)(MYSQL *mysql);
+ int (*read_change_user_result)(MYSQL *mysql);
+#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+ MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
+ my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
+ int (*stmt_execute)(MYSQL_STMT *stmt);
+ int (*read_binary_rows)(MYSQL_STMT *stmt);
+ int (*unbuffered_fetch)(MYSQL *mysql, char **row);
+ void (*free_embedded_thd)(MYSQL *mysql);
+ const char *(*read_statistics)(MYSQL *mysql);
+ my_bool (*next_result)(MYSQL *mysql);
+ int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif
+} MYSQL_METHODS;
+
+#define simple_command(mysql, command, arg, length, skip_check) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, skip_check, NULL)
+#define stmt_command(mysql, command, arg, length, stmt) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, 1, stmt)
extern CHARSET_INFO *default_client_charset_info;
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
@@ -42,9 +89,23 @@ void set_stmt_errmsg(MYSQL_STMT *stmt, N
void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate,
const char *err);
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);
+void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate,
+ const char *format, ...);
+
+/* client side of the pluggable authentication */
+struct st_plugin_vio_info;
+void mpvio_info(Vio *vio, struct st_plugin_vio_info *info);
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ char *data_plugin, const char *db);
+int mysql_client_plugin_init();
+void mysql_client_plugin_deinit();
+struct st_mysql_client_plugin;
+extern struct st_mysql_client_plugin *mysql_client_builtins[];
+
#ifdef __cplusplus
}
#endif
#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)
+#endif
=== modified file 'libmysql/CMakeLists.txt'
--- a/libmysql/CMakeLists.txt 2009-09-15 10:46:35 +0000
+++ b/libmysql/CMakeLists.txt 2010-03-29 15:13:53 +0000
@@ -98,7 +98,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ..
../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c
../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c
../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c
- ../mysys/my_getsystime.c ../mysys/my_sync.c ${LIB_SOURCES})
+ ../mysys/my_getsystime.c ../mysys/my_sync.c ../sql-common/client_plugin.c ${LIB_SOURCES})
# Need to set USE_TLS for building the DLL, since __declspec(thread)
# approach to thread local storage does not work properly in DLLs.
@@ -125,6 +125,7 @@ IF(WIN32)
ENDIF(WIN32)
ADD_DEPENDENCIES(libmysql GenError)
TARGET_LINK_LIBRARIES(libmysql wsock32)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")
=== modified file 'libmysql/Makefile.shared'
--- a/libmysql/Makefile.shared 2009-09-15 10:46:35 +0000
+++ b/libmysql/Makefile.shared 2010-03-29 15:13:53 +0000
@@ -23,6 +23,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
+pkgplugindir = $(pkglibdir)/plugin
## We'll use CLIENT_EXTRA_LDFLAGS for threaded and non-threaded
## until someone complains that they need separate options.
LDADD = @CLIENT_EXTRA_LDFLAGS@ $(target)
@@ -71,26 +72,27 @@ mysysobjects1 = my_init.lo my_static.lo
my_getopt.lo my_gethostbyname.lo my_port.lo \
my_rename.lo my_chsize.lo my_sync.lo my_getsystime.lo
sqlobjects = net.lo
-sql_cmn_objects = pack.lo client.lo my_time.lo
+sql_cmn_objects = pack.lo client.lo my_time.lo client_plugin.lo
# Not needed in the minimum library
mysysobjects2 = my_lib.lo mf_qsort.lo
mysysobjects = $(mysysobjects1) $(mysysobjects2)
target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \
$(sql_cmn_objects) $(vio_objects) $(sqlobjects)
-target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@
+target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ @LIBDL@
vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo
BUILT_SOURCES = link_sources
CLEANFILES = $(target_libadd) $(SHLIBOBJS) \
$(target) $(BUILT_SOURCES)
-DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
+DEFS = -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
-DDEFAULT_HOME_ENV=MYSQL_HOME \
+ -DPLUGINDIR='"$(pkgplugindir)"' \
-DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
+ -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' $(target_defs)
if HAVE_YASSL
yassl_las = $(top_builddir)/extra/yassl/src/libyassl.la \
=== modified file 'libmysql/client_settings.h'
--- a/libmysql/client_settings.h 2007-09-29 19:31:08 +0000
+++ b/libmysql/client_settings.h 2010-03-29 15:13:53 +0000
@@ -18,7 +18,8 @@ extern char * mysql_unix_port;
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
+ CLIENT_PLUGIN_AUTH)
sig_handler my_pipe_sig_handler(int sig);
void read_user_name(char *name);
@@ -57,7 +58,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt);
int cli_read_binary_rows(MYSQL_STMT *stmt);
int cli_unbuffered_fetch(MYSQL *mysql, char **row);
const char * cli_read_statistics(MYSQL *mysql);
-int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd);
+int cli_read_change_user_result(MYSQL *mysql);
#ifdef EMBEDDED_LIBRARY
int init_embedded_server(int argc, char **argv, char **groups);
=== modified file 'libmysql/errmsg.c'
--- a/libmysql/errmsg.c 2008-05-20 16:36:26 +0000
+++ b/libmysql/errmsg.c 2010-03-29 15:13:53 +0000
@@ -85,6 +85,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
@@ -151,6 +152,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
@@ -215,6 +217,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
#endif
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2010-03-04 08:03:07 +0000
+++ b/libmysql/libmysql.c 2010-03-29 15:13:53 +0000
@@ -126,12 +126,13 @@ int STDCALL mysql_server_init(int argc _
if (my_init()) /* Will init threads */
return 1;
init_client_errs();
+ if (mysql_client_plugin_init())
+ return 1;
if (!mysql_port)
{
mysql_port = MYSQL_PORT;
#ifndef MSDOS
{
- struct servent *serv_ptr;
char *env;
/*
@@ -145,6 +146,7 @@ int STDCALL mysql_server_init(int argc _
*/
#if MYSQL_PORT_DEFAULT == 0
+ struct servent *serv_ptr;
if ((serv_ptr = getservbyname("mysql", "tcp")))
mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
#endif
@@ -198,6 +200,8 @@ void STDCALL mysql_server_end()
if (!mysql_client_init)
return;
+ mysql_client_plugin_deinit();
+
#ifdef EMBEDDED_LIBRARY
end_embedded_server();
#endif
@@ -662,44 +666,14 @@ mysql_connect(MYSQL *mysql,const char *h
Change user and database
**************************************************************************/
-int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
-{
- NET *net= &mysql->net;
- ulong pkt_length;
-
- pkt_length= cli_safe_read(mysql);
-
- if (pkt_length == packet_error)
- return 1;
-
- if (pkt_length == 1 && net->read_pos[0] == 254 &&
- mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- By sending this very specific reply server asks us to send scrambled
- password in old format. The reply contains scramble_323.
- */
- scramble_323(buff, mysql->scramble, passwd);
- if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net))
- {
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
- return 1;
- }
- /* Read what server thinks about out new auth message report */
- if (cli_safe_read(mysql) == packet_error)
- return 1;
- }
- return 0;
-}
-
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db)
{
- char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
- char *end= buff;
int rc;
CHARSET_INFO *saved_cs= mysql->charset;
+ char *saved_user= mysql->user;
+ char *saved_passwd= mysql->passwd;
+ char *saved_db= mysql->db;
DBUG_ENTER("mysql_change_user");
@@ -713,49 +687,11 @@ my_bool STDCALL mysql_change_user(MYSQL
/* Use an empty string instead of NULL. */
- if (!user)
- user="";
- if (!passwd)
- passwd="";
-
- /*
- Store user into the buffer.
- Advance position as strmake returns a pointer to the closing NUL.
- */
- end= strmake(end, user, USERNAME_LENGTH) + 1;
-
- /* write scrambled password according to server capabilities */
- if (passwd[0])
- {
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- *end++= SCRAMBLE_LENGTH;
- scramble(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH;
- }
- else
- {
- scramble_323(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH_323 + 1;
- }
- }
- else
- *end++= '\0'; /* empty password */
- /* Add database if needed */
- end= strmake(end, db ? db : "", NAME_LEN) + 1;
-
- /* Add character set number. */
-
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- int2store(end, (ushort) mysql->charset->number);
- end+= 2;
- }
-
- /* Write authentication package */
- simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1);
+ mysql->user= (char*)(user ? user : "");
+ mysql->passwd= (char*)(passwd ? passwd : "");
+ mysql->db= 0;
- rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
+ rc= run_plugin_auth(mysql, 0, 0, 0, db);
/*
The server will close all statements no matter was the attempt
@@ -765,18 +701,21 @@ my_bool STDCALL mysql_change_user(MYSQL
if (rc == 0)
{
/* Free old connect information */
- my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_user, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_passwd, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_db, MYF(MY_ALLOW_ZERO_PTR));
/* alloc new connect information */
- mysql->user= my_strdup(user,MYF(MY_WME));
- mysql->passwd=my_strdup(passwd,MYF(MY_WME));
- mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
+ mysql->user= my_strdup(mysql->user, MYF(MY_WME));
+ mysql->passwd= my_strdup(mysql->passwd, MYF(MY_WME));
+ mysql->db= db ? my_strdup(db, MYF(MY_WME)) : 0;
}
else
{
mysql->charset= saved_cs;
+ mysql->user= saved_user;
+ mysql->passwd= saved_passwd;
+ mysql->db= saved_db;
}
DBUG_RETURN(rc);
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-12-03 11:19:05 +0000
+++ b/libmysqld/Makefile.am 2010-03-29 15:13:53 +0000
@@ -25,10 +25,10 @@ pkgplugindir = $(pkglibdir)/plugin
EXTRA_DIST = libmysqld.def CMakeLists.txt
DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
- -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
- -DPLUGINDIR="\"$(pkgplugindir)\""
+ -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' \
+ -DPLUGINDIR='"$(pkgplugindir)"'
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/sql -I$(top_srcdir)/sql \
-I$(top_srcdir)/sql/examples \
@@ -41,7 +41,7 @@ pkglib_LIBRARIES = libmysqld.a
SUBDIRS = . examples
libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc
libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
- my_time.c
+ my_time.c client_plugin.c
noinst_HEADERS = embedded_priv.h emb_qcache.h
=== modified file 'libmysqld/embedded_priv.h'
--- a/libmysqld/embedded_priv.h 2006-12-31 00:32:21 +0000
+++ b/libmysqld/embedded_priv.h 2010-03-29 15:13:53 +0000
@@ -15,6 +15,8 @@
/* Prototypes for the embedded version of MySQL */
+#include <sql_common.h>
+
C_MODE_START
void lib_connection_phase(NET *net, int phase);
void init_embedded_mysql(MYSQL *mysql, int client_flag);
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2010-03-04 08:03:07 +0000
+++ b/libmysqld/lib_sql.cc 2010-03-29 15:13:53 +0000
@@ -35,7 +35,6 @@ C_MODE_START
#include <mysql.h>
#undef ER
#include "errmsg.h"
-#include <sql_common.h>
#include "embedded_priv.h"
extern unsigned int mysql_server_last_errno;
@@ -413,11 +412,10 @@ static MYSQL_RES * emb_store_result(MYSQ
return mysql_store_result(mysql);
}
-int emb_read_change_user_result(MYSQL *mysql,
- char *buff __attribute__((unused)),
- const char *passwd __attribute__((unused)))
+int emb_read_change_user_result(MYSQL *mysql)
{
- return mysql_errno(mysql);
+ mysql->net.read_pos= (uchar*)""; // fake an OK packet
+ return mysql_errno(mysql) ? packet_error : 1 /* length of the OK packet */;
}
MYSQL_METHODS embedded_methods=
@@ -428,6 +426,7 @@ MYSQL_METHODS embedded_methods=
emb_store_result,
emb_fetch_lengths,
emb_flush_use_result,
+ emb_read_change_user_result,
emb_list_fields,
emb_read_prepare_result,
emb_stmt_execute,
@@ -436,7 +435,6 @@ MYSQL_METHODS embedded_methods=
emb_free_embedded_thd,
emb_read_statistics,
emb_read_query_result,
- emb_read_change_user_result,
emb_read_rows_from_cursor
};
@@ -584,6 +582,7 @@ void init_embedded_mysql(MYSQL *mysql, i
THD *thd = (THD *)mysql->thd;
thd->mysql= mysql;
mysql->server_version= server_version;
+ mysql->client_flag= client_flag;
init_alloc_root(&mysql->field_alloc, 8192, 0);
}
@@ -648,14 +647,19 @@ err:
int check_embedded_connection(MYSQL *mysql, const char *db)
{
int result;
+ LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 };
THD *thd= (THD*)mysql->thd;
thd_init_client_charset(thd, mysql->charset->number);
thd->update_charset();
Security_context *sctx= thd->security_ctx;
sctx->host_or_ip= sctx->host= (char*) my_localhost;
strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
- sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
- result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
+ strmake(sctx->priv_user, mysql->user, USERNAME_LENGTH-1);
+ sctx->user= my_strdup(mysql->user, MYF(0));
+ sctx->master_access= GLOBAL_ACLS; // Full rights
+ /* Change database if necessary */
+ if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE))))
+ my_ok(thd);
net_end_statement(thd);
emb_read_query_result(mysql);
return result;
@@ -664,14 +668,15 @@ int check_embedded_connection(MYSQL *mys
#else
int check_embedded_connection(MYSQL *mysql, const char *db)
{
+ /*
+ we emulate a COM_CHANGE_USER user here,
+ it's easier than to emulate the complete 3-way handshake
+ */
+ char buf[USERNAME_LENGTH + SCRAMBLE_LENGTH + 1 + 2*NAME_LEN + 2], *end;
+ NET *net= &mysql->net;
THD *thd= (THD*)mysql->thd;
Security_context *sctx= thd->security_ctx;
- int result;
- char scramble_buff[SCRAMBLE_LENGTH];
- int passwd_len;
- thd_init_client_charset(thd, mysql->charset->number);
- thd->update_charset();
if (mysql->options.client_ip)
{
sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
@@ -682,36 +687,44 @@ int check_embedded_connection(MYSQL *mys
sctx->host_or_ip= sctx->host;
if (acl_check_host(sctx->host, sctx->ip))
- {
- result= ER_HOST_NOT_PRIVILEGED;
goto err;
- }
- sctx->user= my_strdup(mysql->user, MYF(0));
+ /* construct a COM_CHANGE_USER packet */
+ end= strmake(buf, mysql->user, USERNAME_LENGTH) + 1;
+
+ memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
+ thd->scramble[SCRAMBLE_LENGTH]= 0;
+
if (mysql->passwd && mysql->passwd[0])
{
- memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
- thd->scramble[SCRAMBLE_LENGTH]= 0;
- scramble(scramble_buff, thd->scramble, mysql->passwd);
- passwd_len= SCRAMBLE_LENGTH;
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, thd->scramble, mysql->passwd);
+ end+= SCRAMBLE_LENGTH;
}
else
- passwd_len= 0;
+ *end++= 0;
- if((result= check_user(thd, COM_CONNECT,
- scramble_buff, passwd_len, db, true)))
- goto err;
+ end= strmake(end, db ? db : "", NAME_LEN) + 1;
- return 0;
-err:
+ int2store(end, (ushort) mysql->charset->number);
+ end+= 2;
+
+ /* acl_authenticate() takes the data from thd->net->read_pos */
+ thd->net.read_pos= (uchar*)buf;
+
+ if (acl_authenticate(thd, 0, end - buf))
{
- NET *net= &mysql->net;
- strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
- memcpy(net->sqlstate,
- mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
- sizeof(net->sqlstate)-1);
+ x_free(thd->security_ctx->user);
+ goto err;
}
- return result;
+ return 0;
+
+err:
+ strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
+ memcpy(net->sqlstate,
+ mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
+ sizeof(net->sqlstate)-1);
+ return 1;
}
#endif
=== modified file 'libmysqld/libmysqld.c'
--- a/libmysqld/libmysqld.c 2009-09-25 11:39:05 +0000
+++ b/libmysqld/libmysqld.c 2010-03-29 15:13:53 +0000
@@ -18,7 +18,6 @@
#include <mysql_embed.h>
#include <mysqld_error.h>
#include <my_pthread.h>
-#include "embedded_priv.h"
#include <my_sys.h>
#include <mysys_err.h>
#include <m_string.h>
@@ -28,6 +27,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
+#include "embedded_priv.h"
#include "client_settings.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -81,9 +81,9 @@ static my_bool is_NT(void)
** Shut down connection
**************************************************************************/
-static void end_server(MYSQL *mysql)
+void embedded_end_server(MYSQL *mysql)
{
- DBUG_ENTER("end_server");
+ DBUG_ENTER("embedded_end_server");
free_old_query(mysql);
DBUG_VOID_RETURN;
}
@@ -169,7 +169,11 @@ mysql_real_connect(MYSQL *mysql,const ch
client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_STATEMENTS)
client_flag|= CLIENT_MULTI_RESULTS;
- client_flag&= ~CLIENT_COMPRESS;
+ /*
+ no compression in embedded as we don't send any data,
+ and no pluggable auth, as we cannot do a client-server dialog
+ */
+ client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
@@ -216,7 +220,7 @@ error:
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;
- end_server(mysql);
+ embedded_end_server(mysql);
mysql->free_me=0;
mysql_close(mysql);
mysql->free_me=free_me;
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2010-03-17 02:32:31 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-02-19 08:10:05 +0000
@@ -1272,21 +1272,18 @@ sub command_line_setup {
if ($opt_gdb)
{
- mtr_warning("Silently converting --gdb to --client-gdb in embedded mode");
$opt_client_gdb= $opt_gdb;
$opt_gdb= undef;
}
if ($opt_ddd)
{
- mtr_warning("Silently converting --ddd to --client-ddd in embedded mode");
$opt_client_ddd= $opt_ddd;
$opt_ddd= undef;
}
if ($opt_debugger)
{
- mtr_warning("Silently converting --debugger to --client-debugger in embedded mode");
$opt_client_debugger= $opt_debugger;
$opt_debugger= undef;
}
@@ -5341,20 +5338,12 @@ sub gdb_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
else
{
# write init file for mysqld
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break mysql_parse\n" .
- "commands 1\n" .
- "disable 1\n" .
- "end\n" .
- "run");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
if ( $opt_manual_gdb )
@@ -5405,20 +5394,12 @@ sub ddd_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
else
{
# write init file for mysqld
- mtr_tofile($gdb_init_file,
- "file $$exe\n" .
- "set args $str\n" .
- "break mysql_parse\n" .
- "commands 1\n" .
- "disable 1\n" .
- "end");
+ mtr_tofile($gdb_init_file, "file $$exe\nset args $str\n");
}
if ( $opt_manual_ddd )
=== modified file 'mysql-test/r/change_user.result'
--- a/mysql-test/r/change_user.result 2009-02-12 14:08:56 +0000
+++ b/mysql-test/r/change_user.result 2010-03-29 15:13:53 +0000
@@ -1,3 +1,36 @@
+grant select on test.* to test_nopw;
+grant select on test.* to test_oldpw identified by password "09301740536db389";
+grant select on test.* to test_newpw identified by "newpw";
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_nopw@localhost> <test_nopw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_oldpw@localhost> <test_oldpw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_newpw@localhost> <test_newpw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_nopw@localhost> <test_nopw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_oldpw@localhost> <test_oldpw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_newpw@localhost> <test_newpw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> test
+drop user test_nopw;
+drop user test_oldpw;
+drop user test_newpw;
Bug#20023
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
=== modified file 'mysql-test/r/grant.result'
--- a/mysql-test/r/grant.result 2010-01-29 10:42:31 +0000
+++ b/mysql-test/r/grant.result 2010-03-29 15:13:53 +0000
@@ -13,8 +13,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'loc
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -44,15 +44,15 @@ delete from mysql.user where user='mysql
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
@@ -164,6 +164,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
=== modified file 'mysql-test/r/grant2.result'
--- a/mysql-test/r/grant2.result 2009-10-30 05:06:10 +0000
+++ b/mysql-test/r/grant2.result 2010-03-29 15:13:53 +0000
@@ -287,6 +287,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
create user mysqltest_A@'%';
rename user mysqltest_B@'%' to mysqltest_C@'%';
drop user mysqltest_C@'%';
@@ -354,6 +355,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
INSERT INTO mysql.db (host, db, user, select_priv) VALUES
('%','TESTDB','mysqltest_1','Y');
FLUSH PRIVILEGES;
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result 2009-12-26 11:25:56 +0000
+++ b/mysql-test/r/ps.result 2010-03-29 15:13:53 +0000
@@ -1194,13 +1194,13 @@ SET @aux= "SELECT COUNT(*)
prepare my_stmt from @aux;
execute my_stmt;
COUNT(*)
-39
+41
execute my_stmt;
COUNT(*)
-39
+41
execute my_stmt;
COUNT(*)
-39
+41
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
=== modified file 'mysql-test/r/sp_notembedded.result'
--- a/mysql-test/r/sp_notembedded.result 2010-01-11 13:15:28 +0000
+++ b/mysql-test/r/sp_notembedded.result 2010-03-29 15:13:53 +0000
@@ -191,6 +191,8 @@ max_updates, max_connections, max_user_c
VALUES('%', 'mysqltest_1', password(''), 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N',
'N', 'N', 'N', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'Y', 'Y', 'N', '',
'', '', '', '0', '0', '0', '0');
+Warnings:
+Warning 1364 Field 'auth_string' doesn't have a default value
FLUSH PRIVILEGES;
CREATE PROCEDURE p1(i INT) BEGIN END;
DROP PROCEDURE p1;
=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result 2009-10-27 10:09:36 +0000
+++ b/mysql-test/r/system_mysql_db.result 2010-03-29 15:13:53 +0000
@@ -118,6 +118,8 @@ user CREATE TABLE `user` (
`max_updates` int(11) unsigned NOT NULL DEFAULT '0',
`max_connections` int(11) unsigned NOT NULL DEFAULT '0',
`max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
+ `plugin` char(60) CHARACTER SET latin1 NOT NULL DEFAULT '',
+ `auth_string` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2009-10-28 09:23:02 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-03-29 15:13:53 +0000
@@ -178,6 +178,7 @@ NULL mysql time_zone_transition_type Tim
NULL mysql time_zone_transition_type Transition_type_id 2 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned PRI select,insert,update,references
NULL mysql user Alter_priv 17 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Alter_routine_priv 28 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
+NULL mysql user auth_string 41 NULL NO text 65535 65535 NULL NULL utf8 utf8_bin text select,insert,update,references
NULL mysql user Create_priv 8 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Create_routine_priv 27 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Create_tmp_table_priv 20 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -198,6 +199,7 @@ NULL mysql user max_questions 36 0 NO in
NULL mysql user max_updates 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
NULL mysql user max_user_connections 39 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
NULL mysql user Password 3 NO char 41 41 NULL NULL latin1 latin1_bin char(41) select,insert,update,references
+NULL mysql user plugin 40 NO char 60 60 NULL NULL latin1 latin1_swedish_ci char(60) select,insert,update,references
NULL mysql user Process_priv 12 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user References_priv 15 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Reload_priv 10 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -233,6 +235,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COL
1.0000 char latin1 latin1_bin
1.0000 char latin1 latin1_swedish_ci
1.0000 varchar latin1 latin1_swedish_ci
+1.0000 text utf8 utf8_bin
1.0000 mediumtext utf8 utf8_general_ci
1.0000 text utf8 utf8_general_ci
SELECT DISTINCT
@@ -497,3 +500,5 @@ NULL mysql user max_questions int NULL N
NULL mysql user max_updates int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_connections int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) unsigned
+1.0000 mysql user plugin char 60 60 latin1 latin1_swedish_ci char(60)
+1.0000 mysql user auth_string text 65535 65535 utf8 utf8_bin text
=== modified file 'mysql-test/suite/funcs_1/r/is_user_privileges.result'
--- a/mysql-test/suite/funcs_1/r/is_user_privileges.result 2008-03-07 19:18:14 +0000
+++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result 2010-03-29 15:13:53 +0000
@@ -76,10 +76,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
#
# Add GRANT OPTION db_datadict.* to testuser1;
GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
@@ -93,10 +93,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Establish connection testuser1 (user=testuser1)
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -105,10 +105,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -130,10 +130,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
#
# Here <SELECT YES> is shown correctly for testuser1;
@@ -147,10 +147,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -159,10 +159,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL SELECT YES
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION
@@ -207,10 +207,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -253,10 +253,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -265,10 +265,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -284,10 +284,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -309,10 +309,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
=== modified file 'mysql-test/suite/pbxt/r/grant.result'
--- a/mysql-test/suite/pbxt/r/grant.result 2009-11-24 10:19:08 +0000
+++ b/mysql-test/suite/pbxt/r/grant.result 2010-03-29 15:13:53 +0000
@@ -11,8 +11,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'loc
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -42,15 +42,15 @@ delete from mysql.user where user='mysql
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
@@ -162,6 +162,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
=== modified file 'mysql-test/suite/rpl/r/rpl_ignore_table.result'
--- a/mysql-test/suite/rpl/r/rpl_ignore_table.result 2008-11-13 19:19:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_ignore_table.result 2010-03-29 15:13:53 +0000
@@ -34,6 +34,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
GRANT SELECT ON *.* TO mysqltest6@localhost;
GRANT INSERT ON *.* TO mysqltest6@localhost;
GRANT INSERT ON test.* TO mysqltest6@localhost;
=== modified file 'mysql-test/suite/rpl/r/rpl_stm_000001.result'
--- a/mysql-test/suite/rpl/r/rpl_stm_000001.result 2009-11-18 14:50:31 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stm_000001.result 2010-03-29 15:13:53 +0000
@@ -66,6 +66,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
select select_priv,user from mysql.user where user = _binary'blafasel2';
select_priv user
N blafasel2
=== modified file 'mysql-test/t/change_user.test'
--- a/mysql-test/t/change_user.test 2009-10-28 07:52:34 +0000
+++ b/mysql-test/t/change_user.test 2010-03-29 15:13:53 +0000
@@ -1,4 +1,50 @@
#
+# functional change user tests
+#
+
+grant select on test.* to test_nopw;
+grant select on test.* to test_oldpw identified by password "09301740536db389";
+grant select on test.* to test_newpw identified by "newpw";
+
+#
+# massaging the data for tests to pass in the embedded server,
+# that has authentication completely disabled.
+#
+
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+change_user test_nopw;
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_oldpw, oldpw;
+--replace_result <@> <test_oldpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_newpw, newpw;
+--replace_result <@> <test_newpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user root;
+--replace_result <@> <root@localhost> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+change_user test_nopw,,test;
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_oldpw,oldpw,test;
+--replace_result <@> <test_oldpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_newpw,newpw,test;
+--replace_result <@> <test_newpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user root,,test;
+--replace_result <@> <root@localhost> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+drop user test_nopw;
+drop user test_oldpw;
+drop user test_newpw;
+
+#
# Bug#20023 mysql_change_user() resets the value of SQL_BIG_SELECTS
# The replace's are here to fix things for 32 bit systems
#
=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp 2010-03-10 09:11:02 +0000
+++ b/mysql-test/valgrind.supp 2010-02-19 08:12:25 +0000
@@ -1000,6 +1000,27 @@
fun:nptl_pthread_exit_hack_handler
}
+{
+ Invalid read within nptl_pthread_exit_hack_handler
+ Memcheck:Addr8
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/libc-*.so
+ obj:*/ld-*.so
+ obj:*/libc-*.so
+ fun:__libc_dlopen_mode
+ fun:pthread_cancel_init
+ fun:_Unwind_ForcedUnwind
+ fun:__pthread_unwind
+ fun:pthread_exit
+ fun:nptl_pthread_exit_hack_handler
+}
+
#
# Pthread doesn't free all thread specific memory before program exists
#
=== modified file 'mysys/Makefile.am'
--- a/mysys/Makefile.am 2009-12-03 11:19:05 +0000
+++ b/mysys/Makefile.am 2010-03-29 15:13:53 +0000
@@ -74,13 +74,13 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
# charset2html_DEPENDENCIES= $(LIBRARIES)
-DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+DEFS = -DDEFAULT_BASEDIR='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
+ -DSHAREDIR'="$(MYSQLSHAREdir)"' \
-DDEFAULT_HOME_ENV=MYSQL_HOME \
-DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
+ -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
@DEFS@
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
=== added directory 'plugin/auth'
=== added file 'plugin/auth/Makefile.am'
--- a/plugin/auth/Makefile.am 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/Makefile.am 2010-03-29 15:13:53 +0000
@@ -0,0 +1,15 @@
+pkgplugindir=$(pkglibdir)/plugin
+
+AM_LDFLAGS=-module -rpath $(pkgplugindir)
+AM_CPPFLAGS=-DMYSQL_DYNAMIC_PLUGIN -I$(top_srcdir)/include
+
+pkgplugin_LTLIBRARIES= dialog.la
+dialog_la_SOURCES= dialog.c
+
+if HAVE_PEERCRED
+pkgplugin_LTLIBRARIES+= auth_socket.la
+auth_socket_la_SOURCES= auth_socket.c
+endif
+
+EXTRA_DIST= plug.in
+
=== added file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/auth_socket.c 2010-03-29 15:13:53 +0000
@@ -0,0 +1,102 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ socket_peercred authentication plugin.
+
+ Authentication is successful if the connection is done via a unix socket and
+ the owner of the client process matches the user name that was used when
+ connecting to mysqld.
+*/
+#define _GNU_SOURCE /* for struct ucred */
+
+#include <mysql/plugin_auth.h>
+#include <sys/socket.h>
+#include <pwd.h>
+#include <string.h>
+
+/**
+ perform the unix socket based authentication
+
+ This authentication callback performs a unix socket based authentication -
+ it gets the uid of the client process and considers the user authenticated
+ if it uses username of this uid. That is - if the user is already
+ authenticated to the OS (if she is logged in) - she can use MySQL as herself
+*/
+
+static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ MYSQL_PLUGIN_VIO_INFO vio_info;
+ struct ucred cred;
+ socklen_t cred_len= sizeof(cred);
+ struct passwd pwd_buf, *pwd;
+ char buf[1024];
+
+ /* no user name yet ? read the client handshake packet with the user name */
+ if (info->user_name == 0)
+ {
+ if (vio->read_packet(vio, &pkt) < 0)
+ return CR_ERROR;
+ }
+
+ info->password_used = 0;
+
+ vio->info(vio, &vio_info);
+ if (vio_info.protocol != MYSQL_VIO_SOCKET)
+ return CR_ERROR;
+
+ /* get the UID of the client process */
+ if (getsockopt(vio_info.socket, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len))
+ return CR_ERROR;
+
+ if (cred_len != sizeof(cred))
+ return CR_ERROR;
+
+ /* and find the username for this uid */
+ getpwuid_r(cred.uid, &pwd_buf, buf, sizeof(buf), &pwd);
+ if (pwd == NULL)
+ return CR_ERROR;
+
+ /* now it's simple as that */
+ return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK;
+}
+
+static struct st_mysql_auth socket_auth_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ 0,
+ socket_auth
+};
+
+mysql_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+
=== added file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/dialog.c 2010-03-31 18:37:45 +0000
@@ -0,0 +1,308 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ dialog client authentication plugin with examples
+
+ dialog is a general purpose client authentication plugin, it simply
+ asks the user the question, as provided by the server and reports
+ the answer back to the server. No encryption is involved,
+ the answers are sent in clear text.
+
+ Two examples are provided: two_questions server plugin, that asks
+ the password and an "Are you sure?" question with a reply "yes, of course".
+ It demonstrates the usage of "password" (input is hidden) and "ordinary"
+ (input can be echoed) questions, and how to mark the last question,
+ to avoid an extra roundtrip.
+
+ And three_attempts plugin that gives the user three attempts to enter
+ a correct password. It shows the situation when a number of questions
+ is not known in advance.
+*/
+#define _GNU_SOURCE /* for RTLD_DEFAULT */
+
+#include <mysql/plugin_auth.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ first byte of the question string is the question "type".
+ It can be a "ordinary" or a "password" question.
+ The last bit set marks a last question in the authentication exchange.
+*/
+#define ORDINARY_QUESTION "\2"
+#define LAST_QUESTION "\3"
+#define PASSWORD_QUESTION "\4"
+#define LAST_PASSWORD "\5"
+
+typedef unsigned char uchar;
+
+/********************* SERVER SIDE ****************************************/
+
+/**
+ dialog demo with two questions, one password and one ordinary.
+*/
+
+static int two_questions(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len;
+
+ /* send a password question */
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"),
+ 18))
+ return CR_ERROR;
+
+ /* read the answer */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ /* fail if the password is wrong */
+ if (strcmp((char*) pkt, info->auth_string))
+ return CR_ERROR;
+
+ /* send the last, ordinary, question */
+ if (vio->write_packet(vio,
+ (const uchar*) (LAST_QUESTION "Are you sure ?"), 15))
+ return CR_ERROR;
+
+ /* read the answer */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ /* check the reply */
+ return strcmp((char*) pkt, "yes, of course") ? CR_ERROR : CR_OK;
+}
+
+static struct st_mysql_auth two_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog", /* requires dialog client plugin */
+ two_questions
+};
+
+
+/**
+ dialog demo where the number of questions is not known in advance
+*/
+
+static int three_attempts(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len, i;
+
+ for (i= 0; i < 3; i++)
+ {
+ /* send the prompt */
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"), 18))
+ return CR_ERROR;
+
+ /* read the password */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ /*
+ finish, if the password is correct.
+ note, that we did not mark the prompt packet as "last"
+ */
+ if (strcmp((char*) pkt, info->auth_string) == 0)
+ return CR_OK;
+ }
+
+ return CR_ERROR;
+}
+
+static struct st_mysql_auth three_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog", /* requires dialog client plugin */
+ three_attempts
+};
+
+mysql_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+
+/********************* CLIENT SIDE ***************************************/
+/*
+ This plugin performs a dialog with the user, asking questions and
+ reading answers. Depending on the client it may be desirable to do it
+ using GUI, or console, with or without curses, or read answers
+ from a smardcard, for example.
+
+ To support all this variety, the dialog plugin has a callback function
+ "authentication_dialog_ask". If the client has a function of this name
+ dialog plugin will use it for communication with the user. Otherwise
+ a default gets() based implementation will be used.
+*/
+#include <mysql.h>
+#include <dlfcn.h>
+
+static mysql_authentication_dialog_ask_t ask;
+
+static char *builtin_ask(MYSQL *mysql __attribute__((unused)),
+ int type __attribute__((unused)),
+ const char *prompt,
+ char *buf, int buf_len __attribute__((unused)))
+{
+ fputs(prompt, stdout);
+ fputc(' ', stdout);
+ if (gets(buf) == 0)
+ return 0;
+
+ return buf;
+}
+
+
+/**
+ The main function of the dialog plugin.
+
+ Read the prompt, ask the question, send the reply, repeat until
+ the server is satisfied.
+
+ @note
+ 1. this plugin shows how a client authentication plugin
+ may read a MySQL protocol OK packet internally - which is important
+ where a number of packets is not known in advance.
+ 2. the first byte of the prompt is special. it is not
+ shown to the user, but signals whether it is the last question
+ (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0),
+ and whether the input is a password (not echoed).
+ 3. the prompt is expected to be sent zero-terminated
+*/
+
+static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ unsigned char *pkt, cmd= 0;
+ int pkt_len, res;
+ char reply_buf[1024], *reply;
+
+ do
+ {
+ /* read the prompt */
+ pkt_len= vio->read_packet(vio, &pkt);
+ if (pkt_len < 0)
+ return CR_ERROR;
+
+ if (pkt == 0)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet, so
+ the first vio->read_packet() does nothing (pkt == 0).
+
+ We send the "password", assuming the client knows what its doing.
+ (in other words, the dialog plugin should be only set as a default
+ authentication plugin on the client if the first question
+ asks for a password - which will be sent in clear text, by the way)
+ */
+ reply= mysql->passwd;
+ }
+ else
+ {
+ cmd= *pkt++;
+
+ /* is it MySQL protocol packet ? */
+ if (cmd == 0 || cmd == 254)
+ return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */
+
+ /*
+ asking for a password with an empty prompt means mysql->password
+ otherwise we ask the user and read the reply
+ */
+ if ((cmd >> 1) == 2 && *pkt == 0)
+ reply= mysql->passwd;
+ else
+ reply= ask(mysql, cmd >> 1, (char*) pkt, reply_buf, sizeof(reply_buf));
+ if (!reply)
+ return CR_ERROR;
+ }
+ /* send the reply to the server */
+ res= vio->write_packet(vio, (uchar*) reply, strlen(reply)+1);
+
+ if (reply != mysql->passwd && reply != reply_buf)
+ free(reply);
+
+ if (res)
+ return CR_ERROR;
+
+ /* repeat unless it was the last question */
+ } while ((cmd & 1) != 1);
+
+ /* the job of reading the ok/error packet is left to the server */
+ return CR_OK;
+}
+
+
+/**
+ initialization function of the dialog plugin
+
+ Pick up the client's authentication_dialog_ask() function, if exists,
+ or fall back to the default implementation.
+*/
+
+static int init_dialog()
+{
+ void *sym= dlsym(RTLD_DEFAULT, "mysql_authentication_dialog_ask");
+ ask= sym ? (mysql_authentication_dialog_ask_t)sym : builtin_ask;
+ return 0;
+}
+
+mysql_declare_client_plugin(AUTHENTICATION)
+ "dialog",
+ "Sergei Golubchik",
+ "Dialog Client Authentication Plugin",
+ {0,1,0},
+ init_dialog,
+ NULL,
+ perform_dialog
+mysql_end_client_plugin;
+
=== added file 'plugin/auth/plug.in'
--- a/plugin/auth/plug.in 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/plug.in 2010-03-29 15:13:53 +0000
@@ -0,0 +1,15 @@
+MYSQL_PLUGIN(auth, [Collection of Authentication Plugins],
+ [Collection of Authentication Plugins])
+MYSQL_PLUGIN_DYNAMIC(auth, [dialog.la])
+MYSQL_PLUGIN_ACTIONS(auth,[
+AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#define _GNU_SOURCE
+#include <sys/socket.h>
+]],[[
+ struct ucred cred;
+ getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0);
+]])],have_peercred=yes)
+AM_CONDITIONAL(HAVE_PEERCRED, test x$have_peercred = xyes)
+])
+AM_CONDITIONAL(HAVE_PEERCRED, false)
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql 2009-10-27 10:09:36 +0000
+++ b/scripts/mysql_system_tables.sql 2010-03-29 15:13:53 +0000
@@ -13,7 +13,7 @@ set @had_db_table= @@warning_count != 0;
CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT
NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
-CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_rout
ine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
+CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_rout
ine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, auth_string TEXT NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
-- Remember for later if user table already existed
set @had_user_table= @@warning_count != 0;
=== modified file 'scripts/mysql_system_tables_data.sql'
--- a/scripts/mysql_system_tables_data.sql 2008-10-03 15:54:22 +0000
+++ b/scripts/mysql_system_tables_data.sql 2010-03-29 15:13:53 +0000
@@ -21,9 +21,9 @@ DROP TABLE tmp_db;
-- from local machine if "users" table didn't exist before
CREATE TEMPORARY TABLE tmp_user LIKE user;
set @current_hostname= @@hostname;
-INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
-REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost';
-REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
+REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','' FROM dual WHERE LOWER( @current_hostname) != 'localhost';
+REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
INSERT INTO tmp_user (host,user) VALUES ('localhost','');
INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost';
INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;
=== modified file 'scripts/mysql_system_tables_fix.sql'
--- a/scripts/mysql_system_tables_fix.sql 2009-12-03 16:15:47 +0000
+++ b/scripts/mysql_system_tables_fix.sql 2010-03-29 15:13:53 +0000
@@ -571,6 +571,9 @@ ALTER TABLE tables_priv MODIFY Table_pri
UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0;
+ALTER TABLE user ADD plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, ADD auth_string TEXT NOT NULL;
+ALTER TABLE user MODIFY plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL;
+
# Activate the new, possible modified privilege tables
# This should not be needed, but gives us some extra testing that the above
# changes was correct
=== modified file 'server-tools/instance-manager/Makefile.am'
--- a/server-tools/instance-manager/Makefile.am 2007-02-18 12:45:28 +0000
+++ b/server-tools/instance-manager/Makefile.am 2010-03-29 15:13:53 +0000
@@ -46,7 +46,8 @@ libnet_a_LIBADD= $(top_builddir)/sql/pas
$(top_builddir)/sql/pack.$(OBJEXT) \
$(top_builddir)/sql/sql_state.$(OBJEXT) \
$(top_builddir)/sql/mini_client_errors.$(OBJEXT)\
- $(top_builddir)/sql/client.$(OBJEXT)
+ $(top_builddir)/sql/client.$(OBJEXT) \
+ $(top_builddir)/sql/client_plugin.$(OBJEXT)
CLEANFILES= net_serv.cc client_settings.h
@@ -91,7 +92,7 @@ mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAG
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
$(top_builddir)/dbug/libdbug.a \
- @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@
+ @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@ @LIBDL@
EXTRA_DIST = WindowsService.cpp WindowsService.h IMService.cpp \
IMService.h CMakeLists.txt
=== modified file 'server-tools/instance-manager/user_map.cc'
--- a/server-tools/instance-manager/user_map.cc 2009-12-18 19:14:09 +0000
+++ b/server-tools/instance-manager/user_map.cc 2010-03-29 15:13:53 +0000
@@ -368,7 +368,7 @@ int User_map::authenticate(const LEX_STR
const char *scramble) const
{
const User *user= find_user(user_name);
- return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
+ return user ? check_scramble((uchar*)scrambled_password, scramble, user->salt) : 2;
}
=== modified file 'sql-common/Makefile.am'
--- a/sql-common/Makefile.am 2006-12-31 00:02:27 +0000
+++ b/sql-common/Makefile.am 2010-03-29 15:13:53 +0000
@@ -14,7 +14,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## Process this file with automake to create Makefile.in
-EXTRA_DIST = client.c pack.c my_time.c my_user.c
+EXTRA_DIST = client.c pack.c my_time.c my_user.c client_plugin.c
# Don't update the files from bitkeeper
%::SCCS/s.%
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2010-02-01 06:14:12 +0000
+++ b/sql-common/client.c 2010-03-29 15:13:53 +0000
@@ -107,6 +107,10 @@ my_bool net_flush(NET *net);
#include "client_settings.h"
#include <sql_common.h>
+#include <mysql/client_plugin.h>
+
+#define native_password_plugin_name "mysql_native_password"
+#define old_password_plugin_name "mysql_old_password"
uint mysql_port=0;
char *mysql_unix_port= 0;
@@ -332,7 +336,7 @@ void net_clear_error(NET *net)
@param ... variable number of arguments
*/
-static void set_mysql_extended_error(MYSQL *mysql, int errcode,
+void set_mysql_extended_error(MYSQL *mysql, int errcode,
const char *sqlstate,
const char *format, ...)
{
@@ -1002,9 +1006,20 @@ static const char *default_options[]=
"replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
- "report-data-truncation",
+ "report-data-truncation", "plugin-dir", "default-auth",
NullS
};
+enum option_id {
+ OPT_port=1, OPT_socket, OPT_compress, OPT_password, OPT_pipe, OPT_timeout, OPT_user,
+ OPT_init_command, OPT_host, OPT_database, OPT_debug, OPT_return_found_rows,
+ OPT_ssl_key, OPT_ssl_cert, OPT_ssl_ca, OPT_ssl_capath,
+ OPT_character_sets_dir, OPT_default_character_set, OPT_interactive_timeout,
+ OPT_connect_timeout, OPT_local_infile, OPT_disable_local_infile,
+ OPT_replication_probe, OPT_enable_reads_from_master, OPT_repl_parse_query,
+ OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
+ OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
+ OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
+};
static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options, NULL};
@@ -1035,6 +1050,15 @@ static int add_init_command(struct st_my
return 0;
}
+#define extension_set_string(OPTS, X, STR) \
+ if ((OPTS)->extension) \
+ my_free((OPTS)->extension->X, MYF(MY_ALLOW_ZERO_PTR)); \
+ else \
+ (OPTS)->extension= (struct st_mysql_options_extention *) \
+ my_malloc(sizeof(struct st_mysql_options_extention), \
+ MYF(MY_WME | MY_ZEROFILL)); \
+ (OPTS)->extension->X= my_strdup((STR), MYF(MY_WME));
+
void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
{
@@ -1067,134 +1091,134 @@ void mysql_read_default_options(struct s
for (end= *option ; *(end= strcend(end,'_')) ; )
*end= '-';
switch (find_type(*option+2,&option_types,2)) {
- case 1: /* port */
+ case OPT_port:
if (opt_arg)
options->port=atoi(opt_arg);
break;
- case 2: /* socket */
+ case OPT_socket:
if (opt_arg)
{
my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 3: /* compress */
+ case OPT_compress:
options->compress=1;
options->client_flag|= CLIENT_COMPRESS;
break;
- case 4: /* password */
+ case OPT_password:
if (opt_arg)
{
my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
options->password=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 5:
+ case OPT_pipe:
options->protocol = MYSQL_PROTOCOL_PIPE;
- case 20: /* connect_timeout */
- case 6: /* timeout */
+ case OPT_connect_timeout:
+ case OPT_timeout:
if (opt_arg)
options->connect_timeout=atoi(opt_arg);
break;
- case 7: /* user */
+ case OPT_user:
if (opt_arg)
{
my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
options->user=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 8: /* init-command */
+ case OPT_init_command:
add_init_command(options,opt_arg);
break;
- case 9: /* host */
+ case OPT_host:
if (opt_arg)
{
my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
options->host=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 10: /* database */
+ case OPT_database:
if (opt_arg)
{
my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
options->db=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 11: /* debug */
+ case OPT_debug:
#ifdef MYSQL_CLIENT
mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
break;
#endif
- case 12: /* return-found-rows */
+ case OPT_return_found_rows:
options->client_flag|=CLIENT_FOUND_ROWS;
break;
#ifdef HAVE_OPENSSL
- case 13: /* ssl_key */
+ case OPT_ssl_key:
my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 14: /* ssl_cert */
+ case OPT_ssl_cert:
my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 15: /* ssl_ca */
+ case OPT_ssl_ca:
my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 16: /* ssl_capath */
+ case OPT_ssl_capath:
my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 26: /* ssl_cipher */
+ case OPT_ssl_cipher:
my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
break;
#else
- case 13: /* Ignore SSL options */
- case 14:
- case 15:
- case 16:
- case 26:
+ case OPT_ssl_key:
+ case OPT_ssl_cert:
+ case OPT_ssl_ca:
+ case OPT_ssl_capath:
+ case OPT_ssl_cipher:
break;
#endif /* HAVE_OPENSSL */
- case 17: /* charset-lib */
+ case OPT_character_sets_dir:
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 18:
+ case OPT_default_character_set:
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 19: /* Interactive-timeout */
+ case OPT_interactive_timeout:
options->client_flag|= CLIENT_INTERACTIVE;
break;
- case 21:
+ case OPT_local_infile:
if (!opt_arg || atoi(opt_arg) != 0)
options->client_flag|= CLIENT_LOCAL_FILES;
else
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 22:
+ case OPT_disable_local_infile:
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 23: /* replication probe */
+ case OPT_replication_probe:
#ifndef TO_BE_DELETED
options->rpl_probe= 1;
#endif
break;
- case 24: /* enable-reads-from-master */
+ case OPT_enable_reads_from_master:
options->no_master_reads= 0;
break;
- case 25: /* repl-parse-query */
+ case OPT_repl_parse_query:
#ifndef TO_BE_DELETED
options->rpl_parse= 1;
#endif
break;
- case 27:
+ case OPT_max_allowed_packet:
if (opt_arg)
options->max_allowed_packet= atoi(opt_arg);
break;
- case 28: /* protocol */
+ case OPT_protocol:
if ((options->protocol= find_type(opt_arg,
&sql_protocol_typelib,0)) <= 0)
{
@@ -1202,26 +1226,32 @@ void mysql_read_default_options(struct s
exit(1);
}
break;
- case 29: /* shared_memory_base_name */
+ case OPT_shared_memory_base_name:
#ifdef HAVE_SMEM
if (options->shared_memory_base_name != def_shared_memory_base_name)
my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
#endif
break;
- case 30:
+ case OPT_multi_results:
options->client_flag|= CLIENT_MULTI_RESULTS;
break;
- case 31:
- case 32:
+ case OPT_multi_statements:
+ case OPT_multi_queries:
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break;
- case 33: /* secure-auth */
+ case OPT_secure_auth:
options->secure_auth= TRUE;
break;
- case 34: /* report-data-truncation */
+ case OPT_report_data_truncation:
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
break;
+ case OPT_plugin_dir:
+ extension_set_string(options, plugin_dir, opt_arg);
+ break;
+ case OPT_default_auth:
+ extension_set_string(options, default_auth, opt_arg);
+ break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -1765,6 +1795,11 @@ static int ssl_verify_server_cert(Vio *v
static my_bool cli_read_query_result(MYSQL *mysql);
static MYSQL_RES *cli_use_result(MYSQL *mysql);
+int cli_read_change_user_result(MYSQL *mysql)
+{
+ return cli_safe_read(mysql);
+}
+
static MYSQL_METHODS client_methods=
{
cli_read_query_result, /* read_query_result */
@@ -1772,7 +1807,8 @@ static MYSQL_METHODS client_methods=
cli_read_rows, /* read_rows */
cli_use_result, /* use_result */
cli_fetch_lengths, /* fetch_lengths */
- cli_flush_use_result /* flush_use_result */
+ cli_flush_use_result, /* flush_use_result */
+ cli_read_change_user_result /* read_change_user_result */
#ifndef MYSQL_SERVER
,cli_list_fields, /* list_fields */
cli_read_prepare_result, /* read_prepare_result */
@@ -1782,7 +1818,6 @@ static MYSQL_METHODS client_methods=
NULL, /* free_embedded_thd */
cli_read_statistics, /* read_statistics */
cli_read_query_result, /* next_result */
- cli_read_change_user_result, /* read_change_user_result */
cli_read_binary_rows /* read_rows_from_cursor */
#endif
};
@@ -1856,6 +1891,646 @@ int mysql_init_character_set(MYSQL *mysq
}
C_MODE_END
+/*********** client side authentication support **************************/
+
+typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
+static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+
+static auth_plugin_t native_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ native_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Native MySQL authentication",
+ {1, 0, 0},
+ NULL,
+ NULL,
+ native_password_auth_client
+};
+
+static auth_plugin_t old_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ old_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Old MySQL-3.23 authentication",
+ {1, 0, 0},
+ NULL,
+ NULL,
+ old_password_auth_client
+};
+
+struct st_mysql_client_plugin *mysql_client_builtins[]=
+{
+ (struct st_mysql_client_plugin *)&native_password_client_plugin,
+ (struct st_mysql_client_plugin *)&old_password_client_plugin,
+ 0
+};
+
+
+
+/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
+typedef struct {
+ int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
+ int (*write_packet)(struct st_plugin_vio *vio, const uchar *pkt, int pkt_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+ /* -= end of MYSQL_PLUGIN_VIO =- */
+ MYSQL *mysql;
+ auth_plugin_t *plugin; /**< what plugin we're under */
+ const char *db;
+ struct {
+ uchar *pkt; /**< pointer into NET::buff */
+ uint pkt_len;
+ } cached_server_reply;
+ uint packets_read, packets_written; /**< counters for send/received packets */
+ my_bool mysql_change_user; /**< if it's mysql_change_user() */
+ int last_read_packet_len; /**< the length of the last *read* packet */
+} MCPVIO_EXT;
+
+/**
+ sends a COM_CHANGE_USER command with a caller provided payload
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ n user name - \0-terminated string
+ n password
+ 3.23 scramble - \0-terminated string (9 bytes)
+ otherwise - length (1 byte) coded
+ n database name - \0-terminated string
+ 2 character set number (if the server >= 4.1.x)
+ n client auth plugin name - \0-terminated string,
+ (if the server supports plugin auth)
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static int send_change_user_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ char *buff, *end;
+ int res= 1;
+
+ buff= my_alloca(USERNAME_LENGTH + data_len + 1 + NAME_LEN + 2 + NAME_LEN);
+
+ end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;
+
+ if (!data_len)
+ *end++= 0;
+ else
+ {
+ if (mysql->client_flag & CLIENT_SECURE_CONNECTION)
+ {
+ DBUG_ASSERT(data_len <= 255);
+ if (data_len > 255)
+ {
+ set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+ goto error;
+ }
+ *end++= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1);
+ DBUG_ASSERT(data[SCRAMBLE_LENGTH_323] == 0);
+ }
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ end= strmake(end, mpvio->db ? mpvio->db : "", NAME_LEN) + 1;
+
+ if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
+ {
+ int2store(end, (ushort) mysql->charset->number);
+ end+= 2;
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ res= simple_command(mysql, COM_CHANGE_USER,
+ (uchar*)buff, (ulong)(end-buff), 1);
+
+error:
+ my_afree(buff);
+ return res;
+}
+
+
+/**
+ sends a client authentication packet (second packet in the 3-way handshake)
+
+ Packet format (when the server is 4.0 or earlier):
+
+ Bytes Content
+ ----- ----
+ 2 client capabilities
+ 3 max packet size
+ n user name, \0-terminated
+ 9 scramble_323, \0-terminated
+
+ Packet format (when the server is 4.1 or newer):
+
+ Bytes Content
+ ----- ----
+ 4 client capabilities
+ 4 max packet size
+ 1 charset number
+ 23 reserved (always 0)
+ n user name, \0-terminated
+ n plugin auth data (e.g. scramble), length (1 byte) coded
+ n database name, \0-terminated
+ (if CLIENT_CONNECT_WITH_DB is set in the capabilities)
+ n client auth plugin name - \0-terminated string,
+ (if CLIENT_PLUGIN_AUTH is set in the capabilities)
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static int send_client_reply_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ NET *net= &mysql->net;
+ char *buff, *end;
+
+ /* see end= buff+32 below, fixed size of the packet is 32 bytes */
+ buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN);
+
+ mysql->client_flag|= mysql->options.client_flag;
+ mysql->client_flag|= CLIENT_CAPABILITIES;
+
+ if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
+ mysql->client_flag|= CLIENT_MULTI_RESULTS;
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+ if (mysql->options.ssl_key || mysql->options.ssl_cert ||
+ mysql->options.ssl_ca || mysql->options.ssl_capath ||
+ mysql->options.ssl_cipher)
+ mysql->options.use_ssl= 1;
+ if (mysql->options.use_ssl)
+ mysql->client_flag|= CLIENT_SSL;
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
+ if (mpvio->db)
+ mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
+
+ /* Remove options that server doesn't support */
+ mysql->client_flag= mysql->client_flag &
+ (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)
+ | mysql->server_capabilities);
+
+#ifndef HAVE_COMPRESS
+ mysql->client_flag&= ~CLIENT_COMPRESS;
+#endif
+
+ if (mysql->client_flag & CLIENT_PROTOCOL_41)
+ {
+ /* 4.1 server and 4.1 client has a 32 byte option flag */
+ int4store(buff,mysql->client_flag);
+ int4store(buff+4, net->max_packet_size);
+ buff[8]= (char) mysql->charset->number;
+ bzero(buff+9, 32-9);
+ end= buff+32;
+ }
+ else
+ {
+ int2store(buff, mysql->client_flag);
+ int3store(buff+2, net->max_packet_size);
+ end= buff+5;
+ }
+#ifdef HAVE_OPENSSL
+ if (mysql->client_flag & CLIENT_SSL)
+ {
+ /* Do the SSL layering. */
+ struct st_mysql_options *options= &mysql->options;
+ struct st_VioSSLFd *ssl_fd;
+ char error_string[1024];
+
+ /*
+ Send mysql->client_flag, max_packet_size - unencrypted otherwise
+ the server does not know we want to do SSL
+ */
+ if (my_net_write(net, (uchar*)buff, (size_t) (end-buff)) || net_flush(net))
+ {
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending connection information to server",
+ errno);
+ goto error;
+ }
+
+ /* Create the VioSSLConnectorFd - init SSL and load certs */
+ if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
+ options->ssl_cert,
+ options->ssl_ca,
+ options->ssl_capath,
+ options->ssl_cipher)))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+ mysql->connector_fd= (void*)ssl_fd;
+
+ /* Connect to the server */
+ DBUG_PRINT("info", ("IO layer change in progress..."));
+ if (sslconnect(ssl_fd, net->vio,
+ (long) (mysql->options.connect_timeout),
+ error_string))
+ {
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
+ unknown_sqlstate, "SSL error: %s",
+ error_string[0] ? error_string :
+ ER(CR_SSL_CONNECTION_ERROR));
+ goto error;
+ }
+ DBUG_PRINT("info", ("IO layer change done!"));
+
+ /* Verify server cert */
+ if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
+ ssl_verify_server_cert(net->vio, mysql->host))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+ }
+#endif /* HAVE_OPENSSL */
+
+ DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
+ mysql->server_version, mysql->server_capabilities,
+ mysql->server_status, mysql->client_flag));
+
+ compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
+
+ /* This needs to be changed as it's not useful with big packets */
+ if (mysql->user[0])
+ strmake(end, mysql->user, USERNAME_LENGTH);
+ else
+ read_user_name(end);
+
+ /* We have to handle different version of handshake here */
+ DBUG_PRINT("info",("user: %s",end));
+ end= strend(end) + 1;
+ if (data_len)
+ {
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ *end++= data_len;
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ }
+ else
+ *end++= 0;
+
+ /* Add database if needed */
+ if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
+ {
+ end= strmake(end, mpvio->db, NAME_LEN) + 1;
+ mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ /* Write authentication package */
+ if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
+ {
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ goto error;
+ }
+ my_afree(buff);
+ return 0;
+
+error:
+ my_afree(buff);
+ return 1;
+}
+
+
+/**
+ vio->read_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to read data from the server.
+*/
+
+static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+ MYSQL *mysql= mpvio->mysql;
+ ulong pkt_len;
+
+ /* there are cached data left, feed it to a plugin */
+ if (mpvio->cached_server_reply.pkt)
+ {
+ *buf= mpvio->cached_server_reply.pkt;
+ mpvio->cached_server_reply.pkt= 0;
+ mpvio->packets_read++;
+ return mpvio->cached_server_reply.pkt_len;
+ }
+
+ if (mpvio->packets_read == 0)
+ {
+ /*
+ the server handshake packet came from the wrong plugin,
+ or it's mysql_change_user(). Either way, there is no data
+ for a plugin to read. send a dummy packet to the server
+ to initiate a dialog.
+ */
+ if (client_mpvio_write_packet(mpv, 0, 0))
+ return (int)packet_error;
+ }
+
+ /* otherwise read the data */
+ pkt_len= (*mysql->methods->read_change_user_result)(mysql);
+ mpvio->last_read_packet_len= pkt_len;
+ *buf= mysql->net.read_pos;
+
+ /* was it a request to change plugins ? */
+ if (**buf == 254)
+ return (int)packet_error; /* if yes, this plugin shan't continue */
+
+ /*
+ the server sends \1\255 or \1\254 instead of just \255 or \254 -
+ for us to not confuse it with an error or "change plugin" packets.
+ We remove this escaping \1 here.
+
+ See also server_mpvio_write_packet() where the escaping is done.
+ */
+ if (pkt_len && **buf == 1)
+ {
+ (*buf)++;
+ pkt_len--;
+ }
+ mpvio->packets_read++;
+ return pkt_len;
+}
+
+
+/**
+ vio->write_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to send data to the server.
+
+ It transparently wraps the data into a change user or authentication
+ handshake packet, if neccessary.
+*/
+
+static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
+ const uchar *pkt, int pkt_len)
+{
+ int res;
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+
+ if (mpvio->packets_written == 0)
+ {
+ if (mpvio->mysql_change_user)
+ res= send_change_user_packet(mpvio, pkt, pkt_len);
+ else
+ res= send_client_reply_packet(mpvio, pkt, pkt_len);
+ }
+ else
+ {
+ NET *net= &mpvio->mysql->net;
+ if (mpvio->mysql->thd)
+ res= 1; /* no chit-chat in embedded */
+ else
+ res= my_net_write(net, pkt, pkt_len) || net_flush(net);
+ if (res)
+ set_mysql_extended_error(mpvio->mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
+{
+ bzero(info, sizeof(*info));
+ switch (vio->type) {
+ case VIO_TYPE_TCPIP:
+ info->protocol= MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ case VIO_TYPE_SOCKET:
+ info->protocol= MYSQL_VIO_SOCKET;
+ info->socket= vio->sd;
+ return;
+ case VIO_TYPE_SSL:
+ {
+ struct sockaddr addr;
+ socklen_t addrlen= sizeof(addr);
+ if (getsockname(vio->sd, &addr, &addrlen))
+ return;
+ info->protocol= addr.sa_family == AF_UNIX ?
+ MYSQL_VIO_SOCKET : MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ }
+#ifdef _WIN32
+ case VIO_TYPE_NAMEDPIPE:
+ info->protocol= MYSQL_VIO_PIPE;
+ info->handle= vio->hPipe;
+ return;
+ case VIO_TYPE_SHARED_MEMORY:
+ info->protocol= MYSQL_VIO_MEMORY;
+ info->handle= vio->handle_client_file_map; /* or what ? */
+ return;
+#endif
+ default: DBUG_ASSERT(0);
+ }
+}
+
+
+static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)vio;
+ mpvio_info(mpvio->mysql->net.vio, info);
+}
+
+
+/**
+ Client side of the plugin driver authentication.
+
+ @note this is used by both the mysql_real_connect and mysql_change_user
+
+ @param mysql mysql
+ @param data pointer to the plugin auth data (scramble) in the
+ handshake packet
+ @param data_len the length of the data
+ @param data_plugin a plugin that data were prepared for
+ or 0 if it's mysql_change_user()
+ @param db initial db to use, can be 0
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ char *data_plugin, const char *db)
+{
+ const char *auth_plugin_name;
+ auth_plugin_t *auth_plugin;
+ MCPVIO_EXT mpvio;
+ ulong pkt_length;
+ int res;
+
+ /* determine the default/initial plugin to use */
+ if (mysql->options.extension && mysql->options.extension->default_auth &&
+ mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ auth_plugin_name= mysql->options.extension->default_auth;
+ if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ return 1; /* oops, not found */
+ }
+ else
+ {
+ auth_plugin= mysql->server_capabilities & CLIENT_PROTOCOL_41 ?
+ &native_password_client_plugin : &old_password_client_plugin;
+ auth_plugin_name= auth_plugin->name;
+ }
+
+ mysql->net.last_errno= 0; /* just in case */
+
+ if (data_plugin && strcmp(data_plugin, auth_plugin_name))
+ {
+ /* data was prepared for a different plugin, don't show it to this one */
+ data= 0;
+ data_len= 0;
+ }
+
+ mpvio.mysql_change_user= data_plugin == 0;
+ mpvio.cached_server_reply.pkt= (uchar*)data;
+ mpvio.cached_server_reply.pkt_len= data_len;
+ mpvio.read_packet= client_mpvio_read_packet;
+ mpvio.write_packet= client_mpvio_write_packet;
+ mpvio.info= client_mpvio_info;
+ mpvio.mysql= mysql;
+ mpvio.packets_read= mpvio.packets_written= 0;
+ mpvio.db= db;
+ mpvio.plugin= auth_plugin;
+
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ compile_time_assert(CR_OK == -1);
+ compile_time_assert(CR_ERROR == 0);
+ if (res > CR_OK && mysql->net.read_pos[0] != 254)
+ {
+ /*
+ the plugin returned an error. write it down in mysql,
+ unless the error code is CR_ERROR and mysql->net.last_errno
+ is already set (the plugin has done it)
+ */
+ if (res > CR_ERROR)
+ set_mysql_error(mysql, res, unknown_sqlstate);
+ else
+ if (!mysql->net.last_errno)
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return 1;
+ }
+
+ /* read the OK packet (or use the cached value in mysql->net.read_pos */
+ if (res == CR_OK)
+ pkt_length= (*mysql->methods->read_change_user_result)(mysql);
+ else /* res == CR_OK_HANDSHAKE_COMPLETE */
+ pkt_length= mpvio.last_read_packet_len;
+
+ if (pkt_length == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading authorization packet",
+ errno);
+ return 1;
+ }
+
+ if (mysql->net.read_pos[0] == 254)
+ {
+ /* The server asked to use a different authentication plugin */
+ if (pkt_length == 1)
+ {
+ /* old "use short scramble" packet */
+ auth_plugin_name= old_password_plugin_name;
+ mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble;
+ mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* new "use different plugin" packet */
+ uint len;
+ auth_plugin_name= (char*)mysql->net.read_pos + 1;
+ len= strlen(auth_plugin_name); /* safe as my_net_read always appends \0 */
+ mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
+ mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
+ }
+
+ if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ return 1;
+
+ mpvio.plugin= auth_plugin;
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ if (res > CR_OK)
+ {
+ if (res > CR_ERROR)
+ set_mysql_error(mysql, res, unknown_sqlstate);
+ else
+ if (!mysql->net.last_errno)
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return 1;
+ }
+
+ if (res != CR_OK_HANDSHAKE_COMPLETE)
+ {
+ /* Read what server thinks about out new auth message report */
+ if (cli_safe_read(mysql) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading final connect information",
+ errno);
+ return 1;
+ }
+ }
+ }
+ /*
+ net->read_pos[0] should always be 0 here if the server implements
+ the protocol correctly
+ */
+ return mysql->net.read_pos[0] != 0;
+}
+
MYSQL * STDCALL
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
@@ -1863,8 +2538,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100];
- char error_string[1024];
- char *end,*host_info= NULL;
+ int scramble_data_len, pkt_scramble_len;
+ char *end, *host_info=0, *server_version_end, *pkt_end;
+ char *scramble_data, *scramble_plugin;
my_socket sock;
in_addr_t ip_addr;
struct sockaddr_in sock_addr;
@@ -2180,8 +2856,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
errno);
goto error;
}
+ pkt_end= (char*)net->read_pos + pkt_length;
/* Check if version of protocol matches current one */
-
mysql->protocol_version= net->read_pos[0];
DBUG_DUMP("packet",(uchar*) net->read_pos,10);
DBUG_PRINT("info",("mysql protocol version %d, server=%d",
@@ -2193,31 +2869,29 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
PROTOCOL_VERSION);
goto error;
}
- end=strend((char*) net->read_pos+1);
+ server_version_end= end= strend((char*) net->read_pos+1);
mysql->thread_id=uint4korr(end+1);
end+=5;
/*
- Scramble is split into two parts because old clients does not understand
+ Scramble is split into two parts because old clients do not understand
long scrambles; here goes the first part.
*/
- strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
- end+= SCRAMBLE_LENGTH_323+1;
+ scramble_data= end;
+ scramble_data_len= SCRAMBLE_LENGTH_323 + 1;
+ scramble_plugin= old_password_plugin_name;
+ end+= scramble_data_len;
- if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
+ if (pkt_end >= end + 1)
mysql->server_capabilities=uint2korr(end);
- if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
+ if (pkt_end >= end + 18)
{
/* New protocol with 16 bytes to describe server characteristics */
mysql->server_language=end[2];
mysql->server_status=uint2korr(end+3);
+ mysql->server_capabilities|= uint2korr(end+5) << 16;
+ pkt_scramble_len= end[7];
}
end+= 18;
- if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
- (char *) net->read_pos))
- strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
- SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
- else
- mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
if (mysql->options.secure_auth && passwd[0] &&
!(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
@@ -2236,7 +2910,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
&mysql->unix_socket,unix_socket ?
(uint) strlen(unix_socket)+1 : (uint) 1,
&mysql->server_version,
- (uint) (end - (char*) net->read_pos),
+ (uint) (server_version_end - (char*) net->read_pos + 1),
NullS) ||
!(mysql->user=my_strdup(user,MYF(0))) ||
!(mysql->passwd=my_strdup(passwd,MYF(0))))
@@ -2253,203 +2927,47 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port;
- /*
- Part 2: format and send client info to the server for access check
- */
-
- client_flag|=mysql->options.client_flag;
- client_flag|=CLIENT_CAPABILITIES;
- if (client_flag & CLIENT_MULTI_STATEMENTS)
- client_flag|= CLIENT_MULTI_RESULTS;
-
-#ifdef HAVE_OPENSSL
- if (mysql->options.ssl_key || mysql->options.ssl_cert ||
- mysql->options.ssl_ca || mysql->options.ssl_capath ||
- mysql->options.ssl_cipher)
- mysql->options.use_ssl= 1;
- if (mysql->options.use_ssl)
- client_flag|=CLIENT_SSL;
-#endif /* HAVE_OPENSSL */
- if (db)
- client_flag|=CLIENT_CONNECT_WITH_DB;
-
- /* Remove options that server doesn't support */
- client_flag= ((client_flag &
- ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
- (client_flag & mysql->server_capabilities));
-#ifndef HAVE_COMPRESS
- client_flag&= ~CLIENT_COMPRESS;
-#endif
-
- if (client_flag & CLIENT_PROTOCOL_41)
- {
- /* 4.1 server and 4.1 client has a 32 byte option flag */
- int4store(buff,client_flag);
- int4store(buff+4, net->max_packet_size);
- buff[8]= (char) mysql->charset->number;
- bzero(buff+9, 32-9);
- end= buff+32;
- }
- else
- {
- int2store(buff,client_flag);
- int3store(buff+2,net->max_packet_size);
- end= buff+5;
- }
- mysql->client_flag=client_flag;
-
-#ifdef HAVE_OPENSSL
- if (client_flag & CLIENT_SSL)
+ if (pkt_end >= end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1)
{
- /* Do the SSL layering. */
- struct st_mysql_options *options= &mysql->options;
- struct st_VioSSLFd *ssl_fd;
-
/*
- Send client_flag, max_packet_size - unencrypted otherwise
- the server does not know we want to do SSL
+ move the first scramble part - directly in the NET buffer -
+ to get a full continuous scramble. We've read all the header,
+ and can overwrite it now.
*/
- if (my_net_write(net, (uchar*) buff, (uint) (end-buff)) || net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending connection information to server",
- errno);
- goto error;
- }
-
- /* Create the VioSSLConnectorFd - init SSL and load certs */
- if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
- options->ssl_cert,
- options->ssl_ca,
- options->ssl_capath,
- options->ssl_cipher)))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
- goto error;
- }
- mysql->connector_fd= (void*)ssl_fd;
-
- /* Connect to the server */
- DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslconnect(ssl_fd, mysql->net.vio,
- (long) (mysql->options.connect_timeout),
- error_string))
- {
- set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
- unknown_sqlstate,
- "SSL error: %s",
- error_string[0] ? error_string :
- ER(CR_SSL_CONNECTION_ERROR));
- goto error;
- }
- DBUG_PRINT("info", ("IO layer change done!"));
-
- /* Verify server cert */
- if ((client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
- ssl_verify_server_cert(mysql->net.vio, mysql->host))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
- goto error;
- }
-
- }
-#endif /* HAVE_OPENSSL */
-
- DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
- mysql->server_version,mysql->server_capabilities,
- mysql->server_status, client_flag));
- /* This needs to be changed as it's not useful with big packets */
- if (user && user[0])
- strmake(end,user,USERNAME_LENGTH); /* Max user name */
- else
- read_user_name((char*) end);
-
- /* We have to handle different version of handshake here */
-#ifdef _CUSTOMCONFIG_
-#include "_cust_libmysql.h"
-#endif
- DBUG_PRINT("info",("user: %s",end));
- end= strend(end) + 1;
- if (passwd[0])
- {
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- *end++= SCRAMBLE_LENGTH;
- scramble(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH;
+ memmove(end - SCRAMBLE_LENGTH_323, scramble_data,
+ SCRAMBLE_LENGTH_323);
+ scramble_data= end - SCRAMBLE_LENGTH_323;
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ scramble_data_len= pkt_scramble_len;
+ scramble_plugin= scramble_data + scramble_data_len;
+ if (scramble_data + scramble_data_len > pkt_end)
+ scramble_data_len= pkt_end - scramble_data;
}
else
{
- scramble_323(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH_323 + 1;
+ scramble_data_len= pkt_end - scramble_data;
+ scramble_plugin= native_password_plugin_name;
}
}
else
- *end++= '\0'; /* empty password */
+ mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
+
+ mysql->client_flag= client_flag;
- /* Add database if needed */
- if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
- {
- end= strmake(end, db, NAME_LEN) + 1;
- mysql->db= my_strdup(db,MYF(MY_WME));
- db= 0;
- }
- /* Write authentication package */
- if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending authentication information",
- errno);
- goto error;
- }
-
/*
- Part 3: Authorization data's been sent. Now server can reply with
- OK-packet, or re-request scrambled password.
+ Part 2: invoke the plugin to send the authentication data to the server
*/
- if ((pkt_length=cli_safe_read(mysql)) == packet_error)
- {
- if (mysql->net.last_errno == CR_SERVER_LOST)
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "reading authorization packet",
- errno);
+ if (run_plugin_auth(mysql, scramble_data, scramble_data_len,
+ scramble_plugin, db))
goto error;
- }
- if (pkt_length == 1 && net->read_pos[0] == 254 &&
- mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- By sending this very specific reply server asks us to send scrambled
- password in old format.
- */
- scramble_323(buff, mysql->scramble, passwd);
- if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending password information",
- errno);
- goto error;
- }
- /* Read what server thinks about out new auth message report */
- if (cli_safe_read(mysql) == packet_error)
- {
- if (mysql->net.last_errno == CR_SERVER_LOST)
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "reading final connect information",
- errno);
- goto error;
- }
- }
+ /*
+ Part 3: authenticated, finish the initialization of the connection
+ */
- if (client_flag & CLIENT_COMPRESS) /* We will use compression */
+ if (mysql->client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
#ifdef CHECK_LICENSE
@@ -2457,7 +2975,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
goto error;
#endif
- if (db && mysql_select_db(mysql, db))
+ if (db && !mysql->db && mysql_select_db(mysql, db))
{
if (mysql->net.last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
@@ -2510,7 +3028,7 @@ error:
/* Free alloced memory */
end_server(mysql);
mysql_close_free(mysql);
- if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
+ if (!(client_flag & CLIENT_REMEMBER_OPTIONS))
mysql_close_free_options(mysql);
}
DBUG_RETURN(0);
@@ -2655,6 +3173,12 @@ static void mysql_close_free_options(MYS
if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif /* HAVE_SMEM */
+ if (mysql->options.extension)
+ {
+ my_free(mysql->options.extension->plugin_dir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.extension->default_auth,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.extension,MYF(0));
+ }
bzero((char*) &mysql->options,sizeof(mysql->options));
DBUG_VOID_RETURN;
}
@@ -3185,6 +3709,12 @@ mysql_options(MYSQL *mysql,enum mysql_op
else
mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
break;
+ case MYSQL_PLUGIN_DIR:
+ extension_set_string(&mysql->options, plugin_dir, arg);
+ break;
+ case MYSQL_DEFAULT_AUTH:
+ extension_set_string(&mysql->options, default_auth, arg);
+ break;
default:
DBUG_RETURN(1);
}
@@ -3293,3 +3823,99 @@ int STDCALL mysql_set_character_set(MYSQ
}
+/**
+ client authentication plugin that does native MySQL authentication
+ using a 20-byte (4.1+) scramble
+*/
+
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ int pkt_len;
+ uchar *pkt;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble;
+ pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
+ mysql->scramble[SCRAMBLE_LENGTH] = 0;
+ }
+
+ if (mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH + 1];
+ scramble(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
+
+/**
+ client authentication plugin that does old MySQL authentication
+ using an 8-byte (4.0-) scramble
+*/
+
+static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ uchar *pkt;
+ int pkt_len;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble;
+ pkt_len= SCRAMBLE_LENGTH_323 + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH_323 + 1 &&
+ pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memcpy(mysql->scramble, pkt, pkt_len);
+ mysql->scramble[pkt_len] = 0;
+ }
+
+ if (mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH_323 + 1];
+ scramble_323(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH_323 + 1))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
=== added file 'sql-common/client_plugin.c'
--- a/sql-common/client_plugin.c 1970-01-01 00:00:00 +0000
+++ b/sql-common/client_plugin.c 2010-03-29 15:13:53 +0000
@@ -0,0 +1,436 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Support code for the client side (libmysql) plugins
+
+ Client plugins are somewhat different from server plugins, they are simpler.
+
+ They do not need to be installed or in any way explicitly loaded on the
+ client, they are loaded automatically on demand.
+ One client plugin per shared object, soname *must* match the plugin name.
+
+ There is no reference counting and no unloading either.
+*/
+
+#include <my_global.h>
+#include "mysql.h"
+#include <my_sys.h>
+#include <m_string.h>
+#ifdef THREAD
+#include <my_pthread.h>
+#else
+#include <my_no_pthread.h>
+#endif
+
+#include <sql_common.h>
+#include "errmsg.h"
+#include <mysql/client_plugin.h>
+
+struct st_client_plugin_int {
+ struct st_client_plugin_int *next;
+ void *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+};
+
+static my_bool initialized= 0;
+static MEM_ROOT mem_root;
+
+static const char *plugin_declarations_sym= "_mysql_client_plugin_declaration_";
+static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]=
+{
+ 0, /* these two are taken by Connector/C */
+ 0, /* these two are taken by Connector/C */
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION
+};
+
+/*
+ Loaded plugins are stored in a linked list.
+ The list is append-only, the elements are added to the head (like in a stack).
+ The elements are added under a mutex, but the list can be read and traversed
+ without any mutex because once an element is added to the list, it stays
+ there. The main purpose of a mutex is to prevent two threads from
+ loading the same plugin twice in parallel.
+*/
+struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS];
+#ifdef THREAD
+static pthread_mutex_t LOCK_load_client_plugin;
+#endif
+
+static int is_not_initialized(MYSQL *mysql, const char *name)
+{
+ if (initialized)
+ return 0;
+
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ name, "not initialized");
+ return 1;
+}
+
+
+/**
+ finds a plugin in the list
+
+ @param name plugin name to search for
+ @param type plugin type
+
+ @note this does NOT necessarily need a mutex, take care!
+
+ @retval a pointer to a found plugin or 0
+*/
+
+static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
+{
+ struct st_client_plugin_int *p;
+
+ DBUG_ASSERT(initialized);
+ DBUG_ASSERT(type >= 0 && type < MYSQL_CLIENT_MAX_PLUGINS);
+ if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
+ return 0;
+
+ for (p= plugin_list[type]; p; p= p->next)
+ {
+ if (strcmp(p->plugin->name, name) == 0)
+ return p->plugin;
+ }
+ return NULL;
+}
+
+
+/**
+ verifies the plugin and adds it to the list
+
+ @param mysql MYSQL structure (for error reporting)
+ @param plugin plugin to install
+ @param dlhandle a handle to the shared object (returned by dlopen)
+ or 0 if the plugin was not dynamically loaded
+ @param argc number of arguments in the 'va_list args'
+ @param args arguments passed to the plugin initialization function
+
+ @retval a pointer to an installed plugin or 0
+*/
+
+static struct st_mysql_client_plugin *
+add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ struct st_client_plugin_int plugin_int, *p;
+ char errbuf[1024];
+
+ DBUG_ASSERT(initialized);
+
+ plugin_int.plugin= plugin;
+ plugin_int.dlhandle= dlhandle;
+
+ if (plugin->type >= MYSQL_CLIENT_MAX_PLUGINS)
+ {
+ errmsg= "Unknown client plugin type";
+ goto err1;
+ }
+
+ if (plugin->interface_version < plugin_version[plugin->type] ||
+ (plugin->interface_version >> 8) >
+ (plugin_version[plugin->type] >> 8))
+ {
+ errmsg= "Incompatible client plugin interface";
+ goto err1;
+ }
+
+ /* Call the plugin initialization function, if any */
+ if (plugin->init && plugin->init(errbuf, sizeof(errbuf), argc, args))
+ {
+ errmsg= errbuf;
+ goto err1;
+ }
+
+ p= (struct st_client_plugin_int *)
+ memdup_root(&mem_root, &plugin_int, sizeof(plugin_int));
+
+ if (!p)
+ {
+ errmsg= "Out of memory";
+ goto err2;
+ }
+
+ safe_mutex_assert_owner(&LOCK_load_client_plugin);
+
+ p->next= plugin_list[plugin->type];
+ plugin_list[plugin->type]= p;
+
+ return plugin;
+
+err2:
+ if (plugin->deinit)
+ plugin->deinit();
+err1:
+ if (dlhandle)
+ dlclose(dlhandle);
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name,
+ errmsg);
+ return NULL;
+}
+
+
+/**
+ Loads plugins which are specified in the environment variable
+ LIBMYSQL_PLUGINS.
+
+ Multiple plugins must be separated by semicolon. This function doesn't
+ return or log an error.
+
+ The function is be called by mysql_client_plugin_init
+
+ @todo
+ Support extended syntax, passing parameters to plugins, for example
+ LIBMYSQL_PLUGINS="plugin1(param1,param2);plugin2;..."
+ or
+ LIBMYSQL_PLUGINS="plugin1=int:param1,str:param2;plugin2;..."
+*/
+
+static void load_env_plugins(MYSQL *mysql)
+{
+ char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
+
+ /* no plugins to load */
+ if (!s)
+ return;
+
+ free_env= plugs= my_strdup(s, MYF(MY_WME));
+
+ do {
+ if ((s= strchr(plugs, ';')))
+ *s= '\0';
+ mysql_load_plugin(mysql, plugs, -1, 0);
+ plugs= s + 1;
+ } while (s);
+
+ my_free(free_env, MYF(0));
+}
+
+/********** extern functions to be used by libmysql *********************/
+
+/**
+ Initializes the client plugin layer.
+
+ This function must be called before any other client plugin function.
+
+ @retval 0 successful
+ @retval != 0 error occured
+*/
+
+int mysql_client_plugin_init()
+{
+ MYSQL mysql;
+ struct st_mysql_client_plugin **builtin;
+
+ if (initialized)
+ return 0;
+
+ bzero(&mysql, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
+
+ pthread_mutex_init(&LOCK_load_client_plugin, MY_MUTEX_INIT_SLOW);
+ init_alloc_root(&mem_root, 128, 128);
+
+ bzero(&plugin_list, sizeof(plugin_list));
+
+ initialized= 1;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ for (builtin= mysql_client_builtins; *builtin; builtin++)
+ add_plugin(&mysql, *builtin, 0, 0, 0);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ load_env_plugins(&mysql);
+
+ return 0;
+}
+
+
+/**
+ Deinitializes the client plugin layer.
+
+ Unloades all client plugins and frees any associated resources.
+*/
+
+void mysql_client_plugin_deinit()
+{
+ int i;
+ struct st_client_plugin_int *p;
+
+ if (!initialized)
+ return;
+
+ for (i=0; i < MYSQL_CLIENT_MAX_PLUGINS; i++)
+ for (p= plugin_list[i]; p; p= p->next)
+ {
+ if (p->plugin->deinit)
+ p->plugin->deinit();
+ if (p->dlhandle)
+ dlclose(p->dlhandle);
+ }
+
+ bzero(&plugin_list, sizeof(plugin_list));
+ initialized= 0;
+ free_root(&mem_root, MYF(0));
+ pthread_mutex_destroy(&LOCK_load_client_plugin);
+}
+
+/************* public facing functions, for client consumption *********/
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(MYSQL *mysql,
+ struct st_mysql_client_plugin *plugin)
+{
+ if (is_not_initialized(mysql, plugin->name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (find_plugin(plugin->name, plugin->type))
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ plugin->name, "it is already loaded");
+ plugin= NULL;
+ }
+ else
+ plugin= add_plugin(mysql, plugin, 0, 0, 0);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ return plugin;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ char dlpath[FN_REFLEN+1];
+ void *sym, *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (type >= 0 && find_plugin(name, type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ /* Compile dll path */
+ strxnmov(dlpath, sizeof(dlpath) - 1,
+ mysql->options.extension && mysql->options.extension->plugin_dir ?
+ mysql->options.extension->plugin_dir : PLUGINDIR, "/",
+ name, SO_EXT, NullS);
+
+ /* Open new dll handle */
+ if (!(dlhandle= dlopen(dlpath, RTLD_NOW)))
+ {
+ errmsg= dlerror();
+ goto err;
+ }
+
+ if (!(sym= dlsym(dlhandle, plugin_declarations_sym)))
+ {
+ errmsg= "not a plugin";
+ dlclose(dlhandle);
+ goto err;
+ }
+
+ plugin= (struct st_mysql_client_plugin*)sym;
+
+ if (type >=0 && type != plugin->type)
+ {
+ errmsg= "type mismatch";
+ goto err;
+ }
+
+ if (strcmp(name, plugin->name))
+ {
+ errmsg= "name mismatch";
+ goto err;
+ }
+
+ if (type < 0 && find_plugin(name, plugin->type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ plugin= add_plugin(mysql, plugin, dlhandle, argc, args);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ return plugin;
+
+err:
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, errmsg);
+ return NULL;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_load_plugin(MYSQL *mysql, const char *name, int type, int argc, ...)
+{
+ struct st_mysql_client_plugin *p;
+ va_list args;
+ va_start(args, argc);
+ p= mysql_load_plugin_v(mysql, name, type, argc, args);
+ va_end(args);
+ return p;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
+{
+ struct st_mysql_client_plugin *p;
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name,
+ "invalid type");
+ }
+
+ if ((p= find_plugin(name, type)))
+ return p;
+
+ /* not found, load it */
+ return mysql_load_plugin(mysql, name, type, 0);
+}
+
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2010-03-03 14:44:14 +0000
+++ b/sql/CMakeLists.txt 2010-03-29 15:13:53 +0000
@@ -54,7 +54,7 @@ SET (SQL_SOURCE
log_event.cc rpl_record.cc rpl_reporting.cc
log_event_old.cc rpl_record_old.cc
message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c
- mysqld.cc net_serv.cc
+ mysqld.cc net_serv.cc ../sql-common/client_plugin.c
nt_servc.cc nt_servc.h opt_range.cc opt_range.h opt_sum.cc
../sql-common/pack.c parse_file.cc password.c procedure.cc
protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/sql/Makefile.am 2010-03-29 15:13:53 +0000
@@ -126,7 +126,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.
sql_servers.cc event_parse_data.cc \
opt_table_elimination.cc
-nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
+nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c client_plugin.c
libndb_la_CPPFLAGS= @ndbcluster_includes@
libndb_la_SOURCES= ha_ndbcluster.cc \
@@ -140,10 +140,10 @@ mysql_tzinfo_to_sql_SOURCES = tztime.cc
mysql_tzinfo_to_sql_CXXFLAGS= -DTZINFO2SQL
DEFS = -DMYSQL_SERVER \
- -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
- -DPLUGINDIR="\"$(pkgplugindir)\"" \
+ -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' \
+ -DPLUGINDIR='"$(pkgplugindir)"' \
-DHAVE_EVENT_SCHEDULER \
@DEFS@
@@ -167,6 +167,8 @@ link_sources:
@LN_CP_F@ $(top_srcdir)/sql-common/pack.c pack.c
rm -f client.c
@LN_CP_F@ $(top_srcdir)/sql-common/client.c client.c
+ rm -f client_plugin.c
+ @LN_CP_F@ $(top_srcdir)/sql-common/client_plugin.c client_plugin.c
rm -f my_time.c
@LN_CP_F@ $(top_srcdir)/sql-common/my_time.c my_time.c
rm -f my_user.c
=== modified file 'sql/client_settings.h'
--- a/sql/client_settings.h 2009-08-13 20:07:20 +0000
+++ b/sql/client_settings.h 2010-03-29 15:13:53 +0000
@@ -15,6 +15,7 @@
#include <thr_alarm.h>
+#include <sql_common.h>
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_SECURE_CONNECTION | CLIENT_TRANSACTIONS | \
@@ -31,7 +32,8 @@
#undef HAVE_SMEM
#undef _CUSTOMCONFIG_
-#define mysql_server_init(a,b,c) 0
+#define mysql_server_init(a,b,c) mysql_client_plugin_init()
+#define mysql_server_end() mysql_client_plugin_deinit()
#ifdef HAVE_REPLICATION
C_MODE_START
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-01-06 21:27:53 +0000
+++ b/sql/ha_ndbcluster.cc 2010-03-29 15:13:53 +0000
@@ -9185,7 +9185,7 @@ pthread_handler_t ndb_util_thread_func(v
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
thd->main_security_ctx.master_access= ~0;
- thd->main_security_ctx.priv_user = 0;
+ thd->main_security_ctx.priv_user[0] = 0;
CHARSET_INFO *charset_connection;
charset_connection= get_charset_by_csname("utf8",
=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc 2009-12-03 11:19:05 +0000
+++ b/sql/ha_ndbcluster_binlog.cc 2010-03-29 15:13:53 +0000
@@ -3681,7 +3681,7 @@ pthread_handler_t ndb_binlog_thread_func
thd->client_capabilities= 0;
my_net_init(&thd->net, 0);
thd->main_security_ctx.master_access= ~0;
- thd->main_security_ctx.priv_user= 0;
+ thd->main_security_ctx.priv_user[0]= 0;
/*
Set up ndb binlog
=== modified file 'sql/lex.h'
--- a/sql/lex.h 2009-11-12 04:31:28 +0000
+++ b/sql/lex.h 2010-03-29 15:13:53 +0000
@@ -590,6 +590,7 @@ static SYMBOL symbols[] = {
{ "VARCHARACTER", SYM(VARCHAR)},
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
+ { "VIA", SYM(VIA_SYM)},
{ "VIEW", SYM(VIEW_SYM)},
{ "VIRTUAL", SYM(VIRTUAL_SYM)},
{ "WAIT", SYM(WAIT_SYM)},
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2010-03-15 11:51:23 +0000
+++ b/sql/mysql_priv.h 2010-03-29 15:13:53 +0000
@@ -1067,9 +1067,6 @@ int write_bin_log(THD *thd, bool clear_e
char const *query, ulong query_length);
/* sql_connect.cc */
-int check_user(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count);
pthread_handler_t handle_one_connection(void *arg);
bool init_new_connection_handler_thread();
void reset_mqh(LEX_USER *lu, bool get_them);
@@ -1082,6 +1079,9 @@ bool login_connection(THD *thd);
void end_connection(THD *thd);
void prepare_new_connection_state(THD* thd);
void update_global_user_stats(THD* thd, bool create_user, time_t now);
+int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host, USER_RESOURCES *mqh);
+int check_for_max_user_connections(THD *thd, USER_CONN *uc);
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-29 21:16:12 +0000
+++ b/sql/mysqld.cc 2010-03-31 23:10:03 +0000
@@ -22,6 +22,7 @@
#include "rpl_mi.h"
#include "sql_repl.h"
#include "rpl_filter.h"
+#include "client_settings.h"
#include "repl_failsafe.h"
#include <my_stacktrace.h>
#include "mysqld_suffix.h"
@@ -1394,6 +1395,7 @@ void clean_up(bool print_message)
if (print_message && errmesg && server_start_time)
sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
thread_scheduler.end();
+ mysql_library_end();
finish_client_errs();
my_free((uchar*) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
@@ -3489,6 +3491,7 @@ static int init_common_variables(const c
if (init_errmessage()) /* Read error messages from file */
return 1;
init_client_errs();
+ mysql_library_init(never,never,never); /* for replication */
lex_init();
if (item_create_init())
return 1;
=== modified file 'sql/password.c'
--- a/sql/password.c 2009-09-07 20:50:10 +0000
+++ b/sql/password.c 2010-03-29 15:13:53 +0000
@@ -193,13 +193,13 @@ void scramble_323(char *to, const char *
*/
my_bool
-check_scramble_323(const char *scrambled, const char *message,
+check_scramble_323(const unsigned char *scrambled, const char *message,
ulong *hash_pass)
{
struct my_rnd_struct rand_st;
ulong hash_message[2];
- char buff[16],*to,extra; /* Big enough for check */
- const char *pos;
+ uchar buff[16],*to,extra; /* Big enough for check */
+ const uchar *pos;
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
my_rnd_init(&rand_st,hash_pass[0] ^ hash_message[0],
@@ -214,7 +214,7 @@ check_scramble_323(const char *scrambled
to=buff;
while (*scrambled)
{
- if (*scrambled++ != (char) (*to++ ^ extra))
+ if (*scrambled++ != (uchar) (*to++ ^ extra))
return 1; /* Wrong password */
}
return 0;
@@ -481,7 +481,7 @@ scramble(char *to, const char *message,
*/
my_bool
-check_scramble(const char *scramble_arg, const char *message,
+check_scramble(const uchar *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
SHA1_CONTEXT sha1_context;
@@ -494,7 +494,7 @@ check_scramble(const char *scramble_arg,
mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
mysql_sha1_result(&sha1_context, buf);
/* encrypt scramble */
- my_crypt((char *) buf, buf, (const uchar *) scramble_arg, SCRAMBLE_LENGTH);
+ my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
mysql_sha1_reset(&sha1_context);
mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2009-12-03 11:19:05 +0000
+++ b/sql/protocol.cc 2010-03-29 15:13:53 +0000
@@ -341,24 +341,6 @@ static bool write_eof_packet(THD *thd, N
}
/**
- Please client to send scrambled_password in old format.
-
- @param thd thread handle
-
- @retval
- 0 ok
- @retval
- !0 error
-*/
-
-bool send_old_password_request(THD *thd)
-{
- NET *net= &thd->net;
- return my_net_write(net, eof_buff, 1) || net_flush(net);
-}
-
-
-/**
@param thd Thread handler
@param sql_errno The error code to send
@param err A pointer to the error message
=== modified file 'sql/protocol.h'
--- a/sql/protocol.h 2009-12-03 11:19:05 +0000
+++ b/sql/protocol.h 2010-03-29 15:13:53 +0000
@@ -177,7 +177,6 @@ public:
void send_warning(THD *thd, uint sql_errno, const char *err=0);
bool net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
void net_end_statement(THD *thd);
-bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
uchar *net_store_data(uchar *to,int32 from);
uchar *net_store_data(uchar *to,longlong from);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_acl.cc 2010-03-31 18:37:45 +0000
@@ -30,6 +30,8 @@
#include <stdarg.h>
#include "sp_head.h"
#include "sp.h"
+#include <sql_common.h>
+#include <mysql/plugin_auth.h>
static const
TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
@@ -148,6 +150,87 @@ TABLE_FIELD_TYPE mysql_db_table_fields[M
const TABLE_FIELD_DEF
mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields};
+static LEX_STRING native_password_plugin_name= {
+ C_STRING_WITH_LEN("mysql_native_password")
+};
+
+static LEX_STRING old_password_plugin_name= {
+ C_STRING_WITH_LEN("mysql_old_password")
+};
+
+/// @todo make it configurable
+LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
+
+static plugin_ref native_password_plugin;
+#ifndef EMBEDDED_LIBRARY
+static plugin_ref old_password_plugin;
+#endif
+
+/* Classes */
+
+struct acl_host_and_ip
+{
+ char *hostname;
+ long ip,ip_mask; // Used with masked ip:s
+};
+
+class ACL_ACCESS {
+public:
+ ulong sort;
+ ulong access;
+};
+
+/* ACL_HOST is used if no host is specified */
+
+class ACL_HOST :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *db;
+};
+
+class ACL_USER :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ uint hostname_length;
+ USER_RESOURCES user_resource;
+ char *user;
+ uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
+ uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 4.0, 20 - 4.1.1
+ enum SSL_type ssl_type;
+ const char *ssl_cipher, *x509_issuer, *x509_subject;
+ LEX_STRING plugin;
+ LEX_STRING auth_string;
+
+ ACL_USER *copy(MEM_ROOT *root)
+ {
+ ACL_USER *dst= (ACL_USER *)alloc_root(root, sizeof(ACL_USER));
+ if (!dst)
+ return 0;
+ *dst= *this;
+ dst->user= safe_strdup_root(root, user);
+ dst->ssl_cipher= safe_strdup_root(root, ssl_cipher);
+ dst->x509_issuer= safe_strdup_root(root, x509_issuer);
+ dst->x509_subject= safe_strdup_root(root, x509_subject);
+ if (plugin.str == native_password_plugin_name.str ||
+ plugin.str == old_password_plugin_name.str)
+ dst->plugin= plugin;
+ else
+ dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
+ dst->auth_string.str = safe_strdup_root(root, auth_string.str);
+ dst->host.hostname= safe_strdup_root(root, host.hostname);
+ return dst;
+ }
+};
+
+class ACL_DB :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *user,*db;
+};
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#define FIRST_NON_YN_FIELD 26
@@ -171,6 +254,24 @@ static uchar* acl_entry_get_key(acl_entr
#define IP_ADDR_STRLEN (3+1+3+1+3+1+3)
#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1)
+#if defined(HAVE_OPENSSL)
+/*
+ Without SSL the handshake consists of one packet. This packet
+ has both client capabilites and scrambled password.
+ With SSL the handshake might consist of two packets. If the first
+ packet (client capabilities) has CLIENT_SSL flag set, we have to
+ switch to SSL and read the second packet. The scrambled password
+ is in the second packet and client_capabilites field will be ignored.
+ Maybe it is better to accept flags other than CLIENT_SSL from the
+ second packet?
+*/
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
+#else
+#define MIN_HANDSHAKE_SIZE 6
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
+
static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
static bool initialized=0;
@@ -265,6 +366,19 @@ my_bool acl_init(bool dont_read_acl_tabl
(hash_get_key) acl_entry_get_key,
(hash_free_key) free,
&my_charset_utf8_bin);
+
+ /*
+ cache built-in native authentication plugins,
+ to avoid hash searches and a global mutex lock on every connect
+ */
+ native_password_plugin= my_plugin_lock_by_name(0,
+ &native_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
+ old_password_plugin= my_plugin_lock_by_name(0,
+ &old_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
+
+ if (!native_password_plugin || !old_password_plugin)
+ DBUG_RETURN(1);
+
if (dont_read_acl_tables)
{
DBUG_RETURN(0); /* purecov: tested */
@@ -422,6 +536,7 @@ static my_bool acl_load(THD *thd, TABLE_
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
+ bzero(&user, sizeof(user));
update_hostname(&user.host, get_field(&mem, table->field[0]));
user.user= get_field(&mem, table->field[1]);
if (check_no_resolve && hostname_requires_resolving(user.host.hostname))
@@ -433,27 +548,34 @@ static my_bool acl_load(THD *thd, TABLE_
continue;
}
- const char *password= get_field(thd->mem_root, table->field[2]);
+ char *password= get_field(thd->mem_root, table->field[2]);
uint password_len= password ? strlen(password) : 0;
+ user.auth_string.str= password ? password : const_cast<char*>("");
+ user.auth_string.length= password_len;
set_user_salt(&user, password, password_len);
- if (user.salt_len == 0 && password_len != 0)
- {
- switch (password_len) {
- case 45: /* 4.1: to be removed */
- sql_print_warning("Found 4.1 style password for user '%s@%s'. "
- "Ignoring user. "
- "You should change password for this user.",
- user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : "");
- break;
- default:
- sql_print_warning("Found invalid password for user: '%s@%s'; "
- "Ignoring user", user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : "");
- break;
- }
+
+ switch (password_len) {
+ case 0: /* no password */
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH:
+ user.plugin= native_password_plugin_name;
+ break;
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH_323:
+ user.plugin= old_password_plugin_name;
+ break;
+ case 45: /* 4.1: to be removed */
+ sql_print_warning("Found 4.1.0 style password for user '%s@%s'. "
+ "Ignoring user. "
+ "You should change password for this user.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ continue;
+ default:
+ sql_print_warning("Found invalid password for user: '%s@%s'; "
+ "Ignoring user", user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ continue;
}
- else // password is correct
+
{
uint next_field;
user.access= get_access(table,3,&next_field) & GLOBAL_ACLS;
@@ -530,13 +652,43 @@ static my_bool acl_load(THD *thd, TABLE_
ptr= get_field(thd->mem_root, table->field[next_field++]);
user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
}
- else
- user.user_resource.user_conn= 0;
+
+ if (table->s->fields >= 41)
+ {
+ /* We may have plugin & auth_String fields */
+ char *tmpstr= get_field(&mem, table->field[next_field++]);
+ if (tmpstr)
+ {
+ if (user.auth_string.length)
+ {
+ sql_print_warning("'user' entry '%s@%s' has both a password "
+ "and an authentication plugin specified. The "
+ "password will be ignored.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ }
+ if (my_strcasecmp(system_charset_info, tmpstr,
+ native_password_plugin_name.str) == 0)
+ user.plugin= native_password_plugin_name;
+ else
+ if (my_strcasecmp(system_charset_info, tmpstr,
+ old_password_plugin_name.str) == 0)
+ user.plugin= old_password_plugin_name;
+ else
+ {
+ user.plugin.str= tmpstr;
+ user.plugin.length= strlen(tmpstr);
+ }
+ user.auth_string.str= get_field(&mem, table->field[next_field++]);
+ if (!user.auth_string.str)
+ user.auth_string.str= const_cast<char*>("");
+ user.auth_string.length= strlen(user.auth_string.str);
+ }
+ }
}
else
{
user.ssl_type=SSL_TYPE_NONE;
- bzero((char *)&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED
if (table->s->fields <= 13)
{ // Without grant
@@ -639,6 +791,8 @@ void acl_free(bool end)
delete_dynamic(&acl_dbs);
delete_dynamic(&acl_wild_hosts);
hash_free(&acl_check_hosts);
+ plugin_unlock(0, native_password_plugin);
+ plugin_unlock(0, old_password_plugin);
if (!end)
acl_cache->clear(1); /* purecov: inspected */
else
@@ -841,246 +995,10 @@ static int acl_compare(ACL_ACCESS *a,ACL
/*
- Seek ACL entry for a user, check password, SSL cypher, and if
- everything is OK, update THD user data and USER_RESOURCES struct.
-
- IMPLEMENTATION
- This function does not check if the user has any sensible privileges:
- only user's existence and validity is checked.
- Note, that entire operation is protected by acl_cache_lock.
+ Gets user credentials without authentication and resource limit checks.
SYNOPSIS
acl_getroot()
- thd thread handle. If all checks are OK,
- thd->security_ctx->priv_user/master_access are updated.
- thd->security_ctx->host/ip/user are used for checks.
- mqh user resources; on success mqh is reset, else
- unchanged
- passwd scrambled & crypted password, received from client
- (to check): thd->scramble or thd->scramble_323 is
- used to decrypt passwd, so they must contain
- original random string,
- passwd_len length of passwd, must be one of 0, 8,
- SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
- 'thd' and 'mqh' are updated on success; other params are IN.
-
- RETURN VALUE
- 0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
- updated
- 1 user not found or authentication failure
- 2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
- -1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
-*/
-
-int acl_getroot(THD *thd, USER_RESOURCES *mqh,
- const char *passwd, uint passwd_len)
-{
- ulong user_access= NO_ACCESS;
- int res= 1;
- ACL_USER *acl_user= 0;
- Security_context *sctx= thd->security_ctx;
- DBUG_ENTER("acl_getroot");
-
- if (!initialized)
- {
- /*
- here if mysqld's been started with --skip-grant-tables option.
- */
- sctx->skip_grants();
- bzero((char*) mqh, sizeof(*mqh));
- DBUG_RETURN(0);
- }
-
- VOID(pthread_mutex_lock(&acl_cache->lock));
-
- /*
- Find acl entry in user database. Note, that find_acl_user is not the same,
- because it doesn't take into account the case when user is not empty,
- but acl_user->user is empty
- */
-
- for (uint i=0 ; i < acl_users.elements ; i++)
- {
- ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
- if (!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user))
- {
- if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
- {
- /* check password: it should be empty or valid */
- if (passwd_len == acl_user_tmp->salt_len)
- {
- if (acl_user_tmp->salt_len == 0 ||
- (acl_user_tmp->salt_len == SCRAMBLE_LENGTH ?
- check_scramble(passwd, thd->scramble, acl_user_tmp->salt) :
- check_scramble_323(passwd, thd->scramble,
- (ulong *) acl_user_tmp->salt)) == 0)
- {
- acl_user= acl_user_tmp;
- res= 0;
- }
- }
- else if (passwd_len == SCRAMBLE_LENGTH &&
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH_323)
- res= -1;
- else if (passwd_len == SCRAMBLE_LENGTH_323 &&
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH)
- res= 2;
- /* linear search complete: */
- break;
- }
- }
- }
- /*
- This was moved to separate tree because of heavy HAVE_OPENSSL case.
- If acl_user is not null, res is 0.
- */
-
- if (acl_user)
- {
- /* OK. User found and password checked continue validation */
-#ifdef HAVE_OPENSSL
- Vio *vio=thd->net.vio;
- SSL *ssl= (SSL*) vio->ssl_arg;
- X509 *cert;
-#endif
-
- /*
- At this point we know that user is allowed to connect
- from given host by given username/password pair. Now
- we check if SSL is required, if user is using SSL and
- if X509 certificate attributes are OK
- */
- switch (acl_user->ssl_type) {
- case SSL_TYPE_NOT_SPECIFIED: // Impossible
- case SSL_TYPE_NONE: // SSL is not required
- user_access= acl_user->access;
- break;
-#ifdef HAVE_OPENSSL
- case SSL_TYPE_ANY: // Any kind of SSL is ok
- if (vio_type(vio) == VIO_TYPE_SSL)
- user_access= acl_user->access;
- break;
- case SSL_TYPE_X509: /* Client should have any valid certificate. */
- /*
- Connections with non-valid certificates are dropped already
- in sslaccept() anyway, so we do not check validity here.
-
- We need to check for absence of SSL because without SSL
- we should reject connection.
- */
- if (vio_type(vio) == VIO_TYPE_SSL &&
- SSL_get_verify_result(ssl) == X509_V_OK &&
- (cert= SSL_get_peer_certificate(ssl)))
- {
- user_access= acl_user->access;
- X509_free(cert);
- }
- break;
- case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
- /*
- We do not check for absence of SSL because without SSL it does
- not pass all checks here anyway.
- If cipher name is specified, we compare it to actual cipher in
- use.
- */
- if (vio_type(vio) != VIO_TYPE_SSL ||
- SSL_get_verify_result(ssl) != X509_V_OK)
- break;
- if (acl_user->ssl_cipher)
- {
- DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
- acl_user->ssl_cipher,SSL_get_cipher(ssl)));
- if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl)))
- user_access= acl_user->access;
- else
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
- acl_user->ssl_cipher,
- SSL_get_cipher(ssl));
- break;
- }
- }
- /* Prepare certificate (if exists) */
- DBUG_PRINT("info",("checkpoint 1"));
- if (!(cert= SSL_get_peer_certificate(ssl)))
- {
- user_access=NO_ACCESS;
- break;
- }
- DBUG_PRINT("info",("checkpoint 2"));
- /* If X509 issuer is specified, we check it... */
- if (acl_user->x509_issuer)
- {
- DBUG_PRINT("info",("checkpoint 3"));
- char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
- acl_user->x509_issuer, ptr));
- if (strcmp(acl_user->x509_issuer, ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 issuer mismatch: should be '%s' "
- "but is '%s'", acl_user->x509_issuer, ptr);
- free(ptr);
- X509_free(cert);
- user_access=NO_ACCESS;
- break;
- }
- user_access= acl_user->access;
- free(ptr);
- }
- DBUG_PRINT("info",("checkpoint 4"));
- /* X509 subject is specified, we check it .. */
- if (acl_user->x509_subject)
- {
- char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
- acl_user->x509_subject, ptr));
- if (strcmp(acl_user->x509_subject,ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
- acl_user->x509_subject, ptr);
- free(ptr);
- X509_free(cert);
- user_access=NO_ACCESS;
- break;
- }
- user_access= acl_user->access;
- free(ptr);
- }
- /* Deallocate the X509 certificate. */
- X509_free(cert);
- break;
-#else /* HAVE_OPENSSL */
- default:
- /*
- If we don't have SSL but SSL is required for this user the
- authentication should fail.
- */
- break;
-#endif /* HAVE_OPENSSL */
- }
- sctx->master_access= user_access;
- sctx->priv_user= acl_user->user ? sctx->user : (char *) "";
- *mqh= acl_user->user_resource;
-
- if (acl_user->host.hostname)
- strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
- else
- *sctx->priv_host= 0;
- }
- VOID(pthread_mutex_unlock(&acl_cache->lock));
- DBUG_RETURN(res);
-}
-
-
-/*
- This is like acl_getroot() above, but it doesn't check password,
- and we don't care about the user resources.
-
- SYNOPSIS
- acl_getroot_no_password()
sctx Context which should be initialized
user user name
host host name
@@ -1092,13 +1010,13 @@ int acl_getroot(THD *thd, USER_RESOURCES
TRUE Error
*/
-bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
- char *ip, char *db)
+bool acl_getroot(Security_context *sctx, char *user, char *host,
+ char *ip, char *db)
{
int res= 1;
uint i;
ACL_USER *acl_user= 0;
- DBUG_ENTER("acl_getroot_no_password");
+ DBUG_ENTER("acl_getroot");
DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'",
(host ? host : "(NULL)"), (ip ? ip : "(NULL)"),
@@ -1121,8 +1039,7 @@ bool acl_getroot_no_password(Security_co
sctx->master_access= 0;
sctx->db_access= 0;
- sctx->priv_user= (char *) "";
- *sctx->priv_host= 0;
+ *sctx->priv_user= *sctx->priv_host= 0;
/*
Find acl entry in user database.
@@ -1164,7 +1081,11 @@ bool acl_getroot_no_password(Security_co
}
}
sctx->master_access= acl_user->access;
- sctx->priv_user= acl_user->user ? user : (char *) "";
+
+ if (acl_user->user)
+ strmake(sctx->priv_user, user, USERNAME_LENGTH);
+ else
+ *sctx->priv_user= 0;
if (acl_user->host.hostname)
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
@@ -1190,7 +1111,9 @@ static void acl_update_user(const char *
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- ulong privileges)
+ ulong privileges,
+ const LEX_STRING *plugin,
+ const LEX_STRING *auth)
{
safe_mutex_assert_owner(&acl_cache->lock);
@@ -1204,6 +1127,14 @@ static void acl_update_user(const char *
(acl_user->host.hostname &&
!my_strcasecmp(system_charset_info, host, acl_user->host.hostname)))
{
+ if (plugin->str[0])
+ {
+ acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
+ acl_user->plugin.length= plugin->length;
+ acl_user->auth_string.str= auth->str ?
+ strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
+ acl_user->auth_string.length= auth->length;
+ }
acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
@@ -1240,7 +1171,9 @@ static void acl_insert_user(const char *
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- ulong privileges)
+ ulong privileges,
+ const LEX_STRING *plugin,
+ const LEX_STRING *auth)
{
ACL_USER acl_user;
@@ -1248,6 +1181,22 @@ static void acl_insert_user(const char *
acl_user.user=*user ? strdup_root(&mem,user) : 0;
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
+ if (plugin->str[0])
+ {
+ acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
+ acl_user.plugin.length= plugin->length;
+ acl_user.auth_string.str= auth->str ?
+ strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
+ acl_user.auth_string.length= auth->length;
+ }
+ else
+ {
+ acl_user.plugin= password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323 ?
+ old_password_plugin_name : native_password_plugin_name;
+ acl_user.auth_string.str= strmake_root(&mem, password, password_len);
+ acl_user.auth_string.length= password_len;
+ }
+
acl_user.access=privileges;
acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@@ -1966,6 +1915,15 @@ static int replace_user_table(THD *thd,
thd->security_ctx->user, thd->security_ctx->host_or_ip);
goto end;
}
+ else if (combo.plugin.str[0])
+ {
+ if (!plugin_is_ready(&combo.plugin, MYSQL_AUTHENTICATION_PLUGIN))
+ {
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo.plugin.str);
+ goto end;
+ }
+ }
+
old_row_exists = 0;
restore_record(table,s->default_values);
table->field[0]->store(combo.host.str,combo.host.length,
@@ -1979,7 +1937,7 @@ static int replace_user_table(THD *thd,
{
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
- if (combo.password.str) // If password given
+ if (combo.password.str) // If password given
table->field[2]->store(password, password_len, system_charset_info);
else if (!rights && !revoke_grant &&
lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
@@ -2060,7 +2018,17 @@ static int replace_user_table(THD *thd,
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE);
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
+
+ next_field+=4;
+ if (table->s->fields >= 41 && combo.plugin.str[0])
+ {
+ table->field[next_field]->store(combo.plugin.str, combo.plugin.length,
+ system_charset_info);
+ table->field[next_field+1]->store(combo.auth.str, combo.auth.length,
+ system_charset_info);
+ }
}
+
if (old_row_exists)
{
/*
@@ -2104,7 +2072,9 @@ end:
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
- rights);
+ rights,
+ &combo.plugin,
+ &combo.auth);
else
acl_insert_user(combo.user.str, combo.host.str, password, password_len,
lex->ssl_type,
@@ -2112,7 +2082,9 @@ end:
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
- rights);
+ rights,
+ &combo.plugin,
+ &combo.auth);
}
DBUG_RETURN(error);
}
@@ -4445,14 +4417,14 @@ bool check_routine_level_acl(THD *thd, c
ulong get_table_grant(THD *thd, TABLE_LIST *table)
{
ulong privilege;
- Security_context *sctx= thd->security_ctx;
- const char *db = table->db ? table->db : thd->db;
GRANT_TABLE *grant_table;
rw_rdlock(&LOCK_grant);
#ifdef EMBEDDED_LIBRARY
grant_table= NULL;
#else
+ Security_context *sctx= thd->security_ctx;
+ const char *db = table->db ? table->db : thd->db;
grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user,
table->table_name, 0);
#endif
@@ -6328,38 +6300,44 @@ bool sp_grant_privileges(THD *thd, const
tables->db= (char*)sp_db;
tables->table_name= tables->alias= (char*)sp_name;
- combo->host.length= strlen(combo->host.str);
- combo->user.length= strlen(combo->user.str);
- combo->host.str= thd->strmake(combo->host.str,combo->host.length);
- combo->user.str= thd->strmake(combo->user.str,combo->user.length);
+ thd->make_lex_string(&combo->user,
+ combo->user.str, strlen(combo->user.str), 0);
+ thd->make_lex_string(&combo->host,
+ combo->host.str, strlen(combo->host.str), 0);
+ combo->password= empty_lex_str;
+ combo->plugin= empty_lex_str;
+ combo->auth= empty_lex_str;
- if(au && au->salt_len)
+ if(au)
{
- if (au->salt_len == SCRAMBLE_LENGTH)
- {
- make_password_from_salt(passwd_buff, au->salt);
- combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
- }
- else if (au->salt_len == SCRAMBLE_LENGTH_323)
+ if (au->salt_len)
{
- make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
- combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ if (au->salt_len == SCRAMBLE_LENGTH)
+ {
+ make_password_from_salt(passwd_buff, au->salt);
+ combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+ }
+ else if (au->salt_len == SCRAMBLE_LENGTH_323)
+ {
+ make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
+ combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ }
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
+ ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ return TRUE;
+ }
+ combo->password.str= passwd_buff;
}
- else
+
+ if (au->plugin.str != native_password_plugin_name.str &&
+ au->plugin.str != old_password_plugin_name.str)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PASSWD_LENGTH,
- ER(ER_PASSWD_LENGTH),
- SCRAMBLED_PASSWORD_CHAR_LENGTH);
- return TRUE;
+ combo->plugin= au->plugin;
+ combo->auth= au->auth_string;
}
- combo->password.str= passwd_buff;
- }
- else
- {
- combo->password.str= (char*)"";
- combo->password.length= 0;
}
if (user_list.push_back(combo))
@@ -6853,3 +6831,1429 @@ bool check_routine_level_acl(THD *thd, c
}
#endif
+
+/****************************************************************************
+ AUTHENTICATION CODE
+ including initial connect handshake, invoking appropriate plugins,
+ client-server plugin negotiation, COM_CHANGE_USER, and native
+ MySQL authentication plugins.
+****************************************************************************/
+
+/* few defines to have less ifdef's in the code below */
+#ifdef EMBEDDED_LIBRARY
+#undef HAVE_OPENSSL
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+#define initialized 0
+#define decrease_user_connections(X) /* nothing */
+#define check_for_max_user_connections(X,Y) 0
+#endif
+#endif
+#ifndef HAVE_OPENSSL
+#define ssl_acceptor_fd 0
+#define sslaccept(A,B,C,D) 1
+#define NORMAL_HANDSHAKE_SIZE 6
+#endif
+
+/**
+ The internal version of what plugins know as MYSQL_PLUGIN_VIO,
+ basically the context of the authentication session
+*/
+struct MPVIO_EXT : public MYSQL_PLUGIN_VIO
+{
+ MYSQL_SERVER_AUTH_INFO auth_info;
+ THD *thd;
+ ACL_USER *acl_user; ///< a copy, independent from acl_users array
+ plugin_ref plugin; ///< what plugin we're under
+ LEX_STRING db; ///< db name from the handshake packet
+ /** when restarting a plugin this caches the last client reply */
+ struct {
+ char *plugin, *pkt; ///< pointers into NET::buff
+ uint pkt_len;
+ } cached_client_reply;
+ /** this caches the first plugin packet for restart request on the client */
+ struct {
+ char *pkt;
+ uint pkt_len;
+ } cached_server_packet;
+ int packets_read, packets_written; ///< counters for send/received packets
+ uint connect_errors; ///< if there were connect errors for this host
+ /** when plugin returns a failure this tells us what really happened */
+ enum { SUCCESS, FAILURE, RESTART } status;
+};
+
+
+/**
+ a helper function to report an access denied error in all the proper places
+*/
+
+static void login_failed_error(THD *thd, bool passwd_used)
+{
+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ status_var_increment(thd->status_var.access_denied_errors);
+ /*
+ Log access denied messages to the error log when log-warnings = 2
+ so that the overhead of the general query log is not required to track
+ failed connections.
+ */
+ if (global_system_variables.log_warnings > 1)
+ {
+ sql_print_warning(ER(ER_ACCESS_DENIED_ERROR),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ }
+}
+
+
+/**
+ sends a server handshake initialization packet, the very first packet
+ after the connection was established
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ 1 protocol version (always 10)
+ n server version string, \0-terminated
+ 4 thread id
+ 8 first 8 bytes of the plugin provided data (scramble)
+ 1 \0 byte, terminating the first part of a scramble
+ 2 server capabilities (two lower bytes)
+ 1 server character set
+ 2 server status
+ 2 server capabilities (two upper bytes)
+ 1 length of the scramble
+ 10 reserved, always 0
+ n rest of the plugin provided data (at least 12 bytes)
+ 1 \0 byte, terminating the second part of a scramble
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static bool send_server_handshake_packet(MPVIO_EXT *mpvio,
+ const char *data, uint data_len)
+{
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
+ DBUG_ASSERT(data_len <= 255);
+
+ THD *thd= mpvio->thd;
+ char *buff= (char *)my_alloca(1 + SERVER_VERSION_LENGTH + 1 + data_len + 64);
+ char scramble_buf[SCRAMBLE_LENGTH];
+ char *end= buff;
+
+ *end++= protocol_version;
+
+ thd->client_capabilities= CLIENT_BASIC_FLAGS;
+
+ if (data_len)
+ {
+ mpvio->cached_server_packet.pkt= (char*)thd->memdup(data, data_len);
+ mpvio->cached_server_packet.pkt_len= data_len;
+ }
+
+ if (data_len < SCRAMBLE_LENGTH)
+ {
+ if (data_len)
+ { /*
+ the first packet *must* have at least 20 bytes of a scramble.
+ if a plugin provided less, we pad it to 20 with zeros
+ */
+ memcpy(scramble_buf, data, data_len);
+ bzero(scramble_buf+data_len, SCRAMBLE_LENGTH-data_len);
+ data= scramble_buf;
+ }
+ else
+ {
+ /*
+ if the default plugin does not provide the data for the scramble at
+ all, we generate a scramble internally anyway, just in case the
+ user account (that will be known only later) uses a
+ native_password_plugin (which needs a scramble). If we don't send a
+ scramble now - wasting 20 bytes in the packet -
+ native_password_plugin will have to send it in a separate packet,
+ adding one more round trip.
+ */
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+ data= thd->scramble;
+ }
+ data_len= SCRAMBLE_LENGTH;
+ }
+
+ if (opt_using_transactions)
+ thd->client_capabilities|= CLIENT_TRANSACTIONS;
+
+ thd->client_capabilities|= CAN_CLIENT_COMPRESS;
+
+ if (ssl_acceptor_fd)
+ {
+ thd->client_capabilities |= CLIENT_SSL;
+ thd->client_capabilities |= CLIENT_SSL_VERIFY_SERVER_CERT;
+ }
+
+ end= strnmov(end, server_version, SERVER_VERSION_LENGTH) + 1;
+ int4store((uchar*) end, mpvio->thd->thread_id);
+ end+= 4;
+
+ /*
+ Old clients does not understand long scrambles, but can ignore packet
+ tail: that's why first part of the scramble is placed here, and second
+ part at the end of packet.
+ */
+ end= (char*)memcpy(end, data, SCRAMBLE_LENGTH_323);
+ end+= SCRAMBLE_LENGTH_323;
+ *end++= 0;
+
+ int2store(end, thd->client_capabilities);
+ /* write server characteristics: up to 16 bytes allowed */
+ end[2]=(char) default_charset_info->number;
+ int2store(end+3, mpvio->thd->server_status);
+ int2store(end+5, thd->client_capabilities >> 16);
+ end[7]= data_len;
+ bzero(end+8, 10);
+ end+= 18;
+ /* write scramble tail */
+ end= (char*)memcpy(end, data + SCRAMBLE_LENGTH_323,
+ data_len - SCRAMBLE_LENGTH_323);
+ end+= data_len - SCRAMBLE_LENGTH_323;
+ end= strmake(end, plugin_name(mpvio->plugin)->str,
+ plugin_name(mpvio->plugin)->length);
+
+ int res= my_net_write(&mpvio->thd->net, (uchar*) buff, (size_t) (end-buff)) ||
+ net_flush(&mpvio->thd->net);
+ my_afree(buff);
+ return res;
+}
+
+static bool secure_auth(THD *thd)
+{
+ if (!opt_secure_auth)
+ return 0;
+
+ /*
+ If the server is running in secure auth mode, short scrambles are
+ forbidden. Extra juggling to report the same error as the old code.
+ */
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
+ thd->security_ctx->user,
+ thd->security_ctx->host_or_ip);
+ general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
+ thd->security_ctx->user,
+ thd->security_ctx->host_or_ip);
+ }
+ else
+ {
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ }
+ return 1;
+}
+
+/**
+ sends a "change plugin" packet, requesting a client to restart authentication
+ using a different authentication plugin
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ 1 byte with the value 254
+ n client plugin to use, \0-terminated
+ n plugin provided data
+
+ In a special case of switching from native_password_plugin to
+ old_password_plugin, the packet contains only one - the first - byte,
+ plugin name is omitted, plugin data aren't needed as the scramble was
+ already sent. This one-byte packet is identical to the "use the short
+ scramble" packet in the protocol before plugins were introduced.
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
+ const uchar *data, uint data_len)
+{
+ DBUG_ASSERT(mpvio->packets_written == 1);
+ DBUG_ASSERT(mpvio->packets_read == 1);
+ NET *net= &mpvio->thd->net;
+ static uchar switch_plugin_request_buf[]= { 254 };
+
+
+ mpvio->status= MPVIO_EXT::FAILURE; // the status is no longer RESTART
+
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+
+ DBUG_ASSERT(client_auth_plugin);
+
+ /*
+ we send an old "short 4.0 scramble request", if we need to request a
+ client to use 4.0 auth plugin (short scramble) and the scramble was
+ already sent to the client
+
+ below, cached_client_reply.plugin is the plugin name that client has used,
+ client_auth_plugin is derived from mysql.user table, for the given
+ user account, it's the plugin that the client need to use to login.
+ */
+ bool switch_from_long_to_short_scramble=
+ native_password_plugin_name.str == mpvio->cached_client_reply.plugin &&
+ client_auth_plugin == old_password_plugin_name.str;
+
+ if (switch_from_long_to_short_scramble)
+ return secure_auth(mpvio->thd) ||
+ my_net_write(net, switch_plugin_request_buf, 1) ||
+ net_flush(net);
+
+ /*
+ We never request a client to switch from a short to long scramble.
+ Plugin-aware clients can do that, but traditionally it meant to
+ ask an old 4.0 client to use the new 4.1 authentication protocol.
+ */
+ bool switch_from_short_to_long_scramble=
+ old_password_plugin_name.str == mpvio->cached_client_reply.plugin &&
+ client_auth_plugin == native_password_plugin_name.str;
+
+ if (switch_from_short_to_long_scramble)
+ {
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ return 1;
+ }
+
+ return net_write_command(net, switch_plugin_request_buf[0],
+ (uchar*)client_auth_plugin,
+ strlen(client_auth_plugin)+1,
+ (uchar*)data, data_len);
+}
+
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+/**
+ Finds acl entry in user database for authentication purposes.
+
+ Finds a user and copies it into mpvio. Reports an authentication
+ failure if a user is not found.
+
+ @note find_acl_user is not the same, because it doesn't take into
+ account the case when user is not empty, but acl_user->user is empty
+
+ @retval 0 found
+ @retval 1 not found
+*/
+
+static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx)
+{
+ DBUG_ASSERT(mpvio->acl_user == 0);
+
+ pthread_mutex_lock(&acl_cache->lock);
+ for (uint i=0 ; i < acl_users.elements ; i++)
+ {
+ ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
+ if ((!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user)) &&
+ compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
+ {
+ mpvio->acl_user= acl_user_tmp->copy(mpvio->thd->mem_root);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&acl_cache->lock);
+
+ if (!mpvio->acl_user)
+ {
+ login_failed_error(mpvio->thd, 0);
+ return 1;
+ }
+
+ /* user account requires non-default plugin and the client is too old */
+ if (mpvio->acl_user->plugin.str != native_password_plugin_name.str &&
+ mpvio->acl_user->plugin.str != old_password_plugin_name.str &&
+ !(mpvio->thd->client_capabilities & CLIENT_PLUGIN_AUTH))
+ {
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ native_password_plugin_name.str));
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ old_password_plugin_name.str));
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ return 1;
+ }
+
+ mpvio->auth_info.user_name= sctx->user;
+ mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str;
+ strmake(mpvio->auth_info.authenticated_as, mpvio->acl_user->user ?
+ mpvio->acl_user->user : "", USERNAME_LENGTH);
+
+ return 0;
+}
+#endif
+
+
+/* the packet format is described in send_change_user_packet() */
+static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
+{
+ THD *thd= mpvio->thd;
+ NET *net= &thd->net;
+ Security_context *sctx= thd->security_ctx;
+
+ char *user= (char*) net->read_pos;
+ char *end= user + packet_length;
+ /* Safe because there is always a trailing \0 at the end of the packet */
+ char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1;
+ char *db= passwd;
+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
+ uint dummy_errors;
+
+ if (passwd >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
+
+ Cast *passwd to an unsigned char, so that it doesn't extend the sign for
+ *passwd > 127 and become 2**32-127+ after casting to uint.
+ */
+ uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ (uchar)(*passwd++) : strlen(passwd));
+
+ db+= passwd_len + 1;
+ /*
+ Database name is always NUL-terminated, so in case of empty database
+ the packet must contain at least the trailing '\0'.
+ */
+ if (db >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+
+ uint db_len= strlen(db);
+
+ char *ptr= db + db_len + 1;
+
+ if (ptr+1 < end)
+ {
+ uint cs_number= uint2korr(ptr);
+ thd_init_client_charset(thd, cs_number);
+ thd->update_charset();
+ }
+
+ /* Convert database and user names to utf8 */
+ db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
+ db, db_len, thd->charset(), &dummy_errors);
+
+ user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors);
+
+ if (!(sctx->user= my_strndup(user_buff, user_len, MYF(MY_WME))))
+ return 1;
+
+ /* Clear variables that are allocated */
+ thd->user_connect= 0;
+ strmake(sctx->priv_user, sctx->user, USERNAME_LENGTH);
+
+ if (thd->make_lex_string(&mpvio->db, db_buff, db_len, 0) == 0)
+ return 1; /* The error is set by make_lex_string(). */
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed.
+ */
+ thd->reset_db(NULL, 0);
+
+ if (!initialized)
+ {
+ // if mysqld's been started with --skip-grant-tables option
+ mpvio->status= MPVIO_EXT::SUCCESS;
+ return 0;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (find_mpvio_user(mpvio, sctx))
+ return 1;
+
+ char *client_plugin;
+ if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ client_plugin= ptr + 2;
+ if (client_plugin >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+ }
+ else
+ {
+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+ client_plugin= native_password_plugin_name.str;
+ else
+ {
+ client_plugin= old_password_plugin_name.str;
+ /*
+ For a passwordless accounts we use native_password_plugin.
+ But when an old 4.0 client connects to it, we change it to
+ old_password_plugin, otherwise MySQL will think that server
+ and client plugins don't match.
+ */
+ if (mpvio->acl_user->auth_string.length == 0)
+ mpvio->acl_user->plugin= old_password_plugin_name;
+ }
+ }
+
+ /* remember the data part of the packet, to present it to plugin in read_packet() */
+ mpvio->cached_client_reply.pkt= passwd;
+ mpvio->cached_client_reply.pkt_len= passwd_len;
+ mpvio->cached_client_reply.plugin= client_plugin;
+ mpvio->status= MPVIO_EXT::RESTART;
+#endif
+
+ return 0;
+}
+
+
+/* the packet format is described in send_client_reply_packet() */
+static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
+ uchar **buff, ulong pkt_len)
+{
+#ifndef EMBEDDED_LIBRARY
+ THD *thd= mpvio->thd;
+ NET *net= &thd->net;
+ char *end;
+
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
+
+ if (pkt_len < MIN_HANDSHAKE_SIZE)
+ return packet_error;
+
+ if (mpvio->connect_errors)
+ reset_host_errors(&net->vio->remote.sin_addr);
+
+ ulong client_capabilities= uint2korr(net->read_pos);
+ if (client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
+ thd->max_client_packet_length= uint4korr(net->read_pos+4);
+ DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
+ thd_init_client_charset(thd, (uint) net->read_pos[8]);
+ thd->update_charset();
+ end= (char*) net->read_pos+32;
+ }
+ else
+ {
+ thd->max_client_packet_length= uint3korr(net->read_pos+2);
+ end= (char*) net->read_pos+5;
+ }
+
+ /* Disable those bits which are not supported by the client. */
+ thd->client_capabilities&= client_capabilities;
+
+ if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
+ thd->variables.sql_mode|= MODE_IGNORE_SPACE;
+
+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
+ if (thd->client_capabilities & CLIENT_SSL)
+ {
+ char error_string[1024] __attribute__((unused));
+
+ /* Do the SSL layering. */
+ if (!ssl_acceptor_fd)
+ return packet_error;
+
+ DBUG_PRINT("info", ("IO layer change in progress..."));
+ if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, error_string))
+ {
+ DBUG_PRINT("error", ("Failed to accept new SSL connection"));
+ return packet_error;
+ }
+
+ DBUG_PRINT("info", ("Reading user information over SSL layer"));
+ pkt_len= my_net_read(net);
+ if (pkt_len == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE)
+ {
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
+ return packet_error;
+ }
+ }
+
+ if (end >= (char*) net->read_pos+ pkt_len +2)
+ return packet_error;
+
+ if (thd->client_capabilities & CLIENT_INTERACTIVE)
+ thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
+ if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
+ opt_using_transactions)
+ net->return_status= &thd->server_status;
+
+ char *user= end;
+ char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1, db_len;
+ char *db= passwd;
+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
+ uint dummy_errors;
+
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
+
+ Cast *passwd to an unsigned char, so that it doesn't extend the sign for
+ *passwd > 127 and become 2**32-127+ after casting to uint.
+ */
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ (uchar)(*passwd++) : strlen(passwd);
+
+ if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
+ {
+ db= db + passwd_len + 1;
+ /* strlen() can't be easily deleted without changing protocol */
+ db_len= strlen(db);
+ }
+ else
+ {
+ db= 0;
+ db_len= 0;
+ }
+
+ if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
+ return packet_error;
+
+ char *client_plugin= passwd + passwd_len + (db ? db_len + 1 : 0);
+
+ /* Since 4.1 all database names are stored in utf8 */
+ if (db)
+ {
+ db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
+ db, db_len, thd->charset(), &dummy_errors);
+ db= db_buff;
+ }
+
+ user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors);
+ user= user_buff;
+
+ /* If username starts and ends in "'", chop them off */
+ if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
+ {
+ user++;
+ user_len-= 2;
+ }
+
+ Security_context *sctx= thd->security_ctx;
+
+ if (thd->make_lex_string(&mpvio->db, db, db_len, 0) == 0)
+ return packet_error; /* The error is set by make_lex_string(). */
+ if (sctx->user)
+ x_free(sctx->user);
+ if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME))))
+ return packet_error; /* The error is set by my_strdup(). */
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed.
+ */
+ thd->reset_db(NULL, 0);
+
+ if (!initialized)
+ {
+ // if mysqld's been started with --skip-grant-tables option
+ mpvio->status= MPVIO_EXT::SUCCESS;
+ return packet_error;
+ }
+
+ if (find_mpvio_user(mpvio, sctx))
+ return packet_error;
+
+ if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ if ((client_plugin + strlen(client_plugin)) >
+ (char *)net->read_pos + pkt_len)
+ return packet_error;
+ }
+ else
+ {
+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+ client_plugin= native_password_plugin_name.str;
+ else
+ {
+ client_plugin= old_password_plugin_name.str;
+ /*
+ For a passwordless accounts we use native_password_plugin.
+ But when an old 4.0 client connects to it, we change it to
+ old_password_plugin, otherwise MySQL will think that server
+ and client plugins don't match.
+ */
+ if (mpvio->acl_user->auth_string.length == 0)
+ mpvio->acl_user->plugin= old_password_plugin_name;
+ }
+ }
+
+ /*
+ if the acl_user needs a different plugin to authenticate
+ (specified in GRANT ... AUTHENTICATED VIA plugin_name ..)
+ we need to restart the authentication in the server.
+ But perhaps the client has already used the correct plugin -
+ in that case the authentication on the client may not need to be
+ restarted and a server auth plugin will read the data that the client
+ has just send. Cache them to return in the next server_mpvio_read_packet().
+ */
+ if (my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ plugin_name(mpvio->plugin)->str) != 0)
+ {
+ mpvio->cached_client_reply.pkt= passwd;
+ mpvio->cached_client_reply.pkt_len= passwd_len;
+ mpvio->cached_client_reply.plugin= client_plugin;
+ mpvio->status= MPVIO_EXT::RESTART;
+ return packet_error;
+ }
+
+ /*
+ ok, we don't need to restart the authentication on the server.
+ but if the client used the wrong plugin, we need to restart
+ the authentication on the client. Do it here, the server plugin
+ doesn't need to know.
+ */
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+
+ if (client_auth_plugin &&
+ my_strcasecmp(system_charset_info, client_plugin, client_auth_plugin))
+ {
+ mpvio->cached_client_reply.plugin= client_plugin;
+ if (send_plugin_request_packet(mpvio,
+ (uchar*)mpvio->cached_server_packet.pkt,
+ mpvio->cached_server_packet.pkt_len))
+ return packet_error;
+
+ passwd_len= my_net_read(&mpvio->thd->net);
+ passwd = (char*)mpvio->thd->net.read_pos;
+ }
+
+ *buff= (uchar*)passwd;
+ return passwd_len;
+#else
+ return 0;
+#endif
+}
+
+
+/**
+ vio->write_packet() callback method for server authentication plugins
+
+ This function is called by a server authentication plugin, when it wants
+ to send data to the client.
+
+ It transparently wraps the data into a handshake packet,
+ and handles plugin negotiation with the client. If necessary,
+ it escapes the plugin data, if it starts with a mysql protocol packet byte.
+*/
+
+static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param,
+ const uchar *packet, int packet_len)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)param;
+ int res;
+
+ /* reset cached_client_reply */
+ mpvio->cached_client_reply.pkt= 0;
+ /* for the 1st packet we wrap plugin data into the handshake packet */
+ if (mpvio->packets_written == 0)
+ res= send_server_handshake_packet(mpvio, (char*)packet, packet_len);
+ else if (mpvio->status == MPVIO_EXT::RESTART)
+ res= send_plugin_request_packet(mpvio, packet, packet_len);
+ else if (packet_len > 0 && (*packet == 1 || *packet == 255 || *packet == 254))
+ {
+ /*
+ we cannot allow plugin data packet to start from 255 or 254 -
+ as the client will treat it as an error or "change plugin" packet.
+ We'll escape these bytes with \1. Consequently, we
+ have to escape \1 byte too.
+ */
+ res= net_write_command(&mpvio->thd->net, 1, (uchar*)"", 0,
+ packet, packet_len);
+ }
+ else
+ {
+ res= my_net_write(&mpvio->thd->net, packet, packet_len) ||
+ net_flush(&mpvio->thd->net);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+
+/**
+ vio->read_packet() callback method for server authentication plugins
+
+ This function is called by a server authentication plugin, when it wants
+ to read data from the client.
+
+ It transparently extracts the client plugin data, if embedded into
+ a client authentication handshake packet, and handles plugin negotiation
+ with the client, if necessary.
+*/
+
+static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)param;
+ ulong pkt_len;
+
+ if (mpvio->packets_written == 0)
+ {
+ /*
+ plugin wants to read the data without sending anything first.
+ send an empty packet to force a server handshake packet to be sent
+ */
+ if (server_mpvio_write_packet(mpvio, 0, 0))
+ pkt_len= packet_error;
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+ }
+ else
+ if (mpvio->cached_client_reply.pkt)
+ {
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::RESTART);
+ DBUG_ASSERT(mpvio->packets_read > 0);
+ /*
+ if the have the data cached from the last server_mpvio_read_packet
+ (which can be the case if it's a restarted authentication)
+ and a client has used the correct plugin, then we can return the
+ cached data straight away and avoid one round trip.
+ */
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+ if (client_auth_plugin == 0 ||
+ my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin,
+ client_auth_plugin) == 0)
+ {
+ mpvio->status= MPVIO_EXT::FAILURE;
+ *buf= (uchar*)mpvio->cached_client_reply.pkt;
+ mpvio->cached_client_reply.pkt= 0;
+ mpvio->packets_read++;
+ return (int)mpvio->cached_client_reply.pkt_len;
+ }
+ /*
+ But if the client has used the wrong plugin, the cached data are
+ useless. Furthermore, we have to send a "change plugin" request
+ to the client.
+ */
+ if (server_mpvio_write_packet(mpvio, 0, 0))
+ pkt_len= packet_error;
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+ }
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+
+ if (pkt_len == packet_error)
+ goto err;
+
+ mpvio->packets_read++;
+
+ /*
+ the 1st packet has the plugin data wrapped into the client authentication
+ handshake packet
+ */
+ if (mpvio->packets_read == 1)
+ {
+ pkt_len= parse_client_handshake_packet(mpvio, buf, pkt_len);
+ if (pkt_len == packet_error)
+ goto err;
+ }
+ else
+ *buf = mpvio->thd->net.read_pos;
+
+ return (int)pkt_len;
+
+err:
+ if (mpvio->status == MPVIO_EXT::FAILURE && !mpvio->thd->is_error())
+ {
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0),
+ mpvio->thd->security_ctx->host_or_ip);
+ }
+ return -1;
+}
+
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+static void server_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)vio;
+ mpvio_info(mpvio->thd->net.vio, info);
+}
+
+
+static bool acl_check_ssl(THD *thd, ACL_USER *acl_user)
+{
+#if defined(HAVE_OPENSSL)
+ Vio *vio=thd->net.vio;
+ SSL *ssl= (SSL*) vio->ssl_arg;
+ X509 *cert;
+#endif
+
+ /*
+ At this point we know that user is allowed to connect
+ from given host by given username/password pair. Now
+ we check if SSL is required, if user is using SSL and
+ if X509 certificate attributes are OK
+ */
+ switch (acl_user->ssl_type) {
+ case SSL_TYPE_NOT_SPECIFIED: // Impossible
+ case SSL_TYPE_NONE: // SSL is not required
+ return 0;
+#if defined(HAVE_OPENSSL)
+ case SSL_TYPE_ANY: // Any kind of SSL is ok
+ return vio_type(vio) != VIO_TYPE_SSL;
+ case SSL_TYPE_X509: /* Client should have any valid certificate. */
+ /*
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
+ */
+ if (vio_type(vio) == VIO_TYPE_SSL &&
+ SSL_get_verify_result(ssl) == X509_V_OK &&
+ (cert= SSL_get_peer_certificate(ssl)))
+ {
+ X509_free(cert);
+ return 0;
+ }
+ return 1;
+ case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
+ /* If a cipher name is specified, we compare it to actual cipher in use. */
+ if (vio_type(vio) != VIO_TYPE_SSL ||
+ SSL_get_verify_result(ssl) != X509_V_OK)
+ return 1;
+ if (acl_user->ssl_cipher)
+ {
+ DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
+ acl_user->ssl_cipher,SSL_get_cipher(ssl)));
+ if (strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl)))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
+ acl_user->ssl_cipher, SSL_get_cipher(ssl));
+ return 1;
+ }
+ }
+ /* Prepare certificate (if exists) */
+ if (!(cert= SSL_get_peer_certificate(ssl)))
+ return 1;
+ /* If X509 issuer is specified, we check it... */
+ if (acl_user->x509_issuer)
+ {
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ acl_user->x509_issuer, ptr));
+ if (strcmp(acl_user->x509_issuer, ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 issuer mismatch: should be '%s' "
+ "but is '%s'", acl_user->x509_issuer, ptr);
+ free(ptr);
+ X509_free(cert);
+ return 1;
+ }
+ free(ptr);
+ }
+ /* X509 subject is specified, we check it .. */
+ if (acl_user->x509_subject)
+ {
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
+ acl_user->x509_subject, ptr);
+ free(ptr);
+ X509_free(cert);
+ return 1;
+ }
+ free(ptr);
+ }
+ X509_free(cert);
+ return 0;
+#else /* HAVE_OPENSSL */
+ default:
+ /*
+ If we don't have SSL but SSL is required for this user the
+ authentication should fail.
+ */
+ return 1;
+#endif /* HAVE_OPENSSL */
+ }
+ return 1;
+}
+
+static int do_auth_once(THD *thd, LEX_STRING *auth_plugin_name,
+ MPVIO_EXT *mpvio)
+{
+ int res= CR_OK, old_status= MPVIO_EXT::FAILURE;
+ bool unlock_plugin= false;
+ plugin_ref plugin;
+
+ if (auth_plugin_name->str == native_password_plugin_name.str)
+ plugin= native_password_plugin;
+ else
+#ifndef EMBEDDED_LIBRARY
+ if (auth_plugin_name->str == old_password_plugin_name.str)
+ plugin= old_password_plugin;
+ else
+ if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
+ MYSQL_AUTHENTICATION_PLUGIN)))
+ unlock_plugin= true;
+#endif
+
+ mpvio->plugin= plugin;
+ old_status= mpvio->status;
+
+ if (plugin)
+ {
+ st_mysql_auth *auth= (st_mysql_auth*)plugin_decl(plugin)->info;
+ res= auth->authenticate_user(mpvio, &mpvio->auth_info);
+
+ if (unlock_plugin)
+ plugin_unlock(thd, plugin);
+ }
+ else
+ {
+ /* Server cannot load the required plugin. */
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth_plugin_name->str);
+ res= CR_ERROR;
+ }
+
+ /*
+ If the status was MPVIO_EXT::RESTART before the authenticate_user() call
+ it can never be MPVIO_EXT::RESTART after the call, because any call
+ to write_packet() or read_packet() will reset the status.
+
+ But (!) if a plugin never called a read_packet() or write_packet(), the
+ status will stay unchanged. We'll fix it, by resetting the status here.
+ */
+ if (old_status == MPVIO_EXT::RESTART && mpvio->status == MPVIO_EXT::RESTART)
+ mpvio->status= MPVIO_EXT::FAILURE; // reset to the default
+
+ return res;
+}
+
+/**
+ Perform the handshake, authorize the client and update thd sctx variables.
+
+ @param thd thread handle
+ @param connect_errors number of previous failed connect attemps
+ from this host
+ @param com_change_user_pkt_len size of the COM_CHANGE_USER packet
+ (without the first, command, byte) or 0
+ if it's not a COM_CHANGE_USER (that is, if
+ it's a new connection)
+
+ @retval 0 success, thd is updated.
+ @retval 1 error
+*/
+
+bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
+{
+ int res= CR_OK;
+ MPVIO_EXT mpvio;
+ LEX_STRING *auth_plugin_name= default_auth_plugin_name;
+ enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER
+ : COM_CONNECT;
+ DBUG_ENTER("acl_authenticate");
+
+ compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
+
+ bzero(&mpvio, sizeof(mpvio));
+ mpvio.read_packet= server_mpvio_read_packet;
+ mpvio.write_packet= server_mpvio_write_packet;
+ mpvio.info= server_mpvio_info;
+ mpvio.thd= thd;
+ mpvio.connect_errors= connect_errors;
+ mpvio.status= MPVIO_EXT::FAILURE;
+
+ if (command == COM_CHANGE_USER)
+ {
+ mpvio.packets_written++; // pretend that a server handshake packet was sent
+ mpvio.packets_read++; // take COM_CHANGE_USER packet into account
+
+ if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len))
+ DBUG_RETURN(1);
+
+ DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
+ mpvio.status == MPVIO_EXT::SUCCESS);
+ }
+ else
+ {
+ /* mark the thd as having no scramble yet */
+ thd->scramble[SCRAMBLE_LENGTH]= 1;
+
+ /*
+ perform the first authentication attempt, with the default plugin.
+ This sends the server handshake packet, reads the client reply
+ with a user name, and performs the authentication if everyone has used
+ the correct plugin.
+ */
+ res= do_auth_once(thd, auth_plugin_name, &mpvio);
+ }
+
+ /*
+ retry the authentication, if - after receiving the user name -
+ we found that we need to switch to a non-default plugin
+ */
+ if (mpvio.status == MPVIO_EXT::RESTART)
+ {
+ DBUG_ASSERT(mpvio.acl_user);
+ DBUG_ASSERT(command == COM_CHANGE_USER ||
+ my_strcasecmp(system_charset_info, auth_plugin_name->str,
+ mpvio.acl_user->plugin.str));
+ auth_plugin_name= &mpvio.acl_user->plugin;
+ res= do_auth_once(thd, auth_plugin_name, &mpvio);
+ }
+
+ Security_context *sctx= thd->security_ctx;
+ ACL_USER *acl_user= mpvio.acl_user;
+
+ thd->password= mpvio.auth_info.password_used; // remember for error messages
+
+ /*
+ Log the command here so that the user can check the log
+ for the tried logins and also to detect break-in attempts.
+
+ if sctx->user is unset it's protocol failure, bad packet.
+ */
+ if (sctx->user)
+ {
+ if (strcmp(sctx->priv_user, sctx->user))
+ {
+ general_log_print(thd, command, "%s@%s as %s on %s",
+ sctx->user, sctx->host_or_ip,
+ sctx->priv_user[0] ? sctx->priv_user : "anonymous",
+ mpvio.db.str ? mpvio.db.str : (char*) "");
+ }
+ else
+ general_log_print(thd, command, (char*) "%s@%s on %s",
+ sctx->user, sctx->host_or_ip,
+ mpvio.db.str ? mpvio.db.str : (char*) "");
+ }
+
+ if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
+ {
+ DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
+
+ if (!thd->is_error())
+ login_failed_error(thd, thd->password);
+ DBUG_RETURN(1);
+ }
+
+ if (initialized) // if not --skip-grant-tables
+ {
+ sctx->master_access= acl_user->access;
+ strmake(sctx->priv_user, mpvio.auth_info.authenticated_as, USERNAME_LENGTH);
+ if (acl_user->host.hostname)
+ strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *sctx->priv_host= 0;
+
+ /*
+ OK. Let's check the SSL. Historically it was checked after the password,
+ as an additional layer, not instead of the password
+ (in which case it would've been a plugin too).
+ */
+ if (acl_check_ssl(thd, acl_user))
+ {
+ login_failed_error(thd, thd->password);
+ DBUG_RETURN(1);
+ }
+
+ /* Don't allow the user to connect if he has done too many queries */
+ if ((acl_user->user_resource.questions || acl_user->user_resource.updates ||
+ acl_user->user_resource.conn_per_hour ||
+ acl_user->user_resource.user_conn || max_user_connections) &&
+ get_or_create_user_conn(thd,
+ (opt_old_style_user_limits ? sctx->user : sctx->priv_user),
+ (opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
+ &acl_user->user_resource))
+ DBUG_RETURN(1); // The error is set by get_or_create_user_conn()
+ }
+ else
+ sctx->skip_grants();
+
+ if (thd->user_connect &&
+ (thd->user_connect->user_resources.conn_per_hour ||
+ thd->user_connect->user_resources.user_conn ||
+ max_user_connections) &&
+ check_for_max_user_connections(thd, thd->user_connect))
+ {
+ status_var_increment(denied_connections);
+ DBUG_RETURN(1); // The error is set in check_for_max_user_connections()
+ }
+
+ DBUG_PRINT("info",
+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
+ "Login user: '%s' Priv_user: '%s' Using password: %s "
+ "Access: %lu db: '%s'",
+ thd->client_capabilities, thd->max_client_packet_length,
+ sctx->host_or_ip, sctx->user, sctx->priv_user,
+ thd->password ? "yes": "no",
+ sctx->master_access, mpvio.db.str));
+
+ if (command == COM_CONNECT &&
+ !(thd->main_security_ctx.master_access & SUPER_ACL))
+ {
+ pthread_mutex_lock(&LOCK_connection_count);
+ bool count_ok= (*thd->scheduler->connection_count <=
+ *thd->scheduler->max_connections);
+ VOID(pthread_mutex_unlock(&LOCK_connection_count));
+ if (!count_ok)
+ { // too many connections
+ my_error(ER_CON_COUNT_ERROR, MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+
+ /*
+ This is the default access rights for the current database. It's
+ set to 0 here because we don't have an active database yet (and we
+ may not have an active database to set.
+ */
+ sctx->db_access=0;
+
+ /* Change a database if necessary */
+ if (mpvio.db.length)
+ {
+ if (mysql_change_db(thd, &mpvio.db, FALSE))
+ {
+ /* mysql_change_db() has pushed the error message. */
+ if (thd->user_connect)
+ {
+ status_var_increment(thd->status_var.access_denied_errors);
+ decrease_user_connections(thd->user_connect);
+ thd->user_connect= 0;
+ }
+ DBUG_RETURN(1);
+ }
+ }
+
+ thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
+
+ if (res == CR_OK_HANDSHAKE_COMPLETE)
+ thd->main_da.disable_status();
+ else
+ my_ok(thd);
+
+ /* Ready to handle queries */
+ DBUG_RETURN(0);
+}
+
+
+/**
+ MySQL Server Password Authentication Plugin
+
+ In the MySQL authentication protocol:
+ 1. the server sends the random scramble to the client
+ 2. client sends the encrypted password back to the server
+ 3. the server checks the password.
+*/
+
+static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ uchar *pkt;
+ int pkt_len;
+ MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
+ THD *thd=mpvio->thd;
+
+ /* generate the scramble, or reuse the old one */
+ if (thd->scramble[SCRAMBLE_LENGTH])
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+
+ /* send it to the client */
+ if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+ return CR_ERROR;
+
+ /* reply and authenticate */
+
+ /*
+ <digression>
+ This is more complex than it looks.
+
+ The plugin (we) may be called right after the client was connected -
+ and will need to send a scramble, read reply, authenticate.
+
+ Or the plugin may be called after another plugin has sent a scramble,
+ and read the reply. If the client has used the correct client-plugin,
+ we won't need to read anything here from the client, the client
+ has already sent a reply with everything we need for authentication.
+
+ Or the plugin may be called after another plugin has sent a scramble,
+ and read the reply, but the client has used the wrong client-plugin.
+ We'll need to sent a "switch to another plugin" packet to the
+ client and read the reply. "Use the short scramble" packet is a special
+ case of "switch to another plugin" packet.
+
+ Or, perhaps, the plugin may be called after another plugin has
+ done the handshake but did not send a useful scramble. We'll need
+ to send a scramble (and perhaps a "switch to another plugin" packet)
+ and read the reply.
+
+ Besides, a client may be an old one, that doesn't understand plugins.
+ Or doesn't even understand 4.0 scramble.
+
+ And we want to keep the same protocol on the wire unless non-native
+ plugins are involved.
+
+ Anyway, it still looks simple from a plugin point of view:
+ "send the scramble, read the reply and authenticate".
+ All the magic is transparently handled by the server.
+ </digression>
+ */
+
+ /* read the reply with the encrypted password */
+ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+ return CR_ERROR;
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return CR_OK;
+#endif
+
+ if (pkt_len == 0) /* no password */
+ return info->auth_string[0] ? CR_ERROR : CR_OK;
+
+ info->password_used = 1;
+ if (pkt_len == SCRAMBLE_LENGTH)
+ return check_scramble(pkt, thd->scramble, mpvio->acl_user->salt) ?
+ CR_ERROR : CR_OK;
+
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ return CR_ERROR;
+}
+
+
+static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ uchar *pkt;
+ int pkt_len;
+ MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
+ THD *thd=mpvio->thd;
+
+ /* generate the scramble, or reuse the old one */
+ if (thd->scramble[SCRAMBLE_LENGTH])
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+
+ /* send it to the client */
+ if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+ return CR_ERROR;
+
+ /* read the reply and authenticate */
+ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+ return CR_ERROR;
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return CR_OK;
+#endif
+
+ /*
+ legacy: if switch_from_long_to_short_scramble,
+ the password is sent \0-terminated, the pkt_len is always 9 bytes.
+ We need to figure out the correct scramble length here.
+ */
+ if (pkt_len == SCRAMBLE_LENGTH_323+1)
+ pkt_len= strnlen((char*)pkt, pkt_len);
+
+ if (pkt_len == 0) /* no password */
+ return info->auth_string[0] ? CR_ERROR : CR_OK;
+
+ if (secure_auth(thd))
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ if (pkt_len == SCRAMBLE_LENGTH_323)
+ return check_scramble_323(pkt, thd->scramble,
+ (ulong *)mpvio->acl_user->salt) ? CR_ERROR : CR_OK;
+
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ return CR_ERROR;
+}
+
+static struct st_mysql_auth native_password_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ native_password_plugin_name.str,
+ native_password_authenticate
+};
+
+static struct st_mysql_auth old_password_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ old_password_plugin_name.str,
+ old_password_authenticate
+};
+
+mysql_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
+
=== modified file 'sql/sql_acl.h'
--- a/sql/sql_acl.h 2009-11-21 11:18:21 +0000
+++ b/sql/sql_acl.h 2010-03-29 15:13:53 +0000
@@ -161,53 +161,6 @@ enum mysql_db_table_field
extern const TABLE_FIELD_DEF mysql_db_table_def;
-/* Classes */
-
-struct acl_host_and_ip
-{
- char *hostname;
- long ip,ip_mask; // Used with masked ip:s
-};
-
-
-class ACL_ACCESS {
-public:
- ulong sort;
- ulong access;
-};
-
-
-/* ACL_HOST is used if no host is specified */
-
-class ACL_HOST :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *db;
-};
-
-
-class ACL_USER :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- uint hostname_length;
- USER_RESOURCES user_resource;
- char *user;
- uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
- uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 3.23, 20 - 4.1.1
- enum SSL_type ssl_type;
- const char *ssl_cipher, *x509_issuer, *x509_subject;
-};
-
-
-class ACL_DB :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *user,*db;
-};
-
/* prototypes */
bool hostname_requires_resolving(const char *hostname);
@@ -216,10 +169,9 @@ my_bool acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip,
const char *user, const char *db, my_bool db_is_pattern);
-int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd,
- uint passwd_len);
-bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
- char *ip, char *db);
+bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len);
+bool acl_getroot(Security_context *sctx, char *user, char *host,
+ char *ip, char *db);
bool acl_check_host(const char *host, const char *ip);
int check_change_password(THD *thd, const char *host, const char *user,
char *password, uint password_len);
=== modified file 'sql/sql_builtin.cc.in'
--- a/sql/sql_builtin.cc.in 2009-11-29 23:08:56 +0000
+++ b/sql/sql_builtin.cc.in 2010-03-29 15:13:53 +0000
@@ -19,10 +19,10 @@
typedef struct st_mysql_plugin builtin_plugin[];
extern builtin_plugin
- builtin_binlog_plugin@mysql_plugin_defs@;
+ builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@;
struct st_mysql_plugin *mysqld_builtins[]=
{
- builtin_binlog_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
};
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_class.cc 2010-03-29 15:13:53 +0000
@@ -2984,9 +2984,9 @@ void THD::set_status_var_init()
void Security_context::init()
{
- host= user= priv_user= ip= 0;
+ host= user= ip= 0;
host_or_ip= "connecting host";
- priv_host[0]= '\0';
+ priv_user[0]= priv_host[0]= '\0';
master_access= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access= NO_ACCESS;
@@ -3010,8 +3010,7 @@ void Security_context::skip_grants()
/* privileges for the user are unknown everything is allowed */
host_or_ip= (char *)"";
master_access= ~NO_ACCESS;
- priv_user= (char *)"";
- *priv_host= '\0';
+ *priv_user= *priv_host= '\0';
}
@@ -3053,7 +3052,7 @@ bool Security_context::set_user(char *us
of a statement under credentials of a different user, e.g.
definer of a procedure, we authenticate this user in a local
instance of Security_context by means of this method (and
- ultimately by means of acl_getroot_no_password), and make the
+ ultimately by means of acl_getroot), and make the
local instance active in the thread by re-setting
thd->security_ctx pointer.
@@ -3087,19 +3086,12 @@ change_security_context(THD *thd,
DBUG_ASSERT(definer_user->str && definer_host->str);
*backup= NULL;
- /*
- The current security context may have NULL members
- if we have just started the thread and not authenticated
- any user. This use case is currently in events worker thread.
- */
- needs_change= (thd->security_ctx->priv_user == NULL ||
- strcmp(definer_user->str, thd->security_ctx->priv_user) ||
- thd->security_ctx->priv_host == NULL ||
+ needs_change= (strcmp(definer_user->str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info, definer_host->str,
thd->security_ctx->priv_host));
if (needs_change)
{
- if (acl_getroot_no_password(this, definer_user->str, definer_host->str,
+ if (acl_getroot(this, definer_user->str, definer_host->str,
definer_host->str, db->str))
{
my_error(ER_NO_SUCH_USER, MYF(0), definer_user->str,
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_class.h 2010-03-29 15:13:53 +0000
@@ -805,7 +805,8 @@ public:
priv_user - The user privilege we are using. May be "" for anonymous user.
ip - client IP
*/
- char *host, *user, *priv_user, *ip;
+ char *host, *user, *ip;
+ char priv_user[USERNAME_LENGTH];
/* The host privilege we are using */
char priv_host[MAX_HOSTNAME];
/* points to host if host is available, otherwise points to ip */
=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_connect.cc 2010-03-29 15:13:53 +0000
@@ -27,24 +27,6 @@ extern pthread_mutex_t LOCK_global_user_
extern pthread_mutex_t LOCK_global_table_stats;
extern pthread_mutex_t LOCK_global_index_stats;
-#ifdef HAVE_OPENSSL
-/*
- Without SSL the handshake consists of one packet. This packet
- has both client capabilites and scrambled password.
- With SSL the handshake might consist of two packets. If the first
- packet (client capabilities) has CLIENT_SSL flag set, we have to
- switch to SSL and read the second packet. The scrambled password
- is in the second packet and client_capabilites field will be ignored.
- Maybe it is better to accept flags other than CLIENT_SSL from the
- second packet?
-*/
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
-#else
-#define MIN_HANDSHAKE_SIZE 6
-#endif /* HAVE_OPENSSL */
-
#ifdef __WIN__
extern void win_install_sigabrt_handler();
#endif
@@ -56,9 +38,9 @@ extern void win_install_sigabrt_handler(
#ifndef NO_EMBEDDED_ACCESS_CHECKS
static HASH hash_user_connections;
-static int get_or_create_user_conn(THD *thd, const char *user,
- const char *host,
- USER_RESOURCES *mqh)
+int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host,
+ USER_RESOURCES *mqh)
{
int return_val= 0;
size_t temp_len, user_len;
@@ -124,7 +106,6 @@ end:
1 error
*/
-static
int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
@@ -276,240 +257,6 @@ end:
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-
-/**
- Check if user exist and password supplied is correct.
-
- @param thd thread handle, thd->security_ctx->{host,user,ip} are used
- @param command originator of the check: now check_user is called
- during connect and change user procedures; used for
- logging.
- @param passwd scrambled password received from client
- @param passwd_len length of scrambled password
- @param db database name to connect to, may be NULL
- @param check_count TRUE if establishing a new connection. In this case
- check that we have not exceeded the global
- max_connections limist
-
- @note Host, user and passwd may point to communication buffer.
- Current implementation does not depend on that, but future changes
- should be done with this in mind; 'thd' is INOUT, all other params
- are 'IN'.
-
- @retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and
- thd->db are updated; OK is sent to the client.
- @retval 1 error, e.g. access denied or handshake error, not sent to
- the client. A message is pushed into the error stack.
-*/
-
-int
-check_user(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count)
-{
- DBUG_ENTER("check_user");
- LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
-
- /*
- Clear thd->db as it points to something, that will be freed when
- connection is closed. We don't want to accidentally free a wrong
- pointer if connect failed. Also in case of 'CHANGE USER' failure,
- current database will be switched to 'no database selected'.
- */
- thd->reset_db(NULL, 0);
-
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
- thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights
- /* Change database if necessary */
- if (db && db[0])
- {
- if (mysql_change_db(thd, &db_str, FALSE))
- DBUG_RETURN(1);
- }
- my_ok(thd);
- DBUG_RETURN(0);
-#else
-
- my_bool opt_secure_auth_local;
- pthread_mutex_lock(&LOCK_global_system_variables);
- opt_secure_auth_local= opt_secure_auth;
- pthread_mutex_unlock(&LOCK_global_system_variables);
-
- /*
- If the server is running in secure auth mode, short scrambles are
- forbidden.
- */
- if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
- {
- my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
- general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
- DBUG_RETURN(1);
- }
- if (passwd_len != 0 &&
- passwd_len != SCRAMBLE_LENGTH &&
- passwd_len != SCRAMBLE_LENGTH_323)
- {
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
-
- USER_RESOURCES ur;
- int res= acl_getroot(thd, &ur, passwd, passwd_len);
-#ifndef EMBEDDED_LIBRARY
- if (res == -1)
- {
- /*
- This happens when client (new) sends password scrambled with
- scramble(), but database holds old value (scrambled with
- scramble_323()). Here we please client to send scrambled_password
- in old format.
- */
- NET *net= &thd->net;
- if (opt_secure_auth_local)
- {
- my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip);
- general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
- /* We have to read very specific packet size */
- if (send_old_password_request(thd) ||
- my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
- /* Final attempt to check the user based on reply */
- /* So as passwd is short, errcode is always >= 0 */
- res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
- }
-#endif /*EMBEDDED_LIBRARY*/
- /* here res is always >= 0 */
- if (res == 0)
- {
- if (!(thd->main_security_ctx.master_access &
- NO_ACCESS)) // authentication is OK
- {
- DBUG_PRINT("info",
- ("Capabilities: %lu packet_length: %ld Host: '%s' "
- "Login user: '%s' Priv_user: '%s' Using password: %s "
- "Access: %lu db: '%s'",
- thd->client_capabilities,
- thd->max_client_packet_length,
- thd->main_security_ctx.host_or_ip,
- thd->main_security_ctx.user,
- thd->main_security_ctx.priv_user,
- passwd_len ? "yes": "no",
- thd->main_security_ctx.master_access,
- (thd->db ? thd->db : "*none*")));
-
- if (check_count)
- {
- bool count_ok= 1;
-
- if (!(thd->main_security_ctx.master_access & SUPER_ACL))
- {
- pthread_mutex_lock(&LOCK_connection_count);
- count_ok= (*thd->scheduler->connection_count <=
- *thd->scheduler->max_connections);
- VOID(pthread_mutex_unlock(&LOCK_connection_count));
- }
- if (!count_ok)
- { // too many connections
- my_error(ER_CON_COUNT_ERROR, MYF(0));
- DBUG_RETURN(1);
- }
- }
-
- /*
- Log the command before authentication checks, so that the user can
- check the log for the tried login tried and also to detect
- break-in attempts.
- */
- general_log_print(thd, command,
- (thd->main_security_ctx.priv_user ==
- thd->main_security_ctx.user ?
- (char*) "%s@%s on %s" :
- (char*) "%s@%s as anonymous on %s"),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- db ? db : (char*) "");
-
- /*
- This is the default access rights for the current database. It's
- set to 0 here because we don't have an active database yet (and we
- may not have an active database to set.
- */
- thd->main_security_ctx.db_access=0;
-
- /* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
- max_user_connections) &&
- get_or_create_user_conn(thd,
- (opt_old_style_user_limits ? thd->main_security_ctx.user :
- thd->main_security_ctx.priv_user),
- (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
- thd->main_security_ctx.priv_host),
- &ur))
- {
- /* The error is set by get_or_create_user_conn(). */
- DBUG_RETURN(1);
- }
- if (thd->user_connect &&
- (thd->user_connect->user_resources.conn_per_hour ||
- thd->user_connect->user_resources.user_conn ||
- max_user_connections) &&
- check_for_max_user_connections(thd, thd->user_connect))
- {
- /* The error is set in check_for_max_user_connections(). */
- status_var_increment(denied_connections);
- DBUG_RETURN(1);
- }
-
- /* Change database if necessary */
- if (db && db[0])
- {
- if (mysql_change_db(thd, &db_str, FALSE))
- {
- /* mysql_change_db() has pushed the error message. */
- if (thd->user_connect)
- decrease_user_connections(thd->user_connect);
- status_var_increment(thd->status_var.access_denied_errors);
- DBUG_RETURN(1);
- }
- }
- my_ok(thd);
- thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
- thd->password= test(passwd_len); // remember for error messages
- /* Ready to handle queries */
- DBUG_RETURN(0);
- }
- }
- else if (res == 2) // client gave short hash, server has long hash
- {
- my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
- general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
- DBUG_RETURN(1);
- }
- my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
- general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
- status_var_increment(thd->status_var.access_denied_errors);
-
- DBUG_RETURN(1);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-}
-
-
/*
Check for maximum allowable user connections, if the mysqld server is
started with corresponding variable that is greater then 0.
@@ -1088,9 +835,8 @@ bool init_new_connection_handler_thread(
thd thread handle
RETURN
- 0 success, OK is sent to user, thd is updated.
- -1 error, which is sent to user
- > 0 error code (not sent to user)
+ 0 success, thd is updated.
+ 1 error
*/
#ifndef EMBEDDED_LIBRARY
@@ -1098,8 +844,6 @@ static int check_connection(THD *thd)
{
uint connect_errors= 0;
NET *net= &thd->net;
- ulong pkt_len= 0;
- char *end;
DBUG_PRINT("info",
("New connection received on %s", vio_description(net->vio)));
@@ -1161,200 +905,10 @@ static int check_connection(THD *thd)
}
vio_keepalive(net->vio, TRUE);
- ulong server_capabilites;
- {
- /* buff[] needs to big enough to hold the server_version variable */
- char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64];
- server_capabilites= CLIENT_BASIC_FLAGS;
-
- if (opt_using_transactions)
- server_capabilites|= CLIENT_TRANSACTIONS;
-#ifdef HAVE_COMPRESS
- server_capabilites|= CLIENT_COMPRESS;
-#endif /* HAVE_COMPRESS */
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- {
- server_capabilites |= CLIENT_SSL; /* Wow, SSL is available! */
- server_capabilites |= CLIENT_SSL_VERIFY_SERVER_CERT;
- }
-#endif /* HAVE_OPENSSL */
-
- end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
- int4store((uchar*) end, thd->thread_id);
- end+= 4;
- /*
- So as check_connection is the only entry point to authorization
- procedure, scramble is set here. This gives us new scramble for
- each handshake.
- */
- create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
- /*
- Old clients does not understand long scrambles, but can ignore packet
- tail: that's why first part of the scramble is placed here, and second
- part at the end of packet.
- */
- end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
-
- int2store(end, server_capabilites);
- /* write server characteristics: up to 16 bytes allowed */
- end[2]=(char) default_charset_info->number;
- int2store(end+3, thd->server_status);
- bzero(end+5, 13);
- end+= 18;
- /* write scramble tail */
- end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
- SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
-
- /* At this point we write connection message and read reply */
- if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
- (uchar*) buff, (size_t) (end-buff)) ||
- (pkt_len= my_net_read(net)) == packet_error ||
- pkt_len < MIN_HANDSHAKE_SIZE)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0),
- thd->main_security_ctx.host_or_ip);
- return 1;
- }
- }
-#ifdef _CUSTOMCONFIG_
-#include "_cust_sql_parse.h"
-#endif
- if (connect_errors)
- reset_host_errors(&thd->remote.sin_addr);
if (thd->packet.alloc(thd->variables.net_buffer_length))
return 1; /* The error is set by alloc(). */
- thd->client_capabilities= uint2korr(net->read_pos);
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
- thd->max_client_packet_length= uint4korr(net->read_pos+4);
- DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
- thd_init_client_charset(thd, (uint) net->read_pos[8]);
- thd->update_charset();
- end= (char*) net->read_pos+32;
- }
- else
- {
- thd->max_client_packet_length= uint3korr(net->read_pos+2);
- end= (char*) net->read_pos+5;
- }
- /*
- Disable those bits which are not supported by the server.
- This is a precautionary measure, if the client lies. See Bug#27944.
- */
- thd->client_capabilities&= server_capabilites;
-
- if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
- thd->variables.sql_mode|= MODE_IGNORE_SPACE;
-#ifdef HAVE_OPENSSL
- DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
- if (thd->client_capabilities & CLIENT_SSL)
- {
- char error_string[1024];
- /* Do the SSL layering. */
- if (!ssl_acceptor_fd)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, error_string))
- {
- DBUG_PRINT("error", ("Failed to accept new SSL connection"));
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- DBUG_PRINT("info", ("Reading user information over SSL layer"));
- if ((pkt_len= my_net_read(net)) == packet_error ||
- pkt_len < NORMAL_HANDSHAKE_SIZE)
- {
- DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
- pkt_len));
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- }
-#endif /* HAVE_OPENSSL */
-
- if (end >= (char*) net->read_pos+ pkt_len +2)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
-
- if (thd->client_capabilities & CLIENT_INTERACTIVE)
- thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
- if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
- opt_using_transactions)
- net->return_status= &thd->server_status;
-
- char *user= end;
- char *passwd= strend(user)+1;
- uint user_len= passwd - user - 1;
- char *db= passwd;
- char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
- char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
- uint dummy_errors;
-
- /*
- Old clients send null-terminated string as password; new clients send
- the size (1 byte) + string (not null-terminated). Hence in case of empty
- password both send '\0'.
-
- This strlen() can't be easily deleted without changing protocol.
-
- Cast *passwd to an unsigned char, so that it doesn't extend the sign for
- *passwd > 127 and become 2**32-127+ after casting to uint.
- */
- uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- (uchar)(*passwd++) : strlen(passwd);
- db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
- db + passwd_len + 1 : 0;
- /* strlen() can't be easily deleted without changing protocol */
- uint db_len= db ? strlen(db) : 0;
-
- if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
-
- /* Since 4.1 all database names are stored in utf8 */
- if (db)
- {
- db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info,
- db, db_len,
- thd->charset(), &dummy_errors)]= 0;
- db= db_buff;
- }
-
- user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
- system_charset_info, user, user_len,
- thd->charset(), &dummy_errors)]= '\0';
- user= user_buff;
-
- /* If username starts and ends in "'", chop them off */
- if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
- {
- user[user_len-1]= 0;
- user++;
- user_len-= 2;
- }
-
- if (thd->main_security_ctx.user)
- x_free(thd->main_security_ctx.user);
- if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
- return 1; /* The error is set by my_strdup(). */
- return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
+ return acl_authenticate(thd, connect_errors, 0);
}
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_insert.cc 2010-03-29 15:13:53 +0000
@@ -1778,8 +1778,10 @@ public:
table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0),
group_count(0)
{
- thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user;
+ thd.security_ctx->user=(char*) delayed_user;
thd.security_ctx->host=(char*) my_localhost;
+ strmake(thd.security_ctx->priv_user, thd.security_ctx->user,
+ USERNAME_LENGTH);
thd.current_tablenr=0;
thd.version=refresh_version;
thd.command=COM_DELAYED_INSERT;
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_lex.h 2010-03-29 15:13:53 +0000
@@ -952,6 +952,8 @@ extern sys_var *trg_new_row_fake_var;
enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE,
XA_SUSPEND, XA_FOR_MIGRATE};
+extern const LEX_STRING null_lex_str;
+extern const LEX_STRING empty_lex_str;
/*
Class representing list of all tables used by statement.
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_parse.cc 2010-03-29 15:13:53 +0000
@@ -444,9 +444,8 @@ static void handle_bootstrap_impl(THD *t
thd_proc_info(thd, 0);
thd->version=refresh_version;
- thd->security_ctx->priv_user=
- thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
- thd->security_ctx->priv_host[0]=0;
+ thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
+ thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0;
/*
Make the "client" handle multiple results. This is necessary
to enable stored procedures with SELECTs and Dynamic SQL
@@ -1093,96 +1092,34 @@ bool dispatch_command(enum enum_server_c
case COM_CHANGE_USER:
{
status_var_increment(thd->status_var.com_other);
- char *user= (char*) packet, *packet_end= packet + packet_length;
- /* Safe because there is always a trailing \0 at the end of the packet */
- char *passwd= strend(user)+1;
thd->change_user();
thd->clear_error(); // if errors from rollback
- /*
- Old clients send null-terminated string ('\0' for empty string) for
- password. New clients send the size (1 byte) + string (not null
- terminated, so also '\0' for empty string).
-
- Cast *passwd to an unsigned char, so that it doesn't extend the sign
- for *passwd > 127 and become 2**32-127 after casting to uint.
- */
- char db_buff[NAME_LEN+1]; // buffer to store db in utf8
- char *db= passwd;
- char *save_db;
- /*
- If there is no password supplied, the packet must contain '\0',
- in any type of handshake (4.1 or pre-4.1).
- */
- if (passwd >= packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
- uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- (uchar)(*passwd++) : strlen(passwd));
- uint dummy_errors, save_db_length, db_length;
- int res;
- Security_context save_security_ctx= *thd->security_ctx;
- USER_CONN *save_user_connect;
-
- db+= passwd_len + 1;
- /*
- Database name is always NUL-terminated, so in case of empty database
- the packet must contain at least the trailing '\0'.
- */
- if (db >= packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
- db_length= strlen(db);
-
- char *ptr= db + db_length + 1;
- uint cs_number= 0;
-
- if (ptr < packet_end)
- {
- if (ptr + 2 > packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
-
- cs_number= uint2korr(ptr);
- }
-
- /* Convert database name to utf8 */
- db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info, db, db_length,
- thd->charset(), &dummy_errors)]= 0;
- db= db_buff;
-
- /* Save user and privileges */
- save_db_length= thd->db_length;
- save_db= thd->db;
- save_user_connect= thd->user_connect;
+ /* acl_authenticate() takes the data from net->read_pos */
+ net->read_pos= (uchar*)packet;
- if (!(thd->security_ctx->user= my_strdup(user, MYF(0))))
- {
- thd->security_ctx->user= save_security_ctx.user;
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- break;
- }
-
- /* Clear variables that are allocated */
- thd->user_connect= 0;
- thd->security_ctx->priv_user= thd->security_ctx->user;
- res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
+ uint save_db_length= thd->db_length;
+ char *save_db= thd->db;
+ USER_CONN *save_user_connect= thd->user_connect;
+ Security_context save_security_ctx= *thd->security_ctx;
+ CHARSET_INFO *save_character_set_client=
+ thd->variables.character_set_client;
+ CHARSET_INFO *save_collation_connection=
+ thd->variables.collation_connection;
+ CHARSET_INFO *save_character_set_results=
+ thd->variables.character_set_results;
- if (res)
+ if (acl_authenticate(thd, 0, packet_length))
{
x_free(thd->security_ctx->user);
*thd->security_ctx= save_security_ctx;
thd->user_connect= save_user_connect;
- thd->db= save_db;
- thd->db_length= save_db_length;
+ thd->reset_db(save_db, save_db_length);
+ thd->variables.character_set_client= save_character_set_client;
+ thd->variables.collation_connection= save_collation_connection;
+ thd->variables.character_set_results= save_character_set_results;
+ thd->update_charset();
}
else
{
@@ -1193,12 +1130,6 @@ bool dispatch_command(enum enum_server_c
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
x_free(save_db);
x_free(save_security_ctx.user);
-
- if (cs_number)
- {
- thd_init_client_charset(thd, cs_number);
- thd->update_charset();
- }
}
break;
}
@@ -4348,8 +4279,8 @@ end_with_restore_list:
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL,
- ER(ER_PROC_AUTO_GRANT_FAIL));
+ ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL));
+ thd->clear_error();
}
/*
@@ -7727,8 +7658,9 @@ void get_default_definer(THD *thd, LEX_U
definer->host.str= (char *) sctx->priv_host;
definer->host.length= strlen(definer->host.str);
- definer->password.str= NULL;
- definer->password.length= 0;
+ definer->password= null_lex_str;
+ definer->plugin= empty_lex_str;
+ definer->auth= empty_lex_str;
}
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_plugin.cc 2010-03-29 15:13:53 +0000
@@ -16,6 +16,7 @@
#include "mysql_priv.h"
#include <my_pthread.h>
#include <my_getopt.h>
+#include <mysql/plugin_auth.h>
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
@@ -46,7 +47,10 @@ const LEX_STRING plugin_type_names[MYSQL
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
{ C_STRING_WITH_LEN("FTPARSER") },
{ C_STRING_WITH_LEN("DAEMON") },
- { C_STRING_WITH_LEN("INFORMATION SCHEMA") }
+ { C_STRING_WITH_LEN("INFORMATION SCHEMA") },
+ { C_STRING_WITH_LEN("AUDIT") },
+ { C_STRING_WITH_LEN("REPLICATION") },
+ { C_STRING_WITH_LEN("AUTHENTICATION") }
};
extern int initialize_schema_table(st_plugin_int *plugin);
@@ -59,12 +63,12 @@ extern int finalize_schema_table(st_plug
*/
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
- 0,ha_initialize_handlerton,0,0,initialize_schema_table
+ 0,ha_initialize_handlerton,0,0,initialize_schema_table, 0, 0, 0
};
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
- 0,ha_finalize_handlerton,0,0,finalize_schema_table
+ 0,ha_finalize_handlerton,0,0,finalize_schema_table, 0, 0, 0
};
#ifdef HAVE_DLOPEN
@@ -85,7 +89,10 @@ static int min_plugin_info_interface_ver
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION,
MYSQL_DAEMON_INTERFACE_VERSION,
- MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+ 0xff00, /* audit plugins are supported in a later versions */
+ 0xff00, /* replication plugins are supported in a later versions */
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION
};
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
@@ -93,7 +100,10 @@ static int cur_plugin_info_interface_ver
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION,
MYSQL_DAEMON_INTERFACE_VERSION,
- MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+ 0x0000, /* audit plugins are supported in a later versions */
+ 0x0000, /* replication plugins are supported in a later versions */
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION
};
/* support for Services */
@@ -1013,6 +1023,9 @@ void plugin_unlock_list(THD *thd, plugin
{
LEX *lex= thd ? thd->lex : 0;
DBUG_ENTER("plugin_unlock_list");
+ if (count == 0)
+ DBUG_VOID_RETURN;
+
DBUG_ASSERT(list);
pthread_mutex_lock(&LOCK_plugin);
while (count--)
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-03-15 11:51:23 +0000
+++ b/sql/sql_yacc.yy 2010-03-29 15:13:53 +0000
@@ -56,6 +56,7 @@
int yylex(void *yylval, void *yythd);
const LEX_STRING null_lex_str= {0,0};
+const LEX_STRING empty_lex_str= { (char*) "", 0 };
#define yyoverflow(A,B,C,D,E,F) \
{ \
@@ -1260,8 +1261,9 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token VARIANCE_SYM
%token VARYING /* SQL-2003-R */
%token VAR_SAMP_SYM
-%token VIRTUAL_SYM
+%token VIA_SYM
%token VIEW_SYM /* SQL-2003-N */
+%token VIRTUAL_SYM
%token WAIT_SYM
%token WARNINGS
%token WEEK_SYM
@@ -11673,6 +11675,9 @@ user:
$$->user = $1;
$$->host.str= (char *) "%";
$$->host.length= 1;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
if (check_string_char_length(&$$->user, ER(ER_USERNAME),
USERNAME_CHAR_LENGTH,
@@ -11685,6 +11690,9 @@ user:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1; $$->host=$3;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
if (check_string_char_length(&$$->user, ER(ER_USERNAME),
USERNAME_CHAR_LENGTH,
@@ -12941,6 +12949,18 @@ grant_user:
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$= $1; $1->password= $5; }
+ | user IDENTIFIED_SYM VIA_SYM ident_or_text
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= empty_lex_str;
+ }
+ | user IDENTIFIED_SYM VIA_SYM ident_or_text USING TEXT_STRING_sys
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= $6;
+ }
| user
{ $$= $1; $1->password= null_lex_str; }
;
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2010-02-01 06:14:12 +0000
+++ b/sql/structs.h 2010-03-29 15:13:53 +0000
@@ -178,7 +178,7 @@ extern const char *show_comp_option_name
typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
typedef struct st_lex_user {
- LEX_STRING user, host, password;
+ LEX_STRING user, host, password, plugin, auth;
} LEX_USER;
/*
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/table.cc 2010-03-29 15:13:53 +0000
@@ -4163,11 +4163,8 @@ bool TABLE_LIST::prepare_view_securety_c
{
DBUG_PRINT("info", ("This table is suid view => load contest"));
DBUG_ASSERT(view && view_sctx);
- if (acl_getroot_no_password(view_sctx,
- definer.user.str,
- definer.host.str,
- definer.host.str,
- thd->db))
+ if (acl_getroot(view_sctx, definer.user.str, definer.host.str,
+ definer.host.str, thd->db))
{
if ((thd->lex->sql_command == SQLCOM_SHOW_CREATE) ||
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS))
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ma_loghandler.c 2010-03-30 12:35:15 +0000
@@ -1275,6 +1275,7 @@ static my_bool translog_set_lsn_for_file
{
LOGHANDLER_FILE_INFO info;
File fd= open_logfile_by_number_no_cache(file);
+ LINT_INIT_STRUCT(info);
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
@@ -1457,8 +1458,8 @@ LSN translog_get_file_max_lsn_stored(uin
{
LOGHANDLER_FILE_INFO info;
- LINT_INIT_STRUCT(info);
File fd= open_logfile_by_number_no_cache(file);
+ LINT_INIT_STRUCT(info);
if ((fd < 0) ||
(translog_read_file_header(&info, fd) | my_close(fd, MYF(MY_WME))))
{
@@ -3966,6 +3967,7 @@ my_bool translog_init_with_table(const c
if (!old_log_was_recovered && old_flags == flags)
{
LOGHANDLER_FILE_INFO info;
+ LINT_INIT_STRUCT(info);
/*
Accessing &log_descriptor.open_files without mutex is safe
because it is initialization
@@ -7934,6 +7936,7 @@ my_bool translog_flush(TRANSLOG_ADDRESS
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
LINT_INIT(sent_to_disk);
+ LINT_INIT(flush_interval);
pthread_mutex_lock(&log_descriptor.log_flush_lock);
DBUG_PRINT("info", ("Everything is flushed up to (%lu,0x%lx)",
@@ -8060,18 +8063,14 @@ retest:
/* keep values for soft sync() and forced sync() actual */
{
uint32 fileno= LSN_FILE_NO(lsn);
- my_atomic_rwlock_wrlock(&soft_sync_rwl);
- my_atomic_store32(&soft_sync_min, fileno);
- my_atomic_store32(&soft_sync_max, fileno);
- my_atomic_rwlock_wrunlock(&soft_sync_rwl);
+ soft_sync_min= fileno;
+ soft_sync_max= fileno;
}
}
else
{
- my_atomic_rwlock_wrlock(&soft_sync_rwl);
- my_atomic_store32(&soft_sync_max, LSN_FILE_NO(lsn));
- my_atomic_store32(&soft_need_sync, 1);
- my_atomic_rwlock_wrunlock(&soft_sync_rwl);
+ soft_sync_max= lsn;
+ soft_need_sync= 1;
}
DBUG_ASSERT(flush_horizon <= log_descriptor.horizon);
@@ -8464,9 +8463,7 @@ my_bool translog_purge(TRANSLOG_ADDRESS
translog_status == TRANSLOG_READONLY);
soft= soft_sync;
- my_atomic_rwlock_wrlock(&soft_sync_rwl);
- min_unsync= my_atomic_load32(&soft_sync_min);
- my_atomic_rwlock_wrunlock(&soft_sync_rwl);
+ min_unsync= soft_sync_min;
DBUG_PRINT("info", ("min_unsync: %lu", (ulong) min_unsync));
if (soft && min_unsync < last_need_file)
{
@@ -8748,9 +8745,7 @@ void translog_sync()
uint32 min;
DBUG_ENTER("ma_translog_sync");
- my_atomic_rwlock_rdlock(&soft_sync_rwl);
- min= my_atomic_load32(&soft_sync_min);
- my_atomic_rwlock_rdunlock(&soft_sync_rwl);
+ min= soft_sync_min;
if (!min)
min= max;
@@ -8796,13 +8791,11 @@ ma_soft_sync_background( void *arg __att
ulonglong prev_loop= my_micro_time();
ulonglong time, sleep;
uint32 min, max, sync_request;
- my_atomic_rwlock_rdlock(&soft_sync_rwl);
- min= my_atomic_load32(&soft_sync_min);
- max= my_atomic_load32(&soft_sync_max);
- sync_request= my_atomic_load32(&soft_need_sync);
- my_atomic_store32(&soft_sync_min, max);
- my_atomic_store32(&soft_need_sync, 0);
- my_atomic_rwlock_rdunlock(&soft_sync_rwl);
+ min= soft_sync_min;
+ max= soft_sync_max;
+ sync_request= soft_need_sync;
+ soft_sync_min= max;
+ soft_need_sync= 0;
sleep= group_commit_wait;
if (sync_request)
@@ -8834,15 +8827,13 @@ int translog_soft_sync_start(void)
DBUG_ENTER("translog_soft_sync_start");
/* check and init variables */
- my_atomic_rwlock_rdlock(&soft_sync_rwl);
- min= my_atomic_load32(&soft_sync_min);
- max= my_atomic_load32(&soft_sync_max);
+ min= soft_sync_min;
+ max= soft_sync_max;
if (!max)
- my_atomic_store32(&soft_sync_max, (max= get_current_logfile()->number));
+ soft_sync_max= max= get_current_logfile()->number;
if (!min)
- my_atomic_store32(&soft_sync_min, max);
- my_atomic_store32(&soft_need_sync, 1);
- my_atomic_rwlock_rdunlock(&soft_sync_rwl);
+ soft_sync_min= max;
+ soft_need_sync= 1;
if (!(res= ma_service_thread_control_init(&soft_sync_control)))
if (!(res= pthread_create(&th, NULL, ma_soft_sync_background, NULL)))
@@ -8985,6 +8976,7 @@ static void dump_header_page(uchar *buff
{
LOGHANDLER_FILE_INFO desc;
char strbuff[21];
+ LINT_INIT_STRUCT(desc);
translog_interpret_file_header(&desc, buff);
printf(" This can be header page:\n"
" Timestamp: %s\n"
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-03 14:44:14 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-03-31 18:37:45 +0000
@@ -1215,8 +1215,6 @@ static int pbxt_init(void *p)
THD *thd = NULL;
#ifndef DRIZZLED
- extern myxt_mutex_t LOCK_plugin;
-
/* {MYSQL QUIRK}
* I have to release this lock for PBXT recovery to
* work, because it needs to open .frm files.
=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c 2010-01-11 13:15:28 +0000
+++ b/tests/mysql_client_test.c 2010-03-29 15:13:53 +0000
@@ -34,6 +34,7 @@
#include <m_string.h>
#include <mysqld_error.h>
#include <my_handler.h>
+#include <sql_common.h>
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2745)
by Igor Babaev 31 Mar '10
by Igor Babaev 31 Mar '10
31 Mar '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100331184541-cigkg2yokjzve1mk
2745 Igor Babaev 2010-03-31 [merge]
Merge the latest changes in 5.2.
Made the results for the key_cache test to be plaform independent.
removed:
include/mysql/plugin.h.pp
added:
include/mysql/client_plugin.h
include/mysql/client_plugin.h.pp
include/mysql/plugin_auth.h
include/mysql/plugin_auth.h.pp
include/mysql/plugin_auth_common.h
plugin/auth/
plugin/auth/Makefile.am
plugin/auth/auth_socket.c
plugin/auth/dialog.c
plugin/auth/plug.in
sql-common/client_plugin.c
modified:
.bzrignore
Makefile.am
client/CMakeLists.txt
client/Makefile.am
client/client_priv.h
client/mysql.cc
client/mysqltest.cc
config/ac-macros/plugins.m4
configure.in
include/Makefile.am
include/errmsg.h
include/m_ctype.h
include/my_global.h
include/my_no_pthread.h
include/my_sys.h
include/mysql.h
include/mysql.h.pp
include/mysql/plugin.h
include/mysql_com.h
include/sql_common.h
libmysql/CMakeLists.txt
libmysql/Makefile.shared
libmysql/client_settings.h
libmysql/errmsg.c
libmysql/libmysql.c
libmysqld/Makefile.am
libmysqld/embedded_priv.h
libmysqld/lib_sql.cc
libmysqld/libmysqld.c
mysql-test/mysql-test-run.pl
mysql-test/r/change_user.result
mysql-test/r/grant.result
mysql-test/r/grant2.result
mysql-test/r/key_cache.result
mysql-test/r/ps.result
mysql-test/r/sp_notembedded.result
mysql-test/r/system_mysql_db.result
mysql-test/suite/funcs_1/r/is_columns_mysql.result
mysql-test/suite/funcs_1/r/is_user_privileges.result
mysql-test/suite/pbxt/r/grant.result
mysql-test/suite/rpl/r/rpl_ignore_table.result
mysql-test/suite/rpl/r/rpl_stm_000001.result
mysql-test/t/change_user.test
mysql-test/t/key_cache.test
mysql-test/valgrind.supp
mysys/Makefile.am
scripts/mysql_system_tables.sql
scripts/mysql_system_tables_data.sql
scripts/mysql_system_tables_fix.sql
server-tools/instance-manager/Makefile.am
server-tools/instance-manager/user_map.cc
sql-common/Makefile.am
sql-common/client.c
sql/CMakeLists.txt
sql/Makefile.am
sql/client_settings.h
sql/ha_ndbcluster.cc
sql/ha_ndbcluster_binlog.cc
sql/lex.h
sql/mysql_priv.h
sql/mysqld.cc
sql/password.c
sql/protocol.cc
sql/protocol.h
sql/sql_acl.cc
sql/sql_acl.h
sql/sql_builtin.cc.in
sql/sql_class.cc
sql/sql_class.h
sql/sql_connect.cc
sql/sql_insert.cc
sql/sql_lex.h
sql/sql_parse.cc
sql/sql_plugin.cc
sql/sql_yacc.yy
sql/structs.h
sql/table.cc
storage/maria/ma_loghandler.c
storage/pbxt/src/ha_pbxt.cc
tests/mysql_client_test.c
=== modified file '.bzrignore'
--- a/.bzrignore 2010-02-01 06:14:12 +0000
+++ b/.bzrignore 2010-03-29 15:13:53 +0000
@@ -1931,3 +1931,6 @@ client/rpl_filter.cc
client/rpl_filter.h
client/sql_list.cc
client/sql_list.h
+libmysqld/client_plugin.c
+sql/client_plugin.c
+*.dgcov
=== modified file 'Makefile.am'
--- a/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/Makefile.am 2010-03-29 15:13:53 +0000
@@ -140,14 +140,14 @@ smoke:
test-full: test test-nr test-ps
test-force:
- $(MAKE) force=--force test
+ $(MAKE) -k force=--force test
test-force-full:
- $(MAKE) force=--force test-full
+ $(MAKE) -k force=--force test-full
#used by autopush.pl to run memory based tests
test-force-mem:
- $(MAKE) force=--force mem=--mem test
+ $(MAKE) -k force=--force mem=--mem test
test-bt:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@@ -261,7 +261,7 @@ test-fast-prepare:
$(MAKE) subset=--ps-protocol test-fast
test-full-qa:
- $(MAKE) force=--force test-pr \
+ $(MAKE) -k force=--force test-pr \
test-binlog-statement test-ext test-fast-view \
test-fast-cursor test-unit
@@ -271,12 +271,13 @@ test-full-qa:
# after which TEST_PREPROCESSOR_HEADER will be used.
#
-API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \
- $(top_srcdir)/include/mysql.h
-
-TEST_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \
- $(top_srcdir)/sql/mysql_priv.h \
- $(top_srcdir)/include/mysql.h
+API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql.h \
+ $(top_srcdir)/include/mysql/client_plugin.h \
+ $(top_srcdir)/include/mysql/plugin_auth.h
+
+TEST_PREPROCESSOR_HEADER = $(API_PREPROCESSOR_HEADER) \
+ $(top_srcdir)/sql/mysql_priv.h
+
#
# Rules for checking that the abi/api has not changed.
=== modified file 'client/CMakeLists.txt'
--- a/client/CMakeLists.txt 2009-09-04 05:54:16 +0000
+++ b/client/CMakeLists.txt 2010-03-29 15:13:53 +0000
@@ -83,3 +83,5 @@ IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("echo" "asInvoker")
ENDIF(EMBED_MANIFESTS)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
+
=== modified file 'client/Makefile.am'
--- a/client/Makefile.am 2009-12-08 21:47:54 +0000
+++ b/client/Makefile.am 2010-03-29 15:13:53 +0000
@@ -100,8 +100,8 @@ mysql_upgrade_SOURCES= mysql_up
# Fix for mit-threads
DEFS = -DMYSQL_CLIENT_NO_THREADS \
- -DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \
- -DMYSQL_DATADIR="\"$(localstatedir)\""
+ -DDEFAULT_MYSQL_HOME='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(localstatedir)"'
sql_src=log_event.h mysql_priv.h rpl_constants.h \
rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
=== modified file 'client/client_priv.h'
--- a/client/client_priv.h 2010-03-15 11:51:23 +0000
+++ b/client/client_priv.h 2010-03-29 15:13:53 +0000
@@ -93,5 +93,7 @@ enum options_client
OPT_FIRST_SLAVE,
OPT_ALL,
OPT_REWRITE_DB,
- OPT_MAX_CLIENT_OPTION
+ OPT_PLUGIN_DIR,
+ OPT_DEFAULT_PLUGIN,
+ OPT_MAX_CLIENT_OPTION /* should be always the last */
};
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2010-03-04 08:03:07 +0000
+++ b/client/mysql.cc 2010-03-29 15:13:53 +0000
@@ -167,6 +167,7 @@ static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char mysql_charsets_dir[FN_REFLEN+1];
+static char *opt_plugin_dir= 0, *opt_default_auth;
static const char *xmlmeta[] = {
"&", "&",
"<", "<",
@@ -1542,6 +1543,13 @@ static struct my_option my_long_options[
{"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
(uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_PLUGIN_DIR,
+ "Default authentication client-side plugin to use.",
+ (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -4238,6 +4246,56 @@ char *get_arg(char *line, my_bool get_ne
}
+/**
+ An example of mysql_authentication_dialog_ask callback.
+
+ The C function with the name "mysql_authentication_dialog_ask", if exists,
+ will be used by the "dialog" client authentication plugin when user
+ input is needed. This function should be of mysql_authentication_dialog_ask_t
+ type. If the function does not exists, a built-in implementation will be
+ used.
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - normal string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+
+extern "C" char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ char *s=buf;
+
+ fputs("[mariadb] ", stdout);
+ fputs(prompt, stdout);
+ fputs(" ", stdout);
+
+ if (type == 2) /* password */
+ {
+ s= get_tty_password("");
+ strnmov(buf, s, buf_len);
+ buf[buf_len-1]= 0;
+ my_free(s, MYF(0));
+ }
+ else
+ {
+ fgets(buf, buf_len-1, stdin);
+ if (buf[0] && (s= strend(buf))[-1] == '\n')
+ s[-1]= 0;
+ }
+
+ return buf;
+}
+
static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
@@ -4283,6 +4341,13 @@ sql_real_connect(char *host,char *databa
}
if (default_charset_used)
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc 2010-01-28 14:49:14 +0000
+++ b/client/mysqltest.cc 2010-02-19 08:08:05 +0000
@@ -36,6 +36,7 @@
#include "client_priv.h"
#include <mysql_version.h>
#include <mysqld_error.h>
+#include <sql_common.h>
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -3610,13 +3611,15 @@ void do_change_user(struct st_command *c
}
if (!ds_user.length)
+ {
dynstr_set(&ds_user, mysql->user);
- if (!ds_passwd.length)
- dynstr_set(&ds_passwd, mysql->passwd);
+ if (!ds_passwd.length)
+ dynstr_set(&ds_passwd, mysql->passwd);
- if (!ds_db.length)
- dynstr_set(&ds_db, mysql->db);
+ if (!ds_db.length)
+ dynstr_set(&ds_db, mysql->db);
+ }
DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
=== modified file 'config/ac-macros/plugins.m4'
--- a/config/ac-macros/plugins.m4 2009-12-22 10:33:20 +0000
+++ b/config/ac-macros/plugins.m4 2010-03-29 15:14:28 +0000
@@ -38,6 +38,7 @@ AC_DEFUN([_MYSQL_PLUGIN],[
_MYSQL_PLUGAPPEND([__mysql_plugin_list__],[$1])
m4_define([MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]), [$3])
m4_define([MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]), [$4])
+ m4_ifdef([_AC_ENABLE_IF], [_AC_ENABLE_IF([with],[plugin-$1])])
_MYSQL_PLUGAPPEND_META([$1], $5)
ifelse(m4_bregexp(__mysql_include__,[/plug\.in$]),-1,[],[
MYSQL_PLUGIN_DIRECTORY([$1],
=== modified file 'configure.in'
--- a/configure.in 2010-03-18 12:08:39 +0000
+++ b/configure.in 2010-03-29 15:13:53 +0000
@@ -1605,9 +1605,8 @@ case "$with_mysqld_ldflags " in
;;
*)
- # Check for dlopen, needed for user definable functions
+ # Check for dlopen, needed for user definable functions and plugins
# This must be checked after threads on AIX
- # We only need this for mysqld, not for the clients.
my_save_LIBS="$LIBS"
LIBS=""
=== modified file 'include/Makefile.am'
--- a/include/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/include/Makefile.am 2010-03-29 15:13:53 +0000
@@ -24,6 +24,8 @@ pkginclude_HEADERS = $(HEADERS_ABI) my_d
my_xml.h mysql_embed.h mysql/services.h \
mysql/service_my_snprintf.h mysql/service_thd_alloc.h \
my_pthread.h my_no_pthread.h \
+ mysql/plugin_auth.h mysql/client_plugin.h \
+ mysql/plugin_auth_common.h \
decimal.h errmsg.h my_global.h my_net.h \
my_getopt.h sslopt-longopts.h my_dir.h \
sslopt-vars.h sslopt-case.h sql_common.h keycache.h \
@@ -42,7 +44,7 @@ noinst_HEADERS = config-win.h config-net
atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \
atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \
wqueue.h waiting_threads.h
-EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp
+EXTRA_DIST = mysql.h.pp mysql/plugin_auth.h.pp mysql/client_plugin.h.pp
# Remove built files and the symlinked directories
CLEANFILES = $(BUILT_SOURCES) readline openssl
=== modified file 'include/errmsg.h'
--- a/include/errmsg.h 2008-05-20 16:36:26 +0000
+++ b/include/errmsg.h 2010-03-29 15:13:53 +0000
@@ -97,6 +97,7 @@ extern const char *client_errors[]; /* E
#define CR_SERVER_LOST_EXTENDED 2055
#define CR_STMT_CLOSED 2056
#define CR_NEW_STMT_METADATA 2057
-#define CR_ERROR_LAST /*Copy last error nr:*/ 2057
+#define CR_AUTH_PLUGIN_CANNOT_LOAD 2058
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2058
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
=== modified file 'include/m_ctype.h'
--- a/include/m_ctype.h 2010-01-06 19:20:16 +0000
+++ b/include/m_ctype.h 2010-03-31 18:37:45 +0000
@@ -291,7 +291,7 @@ struct charset_info_st
const uint16 *const *sort_order_big;
const uint16 *tab_to_uni;
MY_UNI_IDX *tab_from_uni;
- const MY_UNICASE_INFO *const *caseinfo;
+ MY_UNICASE_INFO *const *caseinfo;
const uchar *state_map;
const uchar *ident_map;
uint strxfrm_multiply;
=== modified file 'include/my_global.h'
--- a/include/my_global.h 2010-03-10 10:32:14 +0000
+++ b/include/my_global.h 2010-03-29 15:13:53 +0000
@@ -578,6 +578,14 @@ int __void__;
#define IF_VALGRIND(A,B) (B)
#endif
+#ifdef _WIN32
+#define SO_EXT ".dll"
+#elif defined(__APPLE__)
+#define SO_EXT ".dylib"
+#else
+#define SO_EXT ".so"
+#endif
+
/*
Suppress uninitialized variable warning without generating code.
@@ -1522,10 +1530,12 @@ do { doubleget_union _tmp; \
#endif
#ifndef HAVE_DLERROR
-#define dlerror() ""
+#define dlerror() "No support for dynamic loading (static build?)"
+#define dlopen(A,B) 0
+#define dlsym(A,B) 0
+#define dlclose(A) 0
#endif
-
#ifndef __NETWARE__
/*
* Include standard definitions of operator new and delete.
=== modified file 'include/my_no_pthread.h'
--- a/include/my_no_pthread.h 2009-12-12 18:11:25 +0000
+++ b/include/my_no_pthread.h 2010-03-29 15:13:53 +0000
@@ -46,6 +46,7 @@
#define rw_wrlock(A)
#define rw_unlock(A)
#define rwlock_destroy(A)
+#define safe_mutex_assert_owner(mp)
typedef int my_pthread_once_t;
#define MY_PTHREAD_ONCE_INIT 0
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2010-03-15 11:51:23 +0000
+++ b/include/my_sys.h 2010-03-29 15:13:53 +0000
@@ -210,7 +210,7 @@ extern void my_large_free(uchar * ptr, m
#define my_alloca(SZ) alloca((size_t) (SZ))
#define my_afree(PTR) {}
#else
-#define my_alloca(SZ) my_malloc(SZ,MYF(0))
+#define my_alloca(SZ) my_malloc(SZ,MYF(MY_FAE))
#define my_afree(PTR) my_free(PTR,MYF(MY_WME))
#endif /* HAVE_ALLOCA */
@@ -870,6 +870,10 @@ extern void set_prealloc_root(MEM_ROOT *
extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
size_t prealloc_size);
extern char *strdup_root(MEM_ROOT *root,const char *str);
+static inline char *safe_strdup_root(MEM_ROOT *root, const char *str)
+{
+ return str ? strdup_root(root, str) : 0;
+}
extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len);
extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len);
extern int get_defaults_options(int argc, char **argv,
=== modified file 'include/mysql.h'
--- a/include/mysql.h 2010-02-01 06:14:12 +0000
+++ b/include/mysql.h 2010-03-29 15:13:53 +0000
@@ -167,9 +167,15 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
};
+/**
+ @todo remove the "extension", move st_mysql_options completely
+ out of mysql.h
+*/
+struct st_mysql_options_extention;
+
struct st_mysql_options {
unsigned int connect_timeout, read_timeout, write_timeout;
unsigned int port, protocol;
@@ -217,7 +223,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
- void *extension;
+ struct st_mysql_options_extention *extension;
};
enum mysql_status
@@ -752,38 +758,6 @@ enum enum_stmt_attr_type
};
-typedef struct st_mysql_methods
-{
- my_bool (*read_query_result)(MYSQL *mysql);
- my_bool (*advanced_command)(MYSQL *mysql,
- enum enum_server_command command,
- const unsigned char *header,
- unsigned long header_length,
- const unsigned char *arg,
- unsigned long arg_length,
- my_bool skip_check,
- MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields);
- MYSQL_RES * (*use_result)(MYSQL *mysql);
- void (*fetch_lengths)(unsigned long *to,
- MYSQL_ROW column, unsigned int field_count);
- void (*flush_use_result)(MYSQL *mysql);
-#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
- MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
- my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
- int (*stmt_execute)(MYSQL_STMT *stmt);
- int (*read_binary_rows)(MYSQL_STMT *stmt);
- int (*unbuffered_fetch)(MYSQL *mysql, char **row);
- void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistics)(MYSQL *mysql);
- my_bool (*next_result)(MYSQL *mysql);
- int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
- int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
-#endif
-} MYSQL_METHODS;
-
-
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
@@ -846,18 +820,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql,
#endif
#define HAVE_MYSQL_REAL_CONNECT
-/*
- The following functions are mainly exported because of mysqlbinlog;
- They are not for general usage
-*/
-
-#define simple_command(mysql, command, arg, length, skip_check) \
- (*(mysql)->methods->advanced_command)(mysql, command, 0, \
- 0, arg, length, skip_check, NULL)
-#define stmt_command(mysql, command, arg, length, stmt) \
- (*(mysql)->methods->advanced_command)(mysql, command, 0, \
- 0, arg, length, 1, stmt)
-
#ifdef __NETWARE__
#pragma pack(pop) /* restore alignment */
#endif
=== modified file 'include/mysql.h.pp'
--- a/include/mysql.h.pp 2010-03-15 11:51:23 +0000
+++ b/include/mysql.h.pp 2010-03-29 15:13:53 +0000
@@ -128,13 +128,13 @@ void create_random_string(char *to, unsi
void hash_password(unsigned long *to, const char *password, unsigned int password_len);
void make_scrambled_password_323(char *to, const char *password);
void scramble_323(char *to, const char *message, const char *password);
-my_bool check_scramble_323(const char *, const char *message,
+my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
-my_bool check_scramble(const char *reply, const char *message,
+my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
@@ -258,8 +258,9 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
};
+struct st_mysql_options_extention;
struct st_mysql_options {
unsigned int connect_timeout, read_timeout, write_timeout;
unsigned int port, protocol;
@@ -289,7 +290,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
- void *extension;
+ struct st_mysql_options_extention *extension;
};
enum mysql_status
{
@@ -601,34 +602,6 @@ enum enum_stmt_attr_type
STMT_ATTR_CURSOR_TYPE,
STMT_ATTR_PREFETCH_ROWS
};
-typedef struct st_mysql_methods
-{
- my_bool (*read_query_result)(MYSQL *mysql);
- my_bool (*advanced_command)(MYSQL *mysql,
- enum enum_server_command command,
- const unsigned char *header,
- unsigned long header_length,
- const unsigned char *arg,
- unsigned long arg_length,
- my_bool skip_check,
- MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields);
- MYSQL_RES * (*use_result)(MYSQL *mysql);
- void (*fetch_lengths)(unsigned long *to,
- MYSQL_ROW column, unsigned int field_count);
- void (*flush_use_result)(MYSQL *mysql);
- MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
- my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
- int (*stmt_execute)(MYSQL_STMT *stmt);
- int (*read_binary_rows)(MYSQL_STMT *stmt);
- int (*unbuffered_fetch)(MYSQL *mysql, char **row);
- void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistics)(MYSQL *mysql);
- my_bool (*next_result)(MYSQL *mysql);
- int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
- int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
-} MYSQL_METHODS;
MYSQL_STMT * mysql_stmt_init(MYSQL *mysql);
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
=== added file 'include/mysql/client_plugin.h'
--- a/include/mysql/client_plugin.h 1970-01-01 00:00:00 +0000
+++ b/include/mysql/client_plugin.h 2010-03-29 15:13:53 +0000
@@ -0,0 +1,164 @@
+#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ MySQL Client Plugin API
+
+ This file defines the API for plugins that work on the client side
+*/
+#define MYSQL_CLIENT_PLUGIN_INCLUDED
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* known plugin types */
+#define MYSQL_CLIENT_reserved1 0
+#define MYSQL_CLIENT_reserved2 1
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
+
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
+
+#define MYSQL_CLIENT_MAX_PLUGINS 3
+
+#define mysql_declare_client_plugin(X) \
+ struct st_mysql_client_plugin_ ## X \
+ _mysql_client_plugin_declaration_ = { \
+ MYSQL_CLIENT_ ## X ## _PLUGIN, \
+ MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION,
+#define mysql_end_client_plugin }
+
+/* generic plugin header structure */
+#define MYSQL_CLIENT_PLUGIN_HEADER \
+ int type; \
+ unsigned int interface_version; \
+ const char *name; \
+ const char *author; \
+ const char *desc; \
+ unsigned int version[3]; \
+ int (*init)(char *, size_t, int, va_list); \
+ int (*deinit)();
+
+struct st_mysql_client_plugin
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+};
+
+struct st_mysql;
+
+/******** authentication plugin specific declarations *********/
+#include <mysql/plugin_auth_common.h>
+
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+
+/**
+ type of the mysql_authentication_dialog_ask function
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - ordinary string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+/******** using plugins ************/
+
+/**
+ loads a plugin and initializes it
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param ... arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+
+/**
+ loads a plugin and initializes it, taking va_list as an argument
+
+ This is the same as mysql_load_plugin, but take va_list instead of
+ a list of arguments.
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param args arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+
+/**
+ finds an already loaded plugin by name, or loads it, if necessary
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+
+/**
+ adds a plugin structure to the list of loaded plugins
+
+ This is useful if an application has the necessary functionality
+ (for example, a special load data handler) statically linked into
+ the application binary. It can use this function to register the plugin
+ directly, avoiding the need to factor it out into a shared object.
+
+ @param mysql MYSQL structure. It is only used for error reporting
+ @param plugin an st_mysql_client_plugin structure to register
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
+
+#endif
+
=== added file 'include/mysql/client_plugin.h.pp'
--- a/include/mysql/client_plugin.h.pp 1970-01-01 00:00:00 +0000
+++ b/include/mysql/client_plugin.h.pp 2010-03-29 15:13:53 +0000
@@ -0,0 +1,41 @@
+#include <stdarg.h>
+#include <stdlib.h>
+struct st_mysql_client_plugin
+{
+ int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; int (*init)(char *, size_t, int, va_list); int (*deinit)();
+};
+struct st_mysql;
+#include <mysql/plugin_auth_common.h>
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket;
+} MYSQL_PLUGIN_VIO_INFO;
+typedef struct st_plugin_vio
+{
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+} MYSQL_PLUGIN_VIO;
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; int (*init)(char *, size_t, int, va_list); int (*deinit)();
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h 2010-03-03 14:44:14 +0000
+++ b/include/mysql/plugin.h 2010-03-29 15:13:53 +0000
@@ -67,7 +67,10 @@ typedef struct st_mysql_xid MYSQL_XID;
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */
#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */
-#define MYSQL_MAX_PLUGIN_TYPE_NUM 5 /* The number of plugin types */
+#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */
+#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */
+#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */
+#define MYSQL_MAX_PLUGIN_TYPE_NUM 8 /* The number of plugin types */
/* We use the following strings to define licenses for plugins */
#define PLUGIN_LICENSE_PROPRIETARY 0
=== removed file 'include/mysql/plugin.h.pp'
--- a/include/mysql/plugin.h.pp 2010-03-03 14:44:14 +0000
+++ b/include/mysql/plugin.h.pp 1970-01-01 00:00:00 +0000
@@ -1,163 +0,0 @@
-#include <mysql/services.h>
-#include <mysql/service_my_snprintf.h>
-#include <stdarg.h>
-#include <stdlib.h>
-extern struct my_snprintf_service_st {
- size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
- size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
-} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
-size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
-#include <mysql/service_thd_alloc.h>
-#include <stdlib.h>
-struct st_mysql_lex_string
-{
- char *str;
- size_t length;
-};
-typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
-extern struct thd_alloc_service_st {
- void *(*thd_alloc_func)(void*, unsigned int);
- void *(*thd_calloc_func)(void*, unsigned int);
- char *(*thd_strdup_func)(void*, const char *);
- char *(*thd_strmake_func)(void*, const char *, unsigned int);
- void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
- const char *, unsigned int, int);
-} *thd_alloc_service;
-void *thd_alloc(void* thd, unsigned int size);
-void *thd_calloc(void* thd, unsigned int size);
-char *thd_strdup(void* thd, const char *str);
-char *thd_strmake(void* thd, const char *str, unsigned int size);
-void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
-struct st_mysql_xid {
- long formatID;
- long gtrid_length;
- long bqual_length;
- char data[128];
-};
-typedef struct st_mysql_xid MYSQL_XID;
-enum enum_mysql_show_type
-{
- SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
- SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
- SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
- SHOW_always_last
-};
-struct st_mysql_show_var {
- const char *name;
- char *value;
- enum enum_mysql_show_type type;
-};
-typedef int (*mysql_show_var_func)(void*, struct st_mysql_show_var*, char *);
-struct st_mysql_sys_var;
-struct st_mysql_value;
-typedef int (*mysql_var_check_func)(void* thd,
- struct st_mysql_sys_var *var,
- void *save, struct st_mysql_value *value);
-typedef void (*mysql_var_update_func)(void* thd,
- struct st_mysql_sys_var *var,
- void *var_ptr, const void *save);
-struct st_mysql_plugin
-{
- int type;
- void *info;
- const char *name;
- const char *author;
- const char *descr;
- int license;
- int (*init)(void *);
- int (*deinit)(void *);
- unsigned int version;
- struct st_mysql_show_var *status_vars;
- struct st_mysql_sys_var **system_vars;
- void * __reserved1;
-};
-enum enum_ftparser_mode
-{
- MYSQL_FTPARSER_SIMPLE_MODE= 0,
- MYSQL_FTPARSER_WITH_STOPWORDS= 1,
- MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
-};
-enum enum_ft_token_type
-{
- FT_TOKEN_EOF= 0,
- FT_TOKEN_WORD= 1,
- FT_TOKEN_LEFT_PAREN= 2,
- FT_TOKEN_RIGHT_PAREN= 3,
- FT_TOKEN_STOPWORD= 4
-};
-typedef struct st_mysql_ftparser_boolean_info
-{
- enum enum_ft_token_type type;
- int yesno;
- int weight_adjust;
- char wasign;
- char trunc;
- char prev;
- char *quot;
-} MYSQL_FTPARSER_BOOLEAN_INFO;
-typedef int mysql_ft_size_t;
-typedef struct st_mysql_ftparser_param
-{
- int (*mysql_parse)(struct st_mysql_ftparser_param *,
- const unsigned char *doc, mysql_ft_size_t doc_len);
- int (*mysql_add_word)(struct st_mysql_ftparser_param *,
- const unsigned char *word, mysql_ft_size_t word_len,
- MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
- void *ftparser_state;
- void *mysql_ftparam;
- const struct charset_info_st *cs;
- const unsigned char *doc;
- mysql_ft_size_t length;
- unsigned int flags;
- enum enum_ftparser_mode mode;
-} MYSQL_FTPARSER_PARAM;
-struct st_mysql_ftparser
-{
- int interface_version;
- int (*parse)(MYSQL_FTPARSER_PARAM *param);
- int (*init)(MYSQL_FTPARSER_PARAM *param);
- int (*deinit)(MYSQL_FTPARSER_PARAM *param);
-};
-struct st_mysql_storage_engine
-{
- int interface_version;
-};
-struct handlerton;
-struct st_mysql_daemon
-{
- int interface_version;
-};
-struct st_mysql_information_schema
-{
- int interface_version;
-};
-struct st_mysql_value
-{
- int (*value_type)(struct st_mysql_value *);
- const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length);
- int (*val_real)(struct st_mysql_value *, double *realbuf);
- int (*val_int)(struct st_mysql_value *, long long *intbuf);
-};
-int thd_in_lock_tables(const void* thd);
-int thd_tablespace_op(const void* thd);
-long long thd_test_options(const void* thd, long long test_options);
-int thd_sql_command(const void* thd);
-void **thd_ha_data(const void* thd, const struct handlerton *hton);
-int thd_tx_isolation(const void* thd);
-char *thd_security_context(void* thd, char *buffer, unsigned int length,
- unsigned int max_query_len);
-void thd_inc_row_count(void* thd);
-const char *set_thd_proc_info(void*, const char * info, const char *func,
- const char *file, const unsigned int line);
-int mysql_tmpfile(const char *prefix);
-int thd_killed(const void* thd);
-unsigned long thd_get_thread_id(const void* thd);
-void thd_get_xid(const void* thd, MYSQL_XID *xid);
-void mysql_query_cache_invalidate4(void* thd,
- const char *key, unsigned int key_length,
- int using_trx);
=== added file 'include/mysql/plugin_auth.h'
--- a/include/mysql/plugin_auth.h 1970-01-01 00:00:00 +0000
+++ b/include/mysql/plugin_auth.h 2010-03-29 15:13:53 +0000
@@ -0,0 +1,83 @@
+#ifndef MYSQL_PLUGIN_AUTH_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Authentication Plugin API.
+
+ This file defines the API for server authentication plugins.
+*/
+
+#define MYSQL_PLUGIN_AUTH_INCLUDED
+
+#include <mysql/plugin.h>
+
+#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0100
+
+#include <mysql/plugin_auth_common.h>
+
+/**
+ Provides server plugin access to authentication information
+*/
+typedef struct st_mysql_server_auth_info
+{
+ /**
+ User name as sent by the client and shown in USER().
+ NULL if the client packet with the user name was not received yet.
+ */
+ const char *user_name;
+ /**
+ A corresponding column value from the mysql.user table for the
+ matching account name
+ */
+ const char *auth_string;
+
+ /**
+ Matching account name as found in the mysql.user table.
+ A plugin can override it with another name that will be
+ used by MySQL for authorization, and shown in CURRENT_USER()
+ */
+ char authenticated_as[MYSQL_USERNAME_LENGTH+1];
+ /**
+ This only affects the "Authentication failed. Password used: %s"
+ error message. If set, %s will be YES, otherwise - NO.
+ Set it as appropriate or ignore at will.
+ */
+ int password_used;
+} MYSQL_SERVER_AUTH_INFO;
+
+/**
+ Server authentication plugin descriptor
+*/
+struct st_mysql_auth
+{
+ int interface_version; /**< version plugin uses */
+ /**
+ A plugin that a client must use for authentication with this server
+ plugin. Can be NULL to mean "any plugin".
+ */
+ const char *client_auth_plugin;
+ /**
+ Function provided by the plugin which should perform authentication (using
+ the vio functions if necessary) and return 0 if successful. The plugin can
+ also fill the info.authenticated_as field if a different username should be
+ used for authorization.
+ */
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
+};
+#endif
+
=== added file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp 1970-01-01 00:00:00 +0000
+++ b/include/mysql/plugin_auth.h.pp 2010-03-29 15:13:53 +0000
@@ -0,0 +1,193 @@
+#include <mysql/plugin.h>
+#include <mysql/services.h>
+#include <mysql/service_my_snprintf.h>
+#include <stdarg.h>
+#include <stdlib.h>
+extern struct my_snprintf_service_st {
+ size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
+ size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
+} *my_snprintf_service;
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
+#include <mysql/service_thd_alloc.h>
+#include <stdlib.h>
+struct st_mysql_lex_string
+{
+ char *str;
+ size_t length;
+};
+typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+extern struct thd_alloc_service_st {
+ void *(*thd_alloc_func)(void*, unsigned int);
+ void *(*thd_calloc_func)(void*, unsigned int);
+ char *(*thd_strdup_func)(void*, const char *);
+ char *(*thd_strmake_func)(void*, const char *, unsigned int);
+ void *(*thd_memdup_func)(void*, const void*, unsigned int);
+ MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ const char *, unsigned int, int);
+} *thd_alloc_service;
+void *thd_alloc(void* thd, unsigned int size);
+void *thd_calloc(void* thd, unsigned int size);
+char *thd_strdup(void* thd, const char *str);
+char *thd_strmake(void* thd, const char *str, unsigned int size);
+void *thd_memdup(void* thd, const void* str, unsigned int size);
+MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
+struct st_mysql_xid {
+ long formatID;
+ long gtrid_length;
+ long bqual_length;
+ char data[128];
+};
+typedef struct st_mysql_xid MYSQL_XID;
+enum enum_mysql_show_type
+{
+ SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
+ SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
+ SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
+ SHOW_always_last
+};
+struct st_mysql_show_var {
+ const char *name;
+ char *value;
+ enum enum_mysql_show_type type;
+};
+typedef int (*mysql_show_var_func)(void*, struct st_mysql_show_var*, char *);
+struct st_mysql_sys_var;
+struct st_mysql_value;
+typedef int (*mysql_var_check_func)(void* thd,
+ struct st_mysql_sys_var *var,
+ void *save, struct st_mysql_value *value);
+typedef void (*mysql_var_update_func)(void* thd,
+ struct st_mysql_sys_var *var,
+ void *var_ptr, const void *save);
+struct st_mysql_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ void * __reserved1;
+};
+enum enum_ftparser_mode
+{
+ MYSQL_FTPARSER_SIMPLE_MODE= 0,
+ MYSQL_FTPARSER_WITH_STOPWORDS= 1,
+ MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
+};
+enum enum_ft_token_type
+{
+ FT_TOKEN_EOF= 0,
+ FT_TOKEN_WORD= 1,
+ FT_TOKEN_LEFT_PAREN= 2,
+ FT_TOKEN_RIGHT_PAREN= 3,
+ FT_TOKEN_STOPWORD= 4
+};
+typedef struct st_mysql_ftparser_boolean_info
+{
+ enum enum_ft_token_type type;
+ int yesno;
+ int weight_adjust;
+ char wasign;
+ char trunc;
+ char prev;
+ char *quot;
+} MYSQL_FTPARSER_BOOLEAN_INFO;
+typedef int mysql_ft_size_t;
+typedef struct st_mysql_ftparser_param
+{
+ int (*mysql_parse)(struct st_mysql_ftparser_param *,
+ const unsigned char *doc, mysql_ft_size_t doc_len);
+ int (*mysql_add_word)(struct st_mysql_ftparser_param *,
+ const unsigned char *word, mysql_ft_size_t word_len,
+ MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
+ void *ftparser_state;
+ void *mysql_ftparam;
+ const struct charset_info_st *cs;
+ const unsigned char *doc;
+ mysql_ft_size_t length;
+ unsigned int flags;
+ enum enum_ftparser_mode mode;
+} MYSQL_FTPARSER_PARAM;
+struct st_mysql_ftparser
+{
+ int interface_version;
+ int (*parse)(MYSQL_FTPARSER_PARAM *param);
+ int (*init)(MYSQL_FTPARSER_PARAM *param);
+ int (*deinit)(MYSQL_FTPARSER_PARAM *param);
+};
+struct st_mysql_storage_engine
+{
+ int interface_version;
+};
+struct handlerton;
+struct st_mysql_daemon
+{
+ int interface_version;
+};
+struct st_mysql_information_schema
+{
+ int interface_version;
+};
+struct st_mysql_value
+{
+ int (*value_type)(struct st_mysql_value *);
+ const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length);
+ int (*val_real)(struct st_mysql_value *, double *realbuf);
+ int (*val_int)(struct st_mysql_value *, long long *intbuf);
+};
+int thd_in_lock_tables(const void* thd);
+int thd_tablespace_op(const void* thd);
+long long thd_test_options(const void* thd, long long test_options);
+int thd_sql_command(const void* thd);
+void **thd_ha_data(const void* thd, const struct handlerton *hton);
+int thd_tx_isolation(const void* thd);
+char *thd_security_context(void* thd, char *buffer, unsigned int length,
+ unsigned int max_query_len);
+void thd_inc_row_count(void* thd);
+const char *set_thd_proc_info(void*, const char * info, const char *func,
+ const char *file, const unsigned int line);
+int mysql_tmpfile(const char *prefix);
+int thd_killed(const void* thd);
+unsigned long thd_get_thread_id(const void* thd);
+void thd_get_xid(const void* thd, MYSQL_XID *xid);
+void mysql_query_cache_invalidate4(void* thd,
+ const char *key, unsigned int key_length,
+ int using_trx);
+#include <mysql/plugin_auth_common.h>
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket;
+} MYSQL_PLUGIN_VIO_INFO;
+typedef struct st_plugin_vio
+{
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+} MYSQL_PLUGIN_VIO;
+typedef struct st_mysql_server_auth_info
+{
+ const char *user_name;
+ const char *auth_string;
+ char authenticated_as[48 +1];
+ int password_used;
+} MYSQL_SERVER_AUTH_INFO;
+struct st_mysql_auth
+{
+ int interface_version;
+ const char *client_auth_plugin;
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
+};
=== added file 'include/mysql/plugin_auth_common.h'
--- a/include/mysql/plugin_auth_common.h 1970-01-01 00:00:00 +0000
+++ b/include/mysql/plugin_auth_common.h 2010-03-29 15:13:53 +0000
@@ -0,0 +1,105 @@
+#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ This file defines constants and data structures that are the same for
+ both client- and server-side authentication plugins.
+*/
+#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+
+/** the max allowed length for a user name */
+#define MYSQL_USERNAME_LENGTH 48
+
+/**
+ return values of the plugin authenticate_user() method.
+*/
+
+/**
+ Authentication failed. Additionally, all other CR_xxx values
+ (libmysql error code) can be used too.
+
+ The client plugin may set the error code and the error message directly
+ in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error
+ code was returned, an error message in the MYSQL structure will be
+ overwritten. If CR_ERROR is returned without setting the error in MYSQL,
+ CR_UNKNOWN_ERROR will be user.
+*/
+#define CR_ERROR 0
+/**
+ Authentication (client part) was successful. It does not mean that the
+ authentication as a whole was successful, usually it only means
+ that the client was able to send the user name and the password to the
+ server. If CR_OK is returned, the libmysql reads the next packet expecting
+ it to be one of OK, ERROR, or CHANGE_PLUGIN packets.
+*/
+#define CR_OK -1
+/**
+ Authentication was successful.
+ It means that the client has done its part successfully and also that
+ a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN).
+ In this case, libmysql will not read a packet from the server,
+ but it will use the data at mysql->net.read_pos.
+
+ A plugin may return this value if the number of roundtrips in the
+ authentication protocol is not known in advance, and the client plugin
+ needs to read one packet more to determine if the authentication is finished
+ or not.
+*/
+#define CR_OK_HANDSHAKE_COMPLETE -2
+
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket; /**< it's set, if the protocol is SOCKET or TCP */
+#ifdef _WIN32
+ HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
+#endif
+} MYSQL_PLUGIN_VIO_INFO;
+
+/**
+ Provides plugin access to communication channel
+*/
+typedef struct st_plugin_vio
+{
+ /**
+ Plugin provides a pointer reference and this function sets it to the
+ contents of any incoming packet. Returns the packet length, or -1 if
+ the plugin should terminate.
+ */
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+
+ /**
+ Plugin provides a buffer with data and the length and this
+ function sends it as a packet. Returns 0 on success, 1 on failure.
+ */
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+
+ /**
+ Fills in a st_plugin_vio_info structure, providing the information
+ about the connection.
+ */
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+
+} MYSQL_PLUGIN_VIO;
+
+#endif
+
=== modified file 'include/mysql_com.h'
--- a/include/mysql_com.h 2010-03-15 11:51:23 +0000
+++ b/include/mysql_com.h 2010-03-29 15:13:53 +0000
@@ -152,9 +152,17 @@ enum enum_server_command
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
+#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */
+
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
+#ifdef HAVE_COMPRESS
+#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS
+#else
+#define CAN_CLIENT_COMPRESS 0
+#endif
+
/* Gather all possible capabilites (flags) supported by the server */
#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \
CLIENT_FOUND_ROWS | \
@@ -175,7 +183,8 @@ enum enum_server_command
CLIENT_MULTI_STATEMENTS | \
CLIENT_MULTI_RESULTS | \
CLIENT_SSL_VERIFY_SERVER_CERT | \
- CLIENT_REMEMBER_OPTIONS)
+ CLIENT_REMEMBER_OPTIONS | \
+ CLIENT_PLUGIN_AUTH)
/*
Switch off the flags that are optional and depending on build flags
@@ -488,14 +497,14 @@ void create_random_string(char *to, unsi
void hash_password(unsigned long *to, const char *password, unsigned int password_len);
void make_scrambled_password_323(char *to, const char *password);
void scramble_323(char *to, const char *message, const char *password);
-my_bool check_scramble_323(const char *, const char *message,
+my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
-my_bool check_scramble(const char *reply, const char *message,
+my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
=== modified file 'include/sql_common.h'
--- a/include/sql_common.h 2008-02-27 09:00:59 +0000
+++ b/include/sql_common.h 2010-03-29 15:13:53 +0000
@@ -1,3 +1,4 @@
+#ifndef SQL_COMMON_INCLUDED
/* Copyright (C) 2003-2004, 2006 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -13,14 +14,60 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#define SQL_COMMON_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mysql.h>
extern const char *unknown_sqlstate;
extern const char *cant_connect_sqlstate;
extern const char *not_error_sqlstate;
-#ifdef __cplusplus
-extern "C" {
+struct st_mysql_options_extention {
+ char *plugin_dir;
+ char *default_auth;
+};
+
+typedef struct st_mysql_methods
+{
+ my_bool (*read_query_result)(MYSQL *mysql);
+ my_bool (*advanced_command)(MYSQL *mysql,
+ enum enum_server_command command,
+ const unsigned char *header,
+ unsigned long header_length,
+ const unsigned char *arg,
+ unsigned long arg_length,
+ my_bool skip_check,
+ MYSQL_STMT *stmt);
+ MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ unsigned int fields);
+ MYSQL_RES * (*use_result)(MYSQL *mysql);
+ void (*fetch_lengths)(unsigned long *to,
+ MYSQL_ROW column, unsigned int field_count);
+ void (*flush_use_result)(MYSQL *mysql);
+ int (*read_change_user_result)(MYSQL *mysql);
+#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+ MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
+ my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
+ int (*stmt_execute)(MYSQL_STMT *stmt);
+ int (*read_binary_rows)(MYSQL_STMT *stmt);
+ int (*unbuffered_fetch)(MYSQL *mysql, char **row);
+ void (*free_embedded_thd)(MYSQL *mysql);
+ const char *(*read_statistics)(MYSQL *mysql);
+ my_bool (*next_result)(MYSQL *mysql);
+ int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif
+} MYSQL_METHODS;
+
+#define simple_command(mysql, command, arg, length, skip_check) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, skip_check, NULL)
+#define stmt_command(mysql, command, arg, length, stmt) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, 1, stmt)
extern CHARSET_INFO *default_client_charset_info;
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
@@ -42,9 +89,23 @@ void set_stmt_errmsg(MYSQL_STMT *stmt, N
void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate,
const char *err);
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);
+void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate,
+ const char *format, ...);
+
+/* client side of the pluggable authentication */
+struct st_plugin_vio_info;
+void mpvio_info(Vio *vio, struct st_plugin_vio_info *info);
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ char *data_plugin, const char *db);
+int mysql_client_plugin_init();
+void mysql_client_plugin_deinit();
+struct st_mysql_client_plugin;
+extern struct st_mysql_client_plugin *mysql_client_builtins[];
+
#ifdef __cplusplus
}
#endif
#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)
+#endif
=== modified file 'libmysql/CMakeLists.txt'
--- a/libmysql/CMakeLists.txt 2009-09-15 10:46:35 +0000
+++ b/libmysql/CMakeLists.txt 2010-03-29 15:13:53 +0000
@@ -98,7 +98,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ..
../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c
../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c
../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c
- ../mysys/my_getsystime.c ../mysys/my_sync.c ${LIB_SOURCES})
+ ../mysys/my_getsystime.c ../mysys/my_sync.c ../sql-common/client_plugin.c ${LIB_SOURCES})
# Need to set USE_TLS for building the DLL, since __declspec(thread)
# approach to thread local storage does not work properly in DLLs.
@@ -125,6 +125,7 @@ IF(WIN32)
ENDIF(WIN32)
ADD_DEPENDENCIES(libmysql GenError)
TARGET_LINK_LIBRARIES(libmysql wsock32)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")
=== modified file 'libmysql/Makefile.shared'
--- a/libmysql/Makefile.shared 2009-09-15 10:46:35 +0000
+++ b/libmysql/Makefile.shared 2010-03-29 15:13:53 +0000
@@ -23,6 +23,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
+pkgplugindir = $(pkglibdir)/plugin
## We'll use CLIENT_EXTRA_LDFLAGS for threaded and non-threaded
## until someone complains that they need separate options.
LDADD = @CLIENT_EXTRA_LDFLAGS@ $(target)
@@ -71,26 +72,27 @@ mysysobjects1 = my_init.lo my_static.lo
my_getopt.lo my_gethostbyname.lo my_port.lo \
my_rename.lo my_chsize.lo my_sync.lo my_getsystime.lo
sqlobjects = net.lo
-sql_cmn_objects = pack.lo client.lo my_time.lo
+sql_cmn_objects = pack.lo client.lo my_time.lo client_plugin.lo
# Not needed in the minimum library
mysysobjects2 = my_lib.lo mf_qsort.lo
mysysobjects = $(mysysobjects1) $(mysysobjects2)
target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \
$(sql_cmn_objects) $(vio_objects) $(sqlobjects)
-target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@
+target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ @LIBDL@
vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo
BUILT_SOURCES = link_sources
CLEANFILES = $(target_libadd) $(SHLIBOBJS) \
$(target) $(BUILT_SOURCES)
-DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
+DEFS = -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
-DDEFAULT_HOME_ENV=MYSQL_HOME \
+ -DPLUGINDIR='"$(pkgplugindir)"' \
-DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
+ -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' $(target_defs)
if HAVE_YASSL
yassl_las = $(top_builddir)/extra/yassl/src/libyassl.la \
=== modified file 'libmysql/client_settings.h'
--- a/libmysql/client_settings.h 2007-09-29 19:31:08 +0000
+++ b/libmysql/client_settings.h 2010-03-29 15:13:53 +0000
@@ -18,7 +18,8 @@ extern char * mysql_unix_port;
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
+ CLIENT_PLUGIN_AUTH)
sig_handler my_pipe_sig_handler(int sig);
void read_user_name(char *name);
@@ -57,7 +58,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt);
int cli_read_binary_rows(MYSQL_STMT *stmt);
int cli_unbuffered_fetch(MYSQL *mysql, char **row);
const char * cli_read_statistics(MYSQL *mysql);
-int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd);
+int cli_read_change_user_result(MYSQL *mysql);
#ifdef EMBEDDED_LIBRARY
int init_embedded_server(int argc, char **argv, char **groups);
=== modified file 'libmysql/errmsg.c'
--- a/libmysql/errmsg.c 2008-05-20 16:36:26 +0000
+++ b/libmysql/errmsg.c 2010-03-29 15:13:53 +0000
@@ -85,6 +85,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
@@ -151,6 +152,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
@@ -215,6 +217,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
#endif
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2010-03-04 08:03:07 +0000
+++ b/libmysql/libmysql.c 2010-03-29 15:13:53 +0000
@@ -126,12 +126,13 @@ int STDCALL mysql_server_init(int argc _
if (my_init()) /* Will init threads */
return 1;
init_client_errs();
+ if (mysql_client_plugin_init())
+ return 1;
if (!mysql_port)
{
mysql_port = MYSQL_PORT;
#ifndef MSDOS
{
- struct servent *serv_ptr;
char *env;
/*
@@ -145,6 +146,7 @@ int STDCALL mysql_server_init(int argc _
*/
#if MYSQL_PORT_DEFAULT == 0
+ struct servent *serv_ptr;
if ((serv_ptr = getservbyname("mysql", "tcp")))
mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
#endif
@@ -198,6 +200,8 @@ void STDCALL mysql_server_end()
if (!mysql_client_init)
return;
+ mysql_client_plugin_deinit();
+
#ifdef EMBEDDED_LIBRARY
end_embedded_server();
#endif
@@ -662,44 +666,14 @@ mysql_connect(MYSQL *mysql,const char *h
Change user and database
**************************************************************************/
-int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
-{
- NET *net= &mysql->net;
- ulong pkt_length;
-
- pkt_length= cli_safe_read(mysql);
-
- if (pkt_length == packet_error)
- return 1;
-
- if (pkt_length == 1 && net->read_pos[0] == 254 &&
- mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- By sending this very specific reply server asks us to send scrambled
- password in old format. The reply contains scramble_323.
- */
- scramble_323(buff, mysql->scramble, passwd);
- if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net))
- {
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
- return 1;
- }
- /* Read what server thinks about out new auth message report */
- if (cli_safe_read(mysql) == packet_error)
- return 1;
- }
- return 0;
-}
-
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db)
{
- char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
- char *end= buff;
int rc;
CHARSET_INFO *saved_cs= mysql->charset;
+ char *saved_user= mysql->user;
+ char *saved_passwd= mysql->passwd;
+ char *saved_db= mysql->db;
DBUG_ENTER("mysql_change_user");
@@ -713,49 +687,11 @@ my_bool STDCALL mysql_change_user(MYSQL
/* Use an empty string instead of NULL. */
- if (!user)
- user="";
- if (!passwd)
- passwd="";
-
- /*
- Store user into the buffer.
- Advance position as strmake returns a pointer to the closing NUL.
- */
- end= strmake(end, user, USERNAME_LENGTH) + 1;
-
- /* write scrambled password according to server capabilities */
- if (passwd[0])
- {
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- *end++= SCRAMBLE_LENGTH;
- scramble(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH;
- }
- else
- {
- scramble_323(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH_323 + 1;
- }
- }
- else
- *end++= '\0'; /* empty password */
- /* Add database if needed */
- end= strmake(end, db ? db : "", NAME_LEN) + 1;
-
- /* Add character set number. */
-
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- int2store(end, (ushort) mysql->charset->number);
- end+= 2;
- }
-
- /* Write authentication package */
- simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1);
+ mysql->user= (char*)(user ? user : "");
+ mysql->passwd= (char*)(passwd ? passwd : "");
+ mysql->db= 0;
- rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
+ rc= run_plugin_auth(mysql, 0, 0, 0, db);
/*
The server will close all statements no matter was the attempt
@@ -765,18 +701,21 @@ my_bool STDCALL mysql_change_user(MYSQL
if (rc == 0)
{
/* Free old connect information */
- my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_user, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_passwd, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_db, MYF(MY_ALLOW_ZERO_PTR));
/* alloc new connect information */
- mysql->user= my_strdup(user,MYF(MY_WME));
- mysql->passwd=my_strdup(passwd,MYF(MY_WME));
- mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
+ mysql->user= my_strdup(mysql->user, MYF(MY_WME));
+ mysql->passwd= my_strdup(mysql->passwd, MYF(MY_WME));
+ mysql->db= db ? my_strdup(db, MYF(MY_WME)) : 0;
}
else
{
mysql->charset= saved_cs;
+ mysql->user= saved_user;
+ mysql->passwd= saved_passwd;
+ mysql->db= saved_db;
}
DBUG_RETURN(rc);
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-12-03 11:19:05 +0000
+++ b/libmysqld/Makefile.am 2010-03-29 15:13:53 +0000
@@ -25,10 +25,10 @@ pkgplugindir = $(pkglibdir)/plugin
EXTRA_DIST = libmysqld.def CMakeLists.txt
DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
- -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
- -DPLUGINDIR="\"$(pkgplugindir)\""
+ -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' \
+ -DPLUGINDIR='"$(pkgplugindir)"'
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/sql -I$(top_srcdir)/sql \
-I$(top_srcdir)/sql/examples \
@@ -41,7 +41,7 @@ pkglib_LIBRARIES = libmysqld.a
SUBDIRS = . examples
libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc
libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
- my_time.c
+ my_time.c client_plugin.c
noinst_HEADERS = embedded_priv.h emb_qcache.h
=== modified file 'libmysqld/embedded_priv.h'
--- a/libmysqld/embedded_priv.h 2006-12-31 00:32:21 +0000
+++ b/libmysqld/embedded_priv.h 2010-03-29 15:13:53 +0000
@@ -15,6 +15,8 @@
/* Prototypes for the embedded version of MySQL */
+#include <sql_common.h>
+
C_MODE_START
void lib_connection_phase(NET *net, int phase);
void init_embedded_mysql(MYSQL *mysql, int client_flag);
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2010-03-04 08:03:07 +0000
+++ b/libmysqld/lib_sql.cc 2010-03-29 15:13:53 +0000
@@ -35,7 +35,6 @@ C_MODE_START
#include <mysql.h>
#undef ER
#include "errmsg.h"
-#include <sql_common.h>
#include "embedded_priv.h"
extern unsigned int mysql_server_last_errno;
@@ -413,11 +412,10 @@ static MYSQL_RES * emb_store_result(MYSQ
return mysql_store_result(mysql);
}
-int emb_read_change_user_result(MYSQL *mysql,
- char *buff __attribute__((unused)),
- const char *passwd __attribute__((unused)))
+int emb_read_change_user_result(MYSQL *mysql)
{
- return mysql_errno(mysql);
+ mysql->net.read_pos= (uchar*)""; // fake an OK packet
+ return mysql_errno(mysql) ? packet_error : 1 /* length of the OK packet */;
}
MYSQL_METHODS embedded_methods=
@@ -428,6 +426,7 @@ MYSQL_METHODS embedded_methods=
emb_store_result,
emb_fetch_lengths,
emb_flush_use_result,
+ emb_read_change_user_result,
emb_list_fields,
emb_read_prepare_result,
emb_stmt_execute,
@@ -436,7 +435,6 @@ MYSQL_METHODS embedded_methods=
emb_free_embedded_thd,
emb_read_statistics,
emb_read_query_result,
- emb_read_change_user_result,
emb_read_rows_from_cursor
};
@@ -584,6 +582,7 @@ void init_embedded_mysql(MYSQL *mysql, i
THD *thd = (THD *)mysql->thd;
thd->mysql= mysql;
mysql->server_version= server_version;
+ mysql->client_flag= client_flag;
init_alloc_root(&mysql->field_alloc, 8192, 0);
}
@@ -648,14 +647,19 @@ err:
int check_embedded_connection(MYSQL *mysql, const char *db)
{
int result;
+ LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 };
THD *thd= (THD*)mysql->thd;
thd_init_client_charset(thd, mysql->charset->number);
thd->update_charset();
Security_context *sctx= thd->security_ctx;
sctx->host_or_ip= sctx->host= (char*) my_localhost;
strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
- sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
- result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
+ strmake(sctx->priv_user, mysql->user, USERNAME_LENGTH-1);
+ sctx->user= my_strdup(mysql->user, MYF(0));
+ sctx->master_access= GLOBAL_ACLS; // Full rights
+ /* Change database if necessary */
+ if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE))))
+ my_ok(thd);
net_end_statement(thd);
emb_read_query_result(mysql);
return result;
@@ -664,14 +668,15 @@ int check_embedded_connection(MYSQL *mys
#else
int check_embedded_connection(MYSQL *mysql, const char *db)
{
+ /*
+ we emulate a COM_CHANGE_USER user here,
+ it's easier than to emulate the complete 3-way handshake
+ */
+ char buf[USERNAME_LENGTH + SCRAMBLE_LENGTH + 1 + 2*NAME_LEN + 2], *end;
+ NET *net= &mysql->net;
THD *thd= (THD*)mysql->thd;
Security_context *sctx= thd->security_ctx;
- int result;
- char scramble_buff[SCRAMBLE_LENGTH];
- int passwd_len;
- thd_init_client_charset(thd, mysql->charset->number);
- thd->update_charset();
if (mysql->options.client_ip)
{
sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
@@ -682,36 +687,44 @@ int check_embedded_connection(MYSQL *mys
sctx->host_or_ip= sctx->host;
if (acl_check_host(sctx->host, sctx->ip))
- {
- result= ER_HOST_NOT_PRIVILEGED;
goto err;
- }
- sctx->user= my_strdup(mysql->user, MYF(0));
+ /* construct a COM_CHANGE_USER packet */
+ end= strmake(buf, mysql->user, USERNAME_LENGTH) + 1;
+
+ memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
+ thd->scramble[SCRAMBLE_LENGTH]= 0;
+
if (mysql->passwd && mysql->passwd[0])
{
- memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
- thd->scramble[SCRAMBLE_LENGTH]= 0;
- scramble(scramble_buff, thd->scramble, mysql->passwd);
- passwd_len= SCRAMBLE_LENGTH;
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, thd->scramble, mysql->passwd);
+ end+= SCRAMBLE_LENGTH;
}
else
- passwd_len= 0;
+ *end++= 0;
- if((result= check_user(thd, COM_CONNECT,
- scramble_buff, passwd_len, db, true)))
- goto err;
+ end= strmake(end, db ? db : "", NAME_LEN) + 1;
- return 0;
-err:
+ int2store(end, (ushort) mysql->charset->number);
+ end+= 2;
+
+ /* acl_authenticate() takes the data from thd->net->read_pos */
+ thd->net.read_pos= (uchar*)buf;
+
+ if (acl_authenticate(thd, 0, end - buf))
{
- NET *net= &mysql->net;
- strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
- memcpy(net->sqlstate,
- mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
- sizeof(net->sqlstate)-1);
+ x_free(thd->security_ctx->user);
+ goto err;
}
- return result;
+ return 0;
+
+err:
+ strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
+ memcpy(net->sqlstate,
+ mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
+ sizeof(net->sqlstate)-1);
+ return 1;
}
#endif
=== modified file 'libmysqld/libmysqld.c'
--- a/libmysqld/libmysqld.c 2009-09-25 11:39:05 +0000
+++ b/libmysqld/libmysqld.c 2010-03-29 15:13:53 +0000
@@ -18,7 +18,6 @@
#include <mysql_embed.h>
#include <mysqld_error.h>
#include <my_pthread.h>
-#include "embedded_priv.h"
#include <my_sys.h>
#include <mysys_err.h>
#include <m_string.h>
@@ -28,6 +27,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
+#include "embedded_priv.h"
#include "client_settings.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -81,9 +81,9 @@ static my_bool is_NT(void)
** Shut down connection
**************************************************************************/
-static void end_server(MYSQL *mysql)
+void embedded_end_server(MYSQL *mysql)
{
- DBUG_ENTER("end_server");
+ DBUG_ENTER("embedded_end_server");
free_old_query(mysql);
DBUG_VOID_RETURN;
}
@@ -169,7 +169,11 @@ mysql_real_connect(MYSQL *mysql,const ch
client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_STATEMENTS)
client_flag|= CLIENT_MULTI_RESULTS;
- client_flag&= ~CLIENT_COMPRESS;
+ /*
+ no compression in embedded as we don't send any data,
+ and no pluggable auth, as we cannot do a client-server dialog
+ */
+ client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
@@ -216,7 +220,7 @@ error:
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;
- end_server(mysql);
+ embedded_end_server(mysql);
mysql->free_me=0;
mysql_close(mysql);
mysql->free_me=free_me;
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2010-03-17 02:32:31 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-02-19 08:10:05 +0000
@@ -1272,21 +1272,18 @@ sub command_line_setup {
if ($opt_gdb)
{
- mtr_warning("Silently converting --gdb to --client-gdb in embedded mode");
$opt_client_gdb= $opt_gdb;
$opt_gdb= undef;
}
if ($opt_ddd)
{
- mtr_warning("Silently converting --ddd to --client-ddd in embedded mode");
$opt_client_ddd= $opt_ddd;
$opt_ddd= undef;
}
if ($opt_debugger)
{
- mtr_warning("Silently converting --debugger to --client-debugger in embedded mode");
$opt_client_debugger= $opt_debugger;
$opt_debugger= undef;
}
@@ -5341,20 +5338,12 @@ sub gdb_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
else
{
# write init file for mysqld
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break mysql_parse\n" .
- "commands 1\n" .
- "disable 1\n" .
- "end\n" .
- "run");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
if ( $opt_manual_gdb )
@@ -5405,20 +5394,12 @@ sub ddd_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
else
{
# write init file for mysqld
- mtr_tofile($gdb_init_file,
- "file $$exe\n" .
- "set args $str\n" .
- "break mysql_parse\n" .
- "commands 1\n" .
- "disable 1\n" .
- "end");
+ mtr_tofile($gdb_init_file, "file $$exe\nset args $str\n");
}
if ( $opt_manual_ddd )
=== modified file 'mysql-test/r/change_user.result'
--- a/mysql-test/r/change_user.result 2009-02-12 14:08:56 +0000
+++ b/mysql-test/r/change_user.result 2010-03-29 15:13:53 +0000
@@ -1,3 +1,36 @@
+grant select on test.* to test_nopw;
+grant select on test.* to test_oldpw identified by password "09301740536db389";
+grant select on test.* to test_newpw identified by "newpw";
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_nopw@localhost> <test_nopw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_oldpw@localhost> <test_oldpw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_newpw@localhost> <test_newpw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_nopw@localhost> <test_nopw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_oldpw@localhost> <test_oldpw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_newpw@localhost> <test_newpw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> test
+drop user test_nopw;
+drop user test_oldpw;
+drop user test_newpw;
Bug#20023
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
=== modified file 'mysql-test/r/grant.result'
--- a/mysql-test/r/grant.result 2010-01-29 10:42:31 +0000
+++ b/mysql-test/r/grant.result 2010-03-29 15:13:53 +0000
@@ -13,8 +13,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'loc
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -44,15 +44,15 @@ delete from mysql.user where user='mysql
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
@@ -164,6 +164,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
=== modified file 'mysql-test/r/grant2.result'
--- a/mysql-test/r/grant2.result 2009-10-30 05:06:10 +0000
+++ b/mysql-test/r/grant2.result 2010-03-29 15:13:53 +0000
@@ -287,6 +287,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
create user mysqltest_A@'%';
rename user mysqltest_B@'%' to mysqltest_C@'%';
drop user mysqltest_C@'%';
@@ -354,6 +355,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
INSERT INTO mysql.db (host, db, user, select_priv) VALUES
('%','TESTDB','mysqltest_1','Y');
FLUSH PRIVILEGES;
=== modified file 'mysql-test/r/key_cache.result'
--- a/mysql-test/r/key_cache.result 2010-03-31 18:45:41 +0000
+++ b/mysql-test/r/key_cache.result 2010-03-31 23:03:57 +0000
@@ -388,7 +388,7 @@ i int, a char(10), key k1(i), key k2(a))
select @@key_cache_partitions;
@@key_cache_partitions
0
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
@@ -416,18 +416,18 @@ Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t2 where a='zzzz';
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 29 0 32 9
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 29 0 32 9
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
@@ -435,10 +435,8 @@ set global key_cache_partitions=2;
select @@key_cache_partitions;
@@key_cache_partitions
2
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 0 # 0 0 0 0 0
-default 2 2 1048576 1024 0 # 0 0 0 0 0
default 2 NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
@@ -465,27 +463,22 @@ Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 # # 0 10 0 13 4
-default 2 2 1048576 1024 # # 0 12 0 13 2
-default 2 NULL 2097152 1024 # # 0 22 0 26 6
-small NULL NULL 1048576 1024 # # 0 1 0 2 1
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 # # 0 10 0 13 4
-default 2 2 1048576 1024 # # 0 12 0 13 2
-default 2 NULL 2097152 1024 # # 0 22 0 26 6
-small NULL NULL 1048576 1024 # # 0 1 0 2 1
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
set global key_cache_partitions=1;
select @@key_cache_partitions;
@@key_cache_partitions
1
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 0 # 0 0 0 0 0
default 1 NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
@@ -512,23 +505,20 @@ Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 4 # 0 22 0 26 6
default 1 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 4 # 0 22 0 26 6
default 1 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
flush tables;
flush status;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 1 1 2097152 1024 4 # 0 0 0 0 0
default 1 NULL 2097152 1024 4 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
set global key_buffer_size=32*1024;
@@ -539,10 +529,8 @@ set global key_cache_partitions=2;
select @@key_cache_partitions;
@@key_cache_partitions
2
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 0 # 0 0 0 0 0
-default 2 2 16384 1024 0 # 0 0 0 0 0
default 2 NULL 32768 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
@@ -560,10 +548,8 @@ p i a
4 3 zzzz
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 1 # 0 12 0 13 2
-default 2 2 16384 1024 3 # 0 10 0 13 4
default 2 NULL 32768 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
insert into t1(a) select a from t1;
@@ -582,10 +568,8 @@ insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 1951 # 1976 43
-default 2 2 16384 1024 # # 0 4782 # 1708 60
default 2 NULL 32768 1024 # # 0 6733 # 3684 103
small NULL NULL 1048576 1024 # # 0 0 # 0 0
select * from t1 where p between 1010 and 1020 ;
@@ -603,20 +587,16 @@ p i a
1018 2 pppp
1019 2 yyyy
1020 3 zzzz
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 1954 # 1976 43
-default 2 2 16384 1024 # # 0 4796 # 1708 60
default 2 NULL 32768 1024 # # 0 6750 # 3684 103
small NULL NULL 1048576 1024 # # 0 0 # 0 0
flush tables;
flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 940 10 939 10
-default 2 2 16384 1024 # # 0 2136 8 613 8
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=256*1024;
@@ -627,29 +607,14 @@ set global keycache1.key_cache_partition
select @@keycache1.key_cache_partitions;
@@keycache1.key_cache_partitions
7
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 940 10 939 10
-default 2 2 16384 1024 # # 0 2136 8 613 8
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 0 0 0 0
-keycache1 7 2 37449 2048 # # 0 0 0 0 0
-keycache1 7 3 37449 2048 # # 0 0 0 0 0
-keycache1 7 4 37449 2048 # # 0 0 0 0 0
-keycache1 7 5 37449 2048 # # 0 0 0 0 0
-keycache1 7 6 37449 2048 # # 0 0 0 0 0
-keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 0 0 0 0
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 0 # 0 0 0 0 0
-keycache1 7 2 37449 2048 0 # 0 0 0 0 0
-keycache1 7 3 37449 2048 0 # 0 0 0 0 0
-keycache1 7 4 37449 2048 0 # 0 0 0 0 0
-keycache1 7 5 37449 2048 0 # 0 0 0 0 0
-keycache1 7 6 37449 2048 0 # 0 0 0 0 0
-keycache1 7 7 37449 2048 0 # 0 0 0 0 0
keycache1 7 NULL 262143 2048 0 # 0 0 0 0 0
cache index t1 key (`primary`) in keycache1;
Table Op Msg_type Msg_text
@@ -682,61 +647,35 @@ id select_type table type possible_keys
select count(*) from t1, t2 where t1.p = t2.i;
count(*)
256
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 2 1 0 0
-keycache1 7 2 37449 2048 # # 0 7 1 0 0
-keycache1 7 3 37449 2048 # # 0 0 0 0 0
-keycache1 7 4 37449 2048 # # 0 5 1 0 0
-keycache1 7 5 37449 2048 # # 0 0 0 0 0
-keycache1 7 6 37449 2048 # # 0 0 0 0 0
-keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 14 3 0 0
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 1 # 0 2 1 0 0
-keycache1 7 2 37449 2048 1 # 0 7 1 0 0
-keycache1 7 3 37449 2048 0 # 0 0 0 0 0
-keycache1 7 4 37449 2048 1 # 0 5 1 0 0
-keycache1 7 5 37449 2048 0 # 0 0 0 0 0
-keycache1 7 6 37449 2048 0 # 0 0 0 0 0
-keycache1 7 7 37449 2048 0 # 0 0 0 0 0
keycache1 7 NULL 262143 2048 3 # 0 14 3 0 0
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+3000, i=2 where a='qqqq';
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 3 # 0 44 3 43 2
-keycache1 7 2 37449 2048 4 # 0 61 4 51 1
-keycache1 7 3 37449 2048 4 # 0 177 4 176 3
-keycache1 7 4 37449 2048 4 # 0 122 4 119 3
-keycache1 7 5 37449 2048 4 # 0 840 4 335 4
-keycache1 7 6 37449 2048 3 # 0 627 3 133 3
-keycache1 7 7 37449 2048 3 # 0 211 3 214 3
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy');
-select * from information_schema.key_caches where key_cache_name like "keycache2";
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-keycache1 7 1 37449 2048 3 # 0 44 3 43 2
-keycache1 7 2 37449 2048 4 # 0 61 4 51 1
-keycache1 7 3 37449 2048 4 # 0 177 4 176 3
-keycache1 7 4 37449 2048 4 # 0 122 4 119 3
-keycache1 7 5 37449 2048 4 # 0 840 4 335 4
-keycache1 7 6 37449 2048 3 # 0 627 3 133 3
-keycache1 7 7 37449 2048 3 # 0 211 3 214 3
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
cache index t2 in keycache1;
@@ -774,127 +713,77 @@ id select_type table type possible_keys
select a from t2 where a='yyyy' and i=3 ;
a
yyyy
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 85 6 68 3
-keycache1 7 2 37449 2048 # # 0 122 6 102 2
-keycache1 7 3 37449 2048 # # 0 271 8 254 6
-keycache1 7 4 37449 2048 # # 0 179 6 170 4
-keycache1 7 5 37449 2048 # # 0 1445 7 416 6
-keycache1 7 6 37449 2048 # # 0 863 6 345 5
-keycache1 7 7 37449 2048 # # 0 236 4 239 4
keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 37449 2048 # # 0 1 1 1 1
-keycache1 7 2 37449 2048 # # 0 1 1 0 0
-keycache1 7 3 37449 2048 # # 0 0 0 0 0
-keycache1 7 4 37449 2048 # # 0 1 1 1 1
-keycache1 7 5 37449 2048 # # 0 1 1 0 0
-keycache1 7 6 37449 2048 # # 0 2 2 1 1
-keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 3 1 87381 8192 # # 0 1 1 1 1
-keycache1 3 2 87381 8192 # # 0 3 2 1 1
-keycache1 3 3 87381 8192 # # 0 2 2 1 1
keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=64*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=2*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 3 1 21845 2048 # # 0 0 0 0 0
-keycache1 3 2 21845 2048 # # 0 0 0 0 0
-keycache1 3 3 21845 2048 # # 0 0 0 0 0
keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=0;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=0;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=128*1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 1 1 131072 8192 # # 0 0 0 0 0
keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=1024;
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 16384 1024 # # 0 966 12 939 10
-default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 1 18724 1024 # # 0 0 0 0 0
-keycache1 7 2 18724 1024 # # 0 0 0 0 0
-keycache1 7 3 18724 1024 # # 0 0 0 0 0
-keycache1 7 4 18724 1024 # # 0 0 0 0 0
-keycache1 7 5 18724 1024 # # 0 0 0 0 0
-keycache1 7 6 18724 1024 # # 0 0 0 0 0
-keycache1 7 7 18724 1024 # # 0 0 0 0 0
keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
drop table t1,t2;
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result 2009-12-26 11:25:56 +0000
+++ b/mysql-test/r/ps.result 2010-03-29 15:13:53 +0000
@@ -1194,13 +1194,13 @@ SET @aux= "SELECT COUNT(*)
prepare my_stmt from @aux;
execute my_stmt;
COUNT(*)
-39
+41
execute my_stmt;
COUNT(*)
-39
+41
execute my_stmt;
COUNT(*)
-39
+41
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
=== modified file 'mysql-test/r/sp_notembedded.result'
--- a/mysql-test/r/sp_notembedded.result 2010-01-11 13:15:28 +0000
+++ b/mysql-test/r/sp_notembedded.result 2010-03-29 15:13:53 +0000
@@ -191,6 +191,8 @@ max_updates, max_connections, max_user_c
VALUES('%', 'mysqltest_1', password(''), 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N',
'N', 'N', 'N', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'Y', 'Y', 'N', '',
'', '', '', '0', '0', '0', '0');
+Warnings:
+Warning 1364 Field 'auth_string' doesn't have a default value
FLUSH PRIVILEGES;
CREATE PROCEDURE p1(i INT) BEGIN END;
DROP PROCEDURE p1;
=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result 2009-10-27 10:09:36 +0000
+++ b/mysql-test/r/system_mysql_db.result 2010-03-29 15:13:53 +0000
@@ -118,6 +118,8 @@ user CREATE TABLE `user` (
`max_updates` int(11) unsigned NOT NULL DEFAULT '0',
`max_connections` int(11) unsigned NOT NULL DEFAULT '0',
`max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
+ `plugin` char(60) CHARACTER SET latin1 NOT NULL DEFAULT '',
+ `auth_string` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2009-10-28 09:23:02 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result 2010-03-29 15:13:53 +0000
@@ -178,6 +178,7 @@ NULL mysql time_zone_transition_type Tim
NULL mysql time_zone_transition_type Transition_type_id 2 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned PRI select,insert,update,references
NULL mysql user Alter_priv 17 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Alter_routine_priv 28 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
+NULL mysql user auth_string 41 NULL NO text 65535 65535 NULL NULL utf8 utf8_bin text select,insert,update,references
NULL mysql user Create_priv 8 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Create_routine_priv 27 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Create_tmp_table_priv 20 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -198,6 +199,7 @@ NULL mysql user max_questions 36 0 NO in
NULL mysql user max_updates 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
NULL mysql user max_user_connections 39 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
NULL mysql user Password 3 NO char 41 41 NULL NULL latin1 latin1_bin char(41) select,insert,update,references
+NULL mysql user plugin 40 NO char 60 60 NULL NULL latin1 latin1_swedish_ci char(60) select,insert,update,references
NULL mysql user Process_priv 12 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user References_priv 15 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Reload_priv 10 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -233,6 +235,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COL
1.0000 char latin1 latin1_bin
1.0000 char latin1 latin1_swedish_ci
1.0000 varchar latin1 latin1_swedish_ci
+1.0000 text utf8 utf8_bin
1.0000 mediumtext utf8 utf8_general_ci
1.0000 text utf8 utf8_general_ci
SELECT DISTINCT
@@ -497,3 +500,5 @@ NULL mysql user max_questions int NULL N
NULL mysql user max_updates int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_connections int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) unsigned
+1.0000 mysql user plugin char 60 60 latin1 latin1_swedish_ci char(60)
+1.0000 mysql user auth_string text 65535 65535 utf8 utf8_bin text
=== modified file 'mysql-test/suite/funcs_1/r/is_user_privileges.result'
--- a/mysql-test/suite/funcs_1/r/is_user_privileges.result 2008-03-07 19:18:14 +0000
+++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result 2010-03-29 15:13:53 +0000
@@ -76,10 +76,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
#
# Add GRANT OPTION db_datadict.* to testuser1;
GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
@@ -93,10 +93,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Establish connection testuser1 (user=testuser1)
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -105,10 +105,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -130,10 +130,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
#
# Here <SELECT YES> is shown correctly for testuser1;
@@ -147,10 +147,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -159,10 +159,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL SELECT YES
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION
@@ -207,10 +207,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -253,10 +253,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -265,10 +265,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -284,10 +284,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser1'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -309,10 +309,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_
'testuser3'@'localhost' NULL USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
=== modified file 'mysql-test/suite/pbxt/r/grant.result'
--- a/mysql-test/suite/pbxt/r/grant.result 2009-11-24 10:19:08 +0000
+++ b/mysql-test/suite/pbxt/r/grant.result 2010-03-29 15:13:53 +0000
@@ -11,8 +11,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'loc
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -42,15 +42,15 @@ delete from mysql.user where user='mysql
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
@@ -162,6 +162,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
=== modified file 'mysql-test/suite/rpl/r/rpl_ignore_table.result'
--- a/mysql-test/suite/rpl/r/rpl_ignore_table.result 2008-11-13 19:19:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_ignore_table.result 2010-03-29 15:13:53 +0000
@@ -34,6 +34,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
GRANT SELECT ON *.* TO mysqltest6@localhost;
GRANT INSERT ON *.* TO mysqltest6@localhost;
GRANT INSERT ON test.* TO mysqltest6@localhost;
=== modified file 'mysql-test/suite/rpl/r/rpl_stm_000001.result'
--- a/mysql-test/suite/rpl/r/rpl_stm_000001.result 2009-11-18 14:50:31 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stm_000001.result 2010-03-29 15:13:53 +0000
@@ -66,6 +66,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
select select_priv,user from mysql.user where user = _binary'blafasel2';
select_priv user
N blafasel2
=== modified file 'mysql-test/t/change_user.test'
--- a/mysql-test/t/change_user.test 2009-10-28 07:52:34 +0000
+++ b/mysql-test/t/change_user.test 2010-03-29 15:13:53 +0000
@@ -1,4 +1,50 @@
#
+# functional change user tests
+#
+
+grant select on test.* to test_nopw;
+grant select on test.* to test_oldpw identified by password "09301740536db389";
+grant select on test.* to test_newpw identified by "newpw";
+
+#
+# massaging the data for tests to pass in the embedded server,
+# that has authentication completely disabled.
+#
+
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+change_user test_nopw;
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_oldpw, oldpw;
+--replace_result <@> <test_oldpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_newpw, newpw;
+--replace_result <@> <test_newpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user root;
+--replace_result <@> <root@localhost> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+change_user test_nopw,,test;
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_oldpw,oldpw,test;
+--replace_result <@> <test_oldpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_newpw,newpw,test;
+--replace_result <@> <test_newpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user root,,test;
+--replace_result <@> <root@localhost> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+drop user test_nopw;
+drop user test_oldpw;
+drop user test_newpw;
+
+#
# Bug#20023 mysql_change_user() resets the value of SQL_BIG_SELECTS
# The replace's are here to fix things for 32 bit systems
#
=== modified file 'mysql-test/t/key_cache.test'
--- a/mysql-test/t/key_cache.test 2010-03-31 18:45:41 +0000
+++ b/mysql-test/t/key_cache.test 2010-03-31 23:03:57 +0000
@@ -272,7 +272,7 @@ create table t2 (
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -285,16 +285,16 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
delete from t2 where a='zzzz';
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# For the key cache with 2 partitions execute the same sequence of
# statements as for the simple cache above.
@@ -304,7 +304,7 @@ select * from information_schema.key_cac
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -316,20 +316,20 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
---replace_column 6 # 7 #
-select * from information_schema.key_caches;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
---replace_column 6 # 7 #
-select * from information_schema.key_caches;
+--replace_column 7 #
+select * from information_schema.key_caches where partition_number is null;
# Check that we can work with one partition with the same results
set global key_cache_partitions=1;
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -342,16 +342,16 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
flush tables; flush status;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# Switch back to 2 partitions
@@ -360,7 +360,7 @@ select @@key_buffer_size;
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
@@ -371,7 +371,7 @@ update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_column 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# Add more rows to tables t1 and t2
@@ -394,18 +394,18 @@ insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
--replace_column 6 # 7 # 10 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
select * from t1 where p between 1010 and 1020 ;
select * from t2 where p between 1010 and 1020 ;
--replace_column 6 # 7 # 10 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
flush tables; flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
# Now test how we can work with 7 partitions
@@ -415,9 +415,10 @@ set global keycache1.key_cache_partition
select @@keycache1.key_cache_partitions;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
cache index t1 key (`primary`) in keycache1;
@@ -429,22 +430,26 @@ explain select count(*) from t1, t2 wher
select count(*) from t1, t2 where t1.p = t2.i;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
cache index t2 in keycache1;
update t2 set p=p+3000, i=2 where a='qqqq';
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
insert into t2 values (2000, 3, 'yyyy');
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "keycache2";
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and partition_number is null;
--replace_column 7 #
-select * from information_schema.key_caches where key_cache_name like "key%";
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and partition_number is null;
cache index t2 in keycache1;
update t2 set p=p+5000 where a='zzzz';
@@ -456,49 +461,49 @@ select i from t2 where a='yyyy' and i=3;
explain select a from t2 where a='yyyy' and i=3;
select a from t2 where a='yyyy' and i=3 ;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=64*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=2*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=128*1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=1024;
--replace_column 6 # 7 #
-select * from information_schema.key_caches;
+select * from information_schema.key_caches where partition_number is null;
drop table t1,t2;
=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp 2010-03-10 09:11:02 +0000
+++ b/mysql-test/valgrind.supp 2010-02-19 08:12:25 +0000
@@ -1000,6 +1000,27 @@
fun:nptl_pthread_exit_hack_handler
}
+{
+ Invalid read within nptl_pthread_exit_hack_handler
+ Memcheck:Addr8
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/libc-*.so
+ obj:*/ld-*.so
+ obj:*/libc-*.so
+ fun:__libc_dlopen_mode
+ fun:pthread_cancel_init
+ fun:_Unwind_ForcedUnwind
+ fun:__pthread_unwind
+ fun:pthread_exit
+ fun:nptl_pthread_exit_hack_handler
+}
+
#
# Pthread doesn't free all thread specific memory before program exists
#
=== modified file 'mysys/Makefile.am'
--- a/mysys/Makefile.am 2009-12-03 11:19:05 +0000
+++ b/mysys/Makefile.am 2010-03-29 15:13:53 +0000
@@ -74,13 +74,13 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
# charset2html_DEPENDENCIES= $(LIBRARIES)
-DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+DEFS = -DDEFAULT_BASEDIR='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
+ -DSHAREDIR'="$(MYSQLSHAREdir)"' \
-DDEFAULT_HOME_ENV=MYSQL_HOME \
-DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
+ -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
@DEFS@
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
=== added directory 'plugin/auth'
=== added file 'plugin/auth/Makefile.am'
--- a/plugin/auth/Makefile.am 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/Makefile.am 2010-03-29 15:13:53 +0000
@@ -0,0 +1,15 @@
+pkgplugindir=$(pkglibdir)/plugin
+
+AM_LDFLAGS=-module -rpath $(pkgplugindir)
+AM_CPPFLAGS=-DMYSQL_DYNAMIC_PLUGIN -I$(top_srcdir)/include
+
+pkgplugin_LTLIBRARIES= dialog.la
+dialog_la_SOURCES= dialog.c
+
+if HAVE_PEERCRED
+pkgplugin_LTLIBRARIES+= auth_socket.la
+auth_socket_la_SOURCES= auth_socket.c
+endif
+
+EXTRA_DIST= plug.in
+
=== added file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/auth_socket.c 2010-03-29 15:13:53 +0000
@@ -0,0 +1,102 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ socket_peercred authentication plugin.
+
+ Authentication is successful if the connection is done via a unix socket and
+ the owner of the client process matches the user name that was used when
+ connecting to mysqld.
+*/
+#define _GNU_SOURCE /* for struct ucred */
+
+#include <mysql/plugin_auth.h>
+#include <sys/socket.h>
+#include <pwd.h>
+#include <string.h>
+
+/**
+ perform the unix socket based authentication
+
+ This authentication callback performs a unix socket based authentication -
+ it gets the uid of the client process and considers the user authenticated
+ if it uses username of this uid. That is - if the user is already
+ authenticated to the OS (if she is logged in) - she can use MySQL as herself
+*/
+
+static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ MYSQL_PLUGIN_VIO_INFO vio_info;
+ struct ucred cred;
+ socklen_t cred_len= sizeof(cred);
+ struct passwd pwd_buf, *pwd;
+ char buf[1024];
+
+ /* no user name yet ? read the client handshake packet with the user name */
+ if (info->user_name == 0)
+ {
+ if (vio->read_packet(vio, &pkt) < 0)
+ return CR_ERROR;
+ }
+
+ info->password_used = 0;
+
+ vio->info(vio, &vio_info);
+ if (vio_info.protocol != MYSQL_VIO_SOCKET)
+ return CR_ERROR;
+
+ /* get the UID of the client process */
+ if (getsockopt(vio_info.socket, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len))
+ return CR_ERROR;
+
+ if (cred_len != sizeof(cred))
+ return CR_ERROR;
+
+ /* and find the username for this uid */
+ getpwuid_r(cred.uid, &pwd_buf, buf, sizeof(buf), &pwd);
+ if (pwd == NULL)
+ return CR_ERROR;
+
+ /* now it's simple as that */
+ return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK;
+}
+
+static struct st_mysql_auth socket_auth_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ 0,
+ socket_auth
+};
+
+mysql_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+
=== added file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/dialog.c 2010-03-31 18:37:45 +0000
@@ -0,0 +1,308 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ dialog client authentication plugin with examples
+
+ dialog is a general purpose client authentication plugin, it simply
+ asks the user the question, as provided by the server and reports
+ the answer back to the server. No encryption is involved,
+ the answers are sent in clear text.
+
+ Two examples are provided: two_questions server plugin, that asks
+ the password and an "Are you sure?" question with a reply "yes, of course".
+ It demonstrates the usage of "password" (input is hidden) and "ordinary"
+ (input can be echoed) questions, and how to mark the last question,
+ to avoid an extra roundtrip.
+
+ And three_attempts plugin that gives the user three attempts to enter
+ a correct password. It shows the situation when a number of questions
+ is not known in advance.
+*/
+#define _GNU_SOURCE /* for RTLD_DEFAULT */
+
+#include <mysql/plugin_auth.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ first byte of the question string is the question "type".
+ It can be a "ordinary" or a "password" question.
+ The last bit set marks a last question in the authentication exchange.
+*/
+#define ORDINARY_QUESTION "\2"
+#define LAST_QUESTION "\3"
+#define PASSWORD_QUESTION "\4"
+#define LAST_PASSWORD "\5"
+
+typedef unsigned char uchar;
+
+/********************* SERVER SIDE ****************************************/
+
+/**
+ dialog demo with two questions, one password and one ordinary.
+*/
+
+static int two_questions(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len;
+
+ /* send a password question */
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"),
+ 18))
+ return CR_ERROR;
+
+ /* read the answer */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ /* fail if the password is wrong */
+ if (strcmp((char*) pkt, info->auth_string))
+ return CR_ERROR;
+
+ /* send the last, ordinary, question */
+ if (vio->write_packet(vio,
+ (const uchar*) (LAST_QUESTION "Are you sure ?"), 15))
+ return CR_ERROR;
+
+ /* read the answer */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ /* check the reply */
+ return strcmp((char*) pkt, "yes, of course") ? CR_ERROR : CR_OK;
+}
+
+static struct st_mysql_auth two_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog", /* requires dialog client plugin */
+ two_questions
+};
+
+
+/**
+ dialog demo where the number of questions is not known in advance
+*/
+
+static int three_attempts(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len, i;
+
+ for (i= 0; i < 3; i++)
+ {
+ /* send the prompt */
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"), 18))
+ return CR_ERROR;
+
+ /* read the password */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ /*
+ finish, if the password is correct.
+ note, that we did not mark the prompt packet as "last"
+ */
+ if (strcmp((char*) pkt, info->auth_string) == 0)
+ return CR_OK;
+ }
+
+ return CR_ERROR;
+}
+
+static struct st_mysql_auth three_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog", /* requires dialog client plugin */
+ three_attempts
+};
+
+mysql_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+
+/********************* CLIENT SIDE ***************************************/
+/*
+ This plugin performs a dialog with the user, asking questions and
+ reading answers. Depending on the client it may be desirable to do it
+ using GUI, or console, with or without curses, or read answers
+ from a smardcard, for example.
+
+ To support all this variety, the dialog plugin has a callback function
+ "authentication_dialog_ask". If the client has a function of this name
+ dialog plugin will use it for communication with the user. Otherwise
+ a default gets() based implementation will be used.
+*/
+#include <mysql.h>
+#include <dlfcn.h>
+
+static mysql_authentication_dialog_ask_t ask;
+
+static char *builtin_ask(MYSQL *mysql __attribute__((unused)),
+ int type __attribute__((unused)),
+ const char *prompt,
+ char *buf, int buf_len __attribute__((unused)))
+{
+ fputs(prompt, stdout);
+ fputc(' ', stdout);
+ if (gets(buf) == 0)
+ return 0;
+
+ return buf;
+}
+
+
+/**
+ The main function of the dialog plugin.
+
+ Read the prompt, ask the question, send the reply, repeat until
+ the server is satisfied.
+
+ @note
+ 1. this plugin shows how a client authentication plugin
+ may read a MySQL protocol OK packet internally - which is important
+ where a number of packets is not known in advance.
+ 2. the first byte of the prompt is special. it is not
+ shown to the user, but signals whether it is the last question
+ (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0),
+ and whether the input is a password (not echoed).
+ 3. the prompt is expected to be sent zero-terminated
+*/
+
+static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ unsigned char *pkt, cmd= 0;
+ int pkt_len, res;
+ char reply_buf[1024], *reply;
+
+ do
+ {
+ /* read the prompt */
+ pkt_len= vio->read_packet(vio, &pkt);
+ if (pkt_len < 0)
+ return CR_ERROR;
+
+ if (pkt == 0)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet, so
+ the first vio->read_packet() does nothing (pkt == 0).
+
+ We send the "password", assuming the client knows what its doing.
+ (in other words, the dialog plugin should be only set as a default
+ authentication plugin on the client if the first question
+ asks for a password - which will be sent in clear text, by the way)
+ */
+ reply= mysql->passwd;
+ }
+ else
+ {
+ cmd= *pkt++;
+
+ /* is it MySQL protocol packet ? */
+ if (cmd == 0 || cmd == 254)
+ return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */
+
+ /*
+ asking for a password with an empty prompt means mysql->password
+ otherwise we ask the user and read the reply
+ */
+ if ((cmd >> 1) == 2 && *pkt == 0)
+ reply= mysql->passwd;
+ else
+ reply= ask(mysql, cmd >> 1, (char*) pkt, reply_buf, sizeof(reply_buf));
+ if (!reply)
+ return CR_ERROR;
+ }
+ /* send the reply to the server */
+ res= vio->write_packet(vio, (uchar*) reply, strlen(reply)+1);
+
+ if (reply != mysql->passwd && reply != reply_buf)
+ free(reply);
+
+ if (res)
+ return CR_ERROR;
+
+ /* repeat unless it was the last question */
+ } while ((cmd & 1) != 1);
+
+ /* the job of reading the ok/error packet is left to the server */
+ return CR_OK;
+}
+
+
+/**
+ initialization function of the dialog plugin
+
+ Pick up the client's authentication_dialog_ask() function, if exists,
+ or fall back to the default implementation.
+*/
+
+static int init_dialog()
+{
+ void *sym= dlsym(RTLD_DEFAULT, "mysql_authentication_dialog_ask");
+ ask= sym ? (mysql_authentication_dialog_ask_t)sym : builtin_ask;
+ return 0;
+}
+
+mysql_declare_client_plugin(AUTHENTICATION)
+ "dialog",
+ "Sergei Golubchik",
+ "Dialog Client Authentication Plugin",
+ {0,1,0},
+ init_dialog,
+ NULL,
+ perform_dialog
+mysql_end_client_plugin;
+
=== added file 'plugin/auth/plug.in'
--- a/plugin/auth/plug.in 1970-01-01 00:00:00 +0000
+++ b/plugin/auth/plug.in 2010-03-29 15:13:53 +0000
@@ -0,0 +1,15 @@
+MYSQL_PLUGIN(auth, [Collection of Authentication Plugins],
+ [Collection of Authentication Plugins])
+MYSQL_PLUGIN_DYNAMIC(auth, [dialog.la])
+MYSQL_PLUGIN_ACTIONS(auth,[
+AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#define _GNU_SOURCE
+#include <sys/socket.h>
+]],[[
+ struct ucred cred;
+ getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0);
+]])],have_peercred=yes)
+AM_CONDITIONAL(HAVE_PEERCRED, test x$have_peercred = xyes)
+])
+AM_CONDITIONAL(HAVE_PEERCRED, false)
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql 2009-10-27 10:09:36 +0000
+++ b/scripts/mysql_system_tables.sql 2010-03-29 15:13:53 +0000
@@ -13,7 +13,7 @@ set @had_db_table= @@warning_count != 0;
CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT
NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
-CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_rout
ine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
+CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_rout
ine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, auth_string TEXT NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
-- Remember for later if user table already existed
set @had_user_table= @@warning_count != 0;
=== modified file 'scripts/mysql_system_tables_data.sql'
--- a/scripts/mysql_system_tables_data.sql 2008-10-03 15:54:22 +0000
+++ b/scripts/mysql_system_tables_data.sql 2010-03-29 15:13:53 +0000
@@ -21,9 +21,9 @@ DROP TABLE tmp_db;
-- from local machine if "users" table didn't exist before
CREATE TEMPORARY TABLE tmp_user LIKE user;
set @current_hostname= @@hostname;
-INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
-REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost';
-REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
+REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','' FROM dual WHERE LOWER( @current_hostname) != 'localhost';
+REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
INSERT INTO tmp_user (host,user) VALUES ('localhost','');
INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost';
INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;
=== modified file 'scripts/mysql_system_tables_fix.sql'
--- a/scripts/mysql_system_tables_fix.sql 2009-12-03 16:15:47 +0000
+++ b/scripts/mysql_system_tables_fix.sql 2010-03-29 15:13:53 +0000
@@ -571,6 +571,9 @@ ALTER TABLE tables_priv MODIFY Table_pri
UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0;
+ALTER TABLE user ADD plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, ADD auth_string TEXT NOT NULL;
+ALTER TABLE user MODIFY plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL;
+
# Activate the new, possible modified privilege tables
# This should not be needed, but gives us some extra testing that the above
# changes was correct
=== modified file 'server-tools/instance-manager/Makefile.am'
--- a/server-tools/instance-manager/Makefile.am 2007-02-18 12:45:28 +0000
+++ b/server-tools/instance-manager/Makefile.am 2010-03-29 15:13:53 +0000
@@ -46,7 +46,8 @@ libnet_a_LIBADD= $(top_builddir)/sql/pas
$(top_builddir)/sql/pack.$(OBJEXT) \
$(top_builddir)/sql/sql_state.$(OBJEXT) \
$(top_builddir)/sql/mini_client_errors.$(OBJEXT)\
- $(top_builddir)/sql/client.$(OBJEXT)
+ $(top_builddir)/sql/client.$(OBJEXT) \
+ $(top_builddir)/sql/client_plugin.$(OBJEXT)
CLEANFILES= net_serv.cc client_settings.h
@@ -91,7 +92,7 @@ mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAG
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
$(top_builddir)/dbug/libdbug.a \
- @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@
+ @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@ @LIBDL@
EXTRA_DIST = WindowsService.cpp WindowsService.h IMService.cpp \
IMService.h CMakeLists.txt
=== modified file 'server-tools/instance-manager/user_map.cc'
--- a/server-tools/instance-manager/user_map.cc 2009-12-18 19:14:09 +0000
+++ b/server-tools/instance-manager/user_map.cc 2010-03-29 15:13:53 +0000
@@ -368,7 +368,7 @@ int User_map::authenticate(const LEX_STR
const char *scramble) const
{
const User *user= find_user(user_name);
- return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
+ return user ? check_scramble((uchar*)scrambled_password, scramble, user->salt) : 2;
}
=== modified file 'sql-common/Makefile.am'
--- a/sql-common/Makefile.am 2006-12-31 00:02:27 +0000
+++ b/sql-common/Makefile.am 2010-03-29 15:13:53 +0000
@@ -14,7 +14,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## Process this file with automake to create Makefile.in
-EXTRA_DIST = client.c pack.c my_time.c my_user.c
+EXTRA_DIST = client.c pack.c my_time.c my_user.c client_plugin.c
# Don't update the files from bitkeeper
%::SCCS/s.%
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2010-02-01 06:14:12 +0000
+++ b/sql-common/client.c 2010-03-29 15:13:53 +0000
@@ -107,6 +107,10 @@ my_bool net_flush(NET *net);
#include "client_settings.h"
#include <sql_common.h>
+#include <mysql/client_plugin.h>
+
+#define native_password_plugin_name "mysql_native_password"
+#define old_password_plugin_name "mysql_old_password"
uint mysql_port=0;
char *mysql_unix_port= 0;
@@ -332,7 +336,7 @@ void net_clear_error(NET *net)
@param ... variable number of arguments
*/
-static void set_mysql_extended_error(MYSQL *mysql, int errcode,
+void set_mysql_extended_error(MYSQL *mysql, int errcode,
const char *sqlstate,
const char *format, ...)
{
@@ -1002,9 +1006,20 @@ static const char *default_options[]=
"replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
- "report-data-truncation",
+ "report-data-truncation", "plugin-dir", "default-auth",
NullS
};
+enum option_id {
+ OPT_port=1, OPT_socket, OPT_compress, OPT_password, OPT_pipe, OPT_timeout, OPT_user,
+ OPT_init_command, OPT_host, OPT_database, OPT_debug, OPT_return_found_rows,
+ OPT_ssl_key, OPT_ssl_cert, OPT_ssl_ca, OPT_ssl_capath,
+ OPT_character_sets_dir, OPT_default_character_set, OPT_interactive_timeout,
+ OPT_connect_timeout, OPT_local_infile, OPT_disable_local_infile,
+ OPT_replication_probe, OPT_enable_reads_from_master, OPT_repl_parse_query,
+ OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
+ OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
+ OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
+};
static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options, NULL};
@@ -1035,6 +1050,15 @@ static int add_init_command(struct st_my
return 0;
}
+#define extension_set_string(OPTS, X, STR) \
+ if ((OPTS)->extension) \
+ my_free((OPTS)->extension->X, MYF(MY_ALLOW_ZERO_PTR)); \
+ else \
+ (OPTS)->extension= (struct st_mysql_options_extention *) \
+ my_malloc(sizeof(struct st_mysql_options_extention), \
+ MYF(MY_WME | MY_ZEROFILL)); \
+ (OPTS)->extension->X= my_strdup((STR), MYF(MY_WME));
+
void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
{
@@ -1067,134 +1091,134 @@ void mysql_read_default_options(struct s
for (end= *option ; *(end= strcend(end,'_')) ; )
*end= '-';
switch (find_type(*option+2,&option_types,2)) {
- case 1: /* port */
+ case OPT_port:
if (opt_arg)
options->port=atoi(opt_arg);
break;
- case 2: /* socket */
+ case OPT_socket:
if (opt_arg)
{
my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 3: /* compress */
+ case OPT_compress:
options->compress=1;
options->client_flag|= CLIENT_COMPRESS;
break;
- case 4: /* password */
+ case OPT_password:
if (opt_arg)
{
my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
options->password=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 5:
+ case OPT_pipe:
options->protocol = MYSQL_PROTOCOL_PIPE;
- case 20: /* connect_timeout */
- case 6: /* timeout */
+ case OPT_connect_timeout:
+ case OPT_timeout:
if (opt_arg)
options->connect_timeout=atoi(opt_arg);
break;
- case 7: /* user */
+ case OPT_user:
if (opt_arg)
{
my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
options->user=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 8: /* init-command */
+ case OPT_init_command:
add_init_command(options,opt_arg);
break;
- case 9: /* host */
+ case OPT_host:
if (opt_arg)
{
my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
options->host=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 10: /* database */
+ case OPT_database:
if (opt_arg)
{
my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
options->db=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 11: /* debug */
+ case OPT_debug:
#ifdef MYSQL_CLIENT
mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
break;
#endif
- case 12: /* return-found-rows */
+ case OPT_return_found_rows:
options->client_flag|=CLIENT_FOUND_ROWS;
break;
#ifdef HAVE_OPENSSL
- case 13: /* ssl_key */
+ case OPT_ssl_key:
my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 14: /* ssl_cert */
+ case OPT_ssl_cert:
my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 15: /* ssl_ca */
+ case OPT_ssl_ca:
my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 16: /* ssl_capath */
+ case OPT_ssl_capath:
my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 26: /* ssl_cipher */
+ case OPT_ssl_cipher:
my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
break;
#else
- case 13: /* Ignore SSL options */
- case 14:
- case 15:
- case 16:
- case 26:
+ case OPT_ssl_key:
+ case OPT_ssl_cert:
+ case OPT_ssl_ca:
+ case OPT_ssl_capath:
+ case OPT_ssl_cipher:
break;
#endif /* HAVE_OPENSSL */
- case 17: /* charset-lib */
+ case OPT_character_sets_dir:
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 18:
+ case OPT_default_character_set:
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 19: /* Interactive-timeout */
+ case OPT_interactive_timeout:
options->client_flag|= CLIENT_INTERACTIVE;
break;
- case 21:
+ case OPT_local_infile:
if (!opt_arg || atoi(opt_arg) != 0)
options->client_flag|= CLIENT_LOCAL_FILES;
else
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 22:
+ case OPT_disable_local_infile:
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 23: /* replication probe */
+ case OPT_replication_probe:
#ifndef TO_BE_DELETED
options->rpl_probe= 1;
#endif
break;
- case 24: /* enable-reads-from-master */
+ case OPT_enable_reads_from_master:
options->no_master_reads= 0;
break;
- case 25: /* repl-parse-query */
+ case OPT_repl_parse_query:
#ifndef TO_BE_DELETED
options->rpl_parse= 1;
#endif
break;
- case 27:
+ case OPT_max_allowed_packet:
if (opt_arg)
options->max_allowed_packet= atoi(opt_arg);
break;
- case 28: /* protocol */
+ case OPT_protocol:
if ((options->protocol= find_type(opt_arg,
&sql_protocol_typelib,0)) <= 0)
{
@@ -1202,26 +1226,32 @@ void mysql_read_default_options(struct s
exit(1);
}
break;
- case 29: /* shared_memory_base_name */
+ case OPT_shared_memory_base_name:
#ifdef HAVE_SMEM
if (options->shared_memory_base_name != def_shared_memory_base_name)
my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
#endif
break;
- case 30:
+ case OPT_multi_results:
options->client_flag|= CLIENT_MULTI_RESULTS;
break;
- case 31:
- case 32:
+ case OPT_multi_statements:
+ case OPT_multi_queries:
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break;
- case 33: /* secure-auth */
+ case OPT_secure_auth:
options->secure_auth= TRUE;
break;
- case 34: /* report-data-truncation */
+ case OPT_report_data_truncation:
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
break;
+ case OPT_plugin_dir:
+ extension_set_string(options, plugin_dir, opt_arg);
+ break;
+ case OPT_default_auth:
+ extension_set_string(options, default_auth, opt_arg);
+ break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -1765,6 +1795,11 @@ static int ssl_verify_server_cert(Vio *v
static my_bool cli_read_query_result(MYSQL *mysql);
static MYSQL_RES *cli_use_result(MYSQL *mysql);
+int cli_read_change_user_result(MYSQL *mysql)
+{
+ return cli_safe_read(mysql);
+}
+
static MYSQL_METHODS client_methods=
{
cli_read_query_result, /* read_query_result */
@@ -1772,7 +1807,8 @@ static MYSQL_METHODS client_methods=
cli_read_rows, /* read_rows */
cli_use_result, /* use_result */
cli_fetch_lengths, /* fetch_lengths */
- cli_flush_use_result /* flush_use_result */
+ cli_flush_use_result, /* flush_use_result */
+ cli_read_change_user_result /* read_change_user_result */
#ifndef MYSQL_SERVER
,cli_list_fields, /* list_fields */
cli_read_prepare_result, /* read_prepare_result */
@@ -1782,7 +1818,6 @@ static MYSQL_METHODS client_methods=
NULL, /* free_embedded_thd */
cli_read_statistics, /* read_statistics */
cli_read_query_result, /* next_result */
- cli_read_change_user_result, /* read_change_user_result */
cli_read_binary_rows /* read_rows_from_cursor */
#endif
};
@@ -1856,6 +1891,646 @@ int mysql_init_character_set(MYSQL *mysq
}
C_MODE_END
+/*********** client side authentication support **************************/
+
+typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
+static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+
+static auth_plugin_t native_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ native_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Native MySQL authentication",
+ {1, 0, 0},
+ NULL,
+ NULL,
+ native_password_auth_client
+};
+
+static auth_plugin_t old_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ old_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Old MySQL-3.23 authentication",
+ {1, 0, 0},
+ NULL,
+ NULL,
+ old_password_auth_client
+};
+
+struct st_mysql_client_plugin *mysql_client_builtins[]=
+{
+ (struct st_mysql_client_plugin *)&native_password_client_plugin,
+ (struct st_mysql_client_plugin *)&old_password_client_plugin,
+ 0
+};
+
+
+
+/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
+typedef struct {
+ int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
+ int (*write_packet)(struct st_plugin_vio *vio, const uchar *pkt, int pkt_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+ /* -= end of MYSQL_PLUGIN_VIO =- */
+ MYSQL *mysql;
+ auth_plugin_t *plugin; /**< what plugin we're under */
+ const char *db;
+ struct {
+ uchar *pkt; /**< pointer into NET::buff */
+ uint pkt_len;
+ } cached_server_reply;
+ uint packets_read, packets_written; /**< counters for send/received packets */
+ my_bool mysql_change_user; /**< if it's mysql_change_user() */
+ int last_read_packet_len; /**< the length of the last *read* packet */
+} MCPVIO_EXT;
+
+/**
+ sends a COM_CHANGE_USER command with a caller provided payload
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ n user name - \0-terminated string
+ n password
+ 3.23 scramble - \0-terminated string (9 bytes)
+ otherwise - length (1 byte) coded
+ n database name - \0-terminated string
+ 2 character set number (if the server >= 4.1.x)
+ n client auth plugin name - \0-terminated string,
+ (if the server supports plugin auth)
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static int send_change_user_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ char *buff, *end;
+ int res= 1;
+
+ buff= my_alloca(USERNAME_LENGTH + data_len + 1 + NAME_LEN + 2 + NAME_LEN);
+
+ end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;
+
+ if (!data_len)
+ *end++= 0;
+ else
+ {
+ if (mysql->client_flag & CLIENT_SECURE_CONNECTION)
+ {
+ DBUG_ASSERT(data_len <= 255);
+ if (data_len > 255)
+ {
+ set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+ goto error;
+ }
+ *end++= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1);
+ DBUG_ASSERT(data[SCRAMBLE_LENGTH_323] == 0);
+ }
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ end= strmake(end, mpvio->db ? mpvio->db : "", NAME_LEN) + 1;
+
+ if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
+ {
+ int2store(end, (ushort) mysql->charset->number);
+ end+= 2;
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ res= simple_command(mysql, COM_CHANGE_USER,
+ (uchar*)buff, (ulong)(end-buff), 1);
+
+error:
+ my_afree(buff);
+ return res;
+}
+
+
+/**
+ sends a client authentication packet (second packet in the 3-way handshake)
+
+ Packet format (when the server is 4.0 or earlier):
+
+ Bytes Content
+ ----- ----
+ 2 client capabilities
+ 3 max packet size
+ n user name, \0-terminated
+ 9 scramble_323, \0-terminated
+
+ Packet format (when the server is 4.1 or newer):
+
+ Bytes Content
+ ----- ----
+ 4 client capabilities
+ 4 max packet size
+ 1 charset number
+ 23 reserved (always 0)
+ n user name, \0-terminated
+ n plugin auth data (e.g. scramble), length (1 byte) coded
+ n database name, \0-terminated
+ (if CLIENT_CONNECT_WITH_DB is set in the capabilities)
+ n client auth plugin name - \0-terminated string,
+ (if CLIENT_PLUGIN_AUTH is set in the capabilities)
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static int send_client_reply_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ NET *net= &mysql->net;
+ char *buff, *end;
+
+ /* see end= buff+32 below, fixed size of the packet is 32 bytes */
+ buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN);
+
+ mysql->client_flag|= mysql->options.client_flag;
+ mysql->client_flag|= CLIENT_CAPABILITIES;
+
+ if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
+ mysql->client_flag|= CLIENT_MULTI_RESULTS;
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+ if (mysql->options.ssl_key || mysql->options.ssl_cert ||
+ mysql->options.ssl_ca || mysql->options.ssl_capath ||
+ mysql->options.ssl_cipher)
+ mysql->options.use_ssl= 1;
+ if (mysql->options.use_ssl)
+ mysql->client_flag|= CLIENT_SSL;
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
+ if (mpvio->db)
+ mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
+
+ /* Remove options that server doesn't support */
+ mysql->client_flag= mysql->client_flag &
+ (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)
+ | mysql->server_capabilities);
+
+#ifndef HAVE_COMPRESS
+ mysql->client_flag&= ~CLIENT_COMPRESS;
+#endif
+
+ if (mysql->client_flag & CLIENT_PROTOCOL_41)
+ {
+ /* 4.1 server and 4.1 client has a 32 byte option flag */
+ int4store(buff,mysql->client_flag);
+ int4store(buff+4, net->max_packet_size);
+ buff[8]= (char) mysql->charset->number;
+ bzero(buff+9, 32-9);
+ end= buff+32;
+ }
+ else
+ {
+ int2store(buff, mysql->client_flag);
+ int3store(buff+2, net->max_packet_size);
+ end= buff+5;
+ }
+#ifdef HAVE_OPENSSL
+ if (mysql->client_flag & CLIENT_SSL)
+ {
+ /* Do the SSL layering. */
+ struct st_mysql_options *options= &mysql->options;
+ struct st_VioSSLFd *ssl_fd;
+ char error_string[1024];
+
+ /*
+ Send mysql->client_flag, max_packet_size - unencrypted otherwise
+ the server does not know we want to do SSL
+ */
+ if (my_net_write(net, (uchar*)buff, (size_t) (end-buff)) || net_flush(net))
+ {
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending connection information to server",
+ errno);
+ goto error;
+ }
+
+ /* Create the VioSSLConnectorFd - init SSL and load certs */
+ if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
+ options->ssl_cert,
+ options->ssl_ca,
+ options->ssl_capath,
+ options->ssl_cipher)))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+ mysql->connector_fd= (void*)ssl_fd;
+
+ /* Connect to the server */
+ DBUG_PRINT("info", ("IO layer change in progress..."));
+ if (sslconnect(ssl_fd, net->vio,
+ (long) (mysql->options.connect_timeout),
+ error_string))
+ {
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
+ unknown_sqlstate, "SSL error: %s",
+ error_string[0] ? error_string :
+ ER(CR_SSL_CONNECTION_ERROR));
+ goto error;
+ }
+ DBUG_PRINT("info", ("IO layer change done!"));
+
+ /* Verify server cert */
+ if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
+ ssl_verify_server_cert(net->vio, mysql->host))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+ }
+#endif /* HAVE_OPENSSL */
+
+ DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
+ mysql->server_version, mysql->server_capabilities,
+ mysql->server_status, mysql->client_flag));
+
+ compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
+
+ /* This needs to be changed as it's not useful with big packets */
+ if (mysql->user[0])
+ strmake(end, mysql->user, USERNAME_LENGTH);
+ else
+ read_user_name(end);
+
+ /* We have to handle different version of handshake here */
+ DBUG_PRINT("info",("user: %s",end));
+ end= strend(end) + 1;
+ if (data_len)
+ {
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ *end++= data_len;
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ }
+ else
+ *end++= 0;
+
+ /* Add database if needed */
+ if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
+ {
+ end= strmake(end, mpvio->db, NAME_LEN) + 1;
+ mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ /* Write authentication package */
+ if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
+ {
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ goto error;
+ }
+ my_afree(buff);
+ return 0;
+
+error:
+ my_afree(buff);
+ return 1;
+}
+
+
+/**
+ vio->read_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to read data from the server.
+*/
+
+static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+ MYSQL *mysql= mpvio->mysql;
+ ulong pkt_len;
+
+ /* there are cached data left, feed it to a plugin */
+ if (mpvio->cached_server_reply.pkt)
+ {
+ *buf= mpvio->cached_server_reply.pkt;
+ mpvio->cached_server_reply.pkt= 0;
+ mpvio->packets_read++;
+ return mpvio->cached_server_reply.pkt_len;
+ }
+
+ if (mpvio->packets_read == 0)
+ {
+ /*
+ the server handshake packet came from the wrong plugin,
+ or it's mysql_change_user(). Either way, there is no data
+ for a plugin to read. send a dummy packet to the server
+ to initiate a dialog.
+ */
+ if (client_mpvio_write_packet(mpv, 0, 0))
+ return (int)packet_error;
+ }
+
+ /* otherwise read the data */
+ pkt_len= (*mysql->methods->read_change_user_result)(mysql);
+ mpvio->last_read_packet_len= pkt_len;
+ *buf= mysql->net.read_pos;
+
+ /* was it a request to change plugins ? */
+ if (**buf == 254)
+ return (int)packet_error; /* if yes, this plugin shan't continue */
+
+ /*
+ the server sends \1\255 or \1\254 instead of just \255 or \254 -
+ for us to not confuse it with an error or "change plugin" packets.
+ We remove this escaping \1 here.
+
+ See also server_mpvio_write_packet() where the escaping is done.
+ */
+ if (pkt_len && **buf == 1)
+ {
+ (*buf)++;
+ pkt_len--;
+ }
+ mpvio->packets_read++;
+ return pkt_len;
+}
+
+
+/**
+ vio->write_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to send data to the server.
+
+ It transparently wraps the data into a change user or authentication
+ handshake packet, if neccessary.
+*/
+
+static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
+ const uchar *pkt, int pkt_len)
+{
+ int res;
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+
+ if (mpvio->packets_written == 0)
+ {
+ if (mpvio->mysql_change_user)
+ res= send_change_user_packet(mpvio, pkt, pkt_len);
+ else
+ res= send_client_reply_packet(mpvio, pkt, pkt_len);
+ }
+ else
+ {
+ NET *net= &mpvio->mysql->net;
+ if (mpvio->mysql->thd)
+ res= 1; /* no chit-chat in embedded */
+ else
+ res= my_net_write(net, pkt, pkt_len) || net_flush(net);
+ if (res)
+ set_mysql_extended_error(mpvio->mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
+{
+ bzero(info, sizeof(*info));
+ switch (vio->type) {
+ case VIO_TYPE_TCPIP:
+ info->protocol= MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ case VIO_TYPE_SOCKET:
+ info->protocol= MYSQL_VIO_SOCKET;
+ info->socket= vio->sd;
+ return;
+ case VIO_TYPE_SSL:
+ {
+ struct sockaddr addr;
+ socklen_t addrlen= sizeof(addr);
+ if (getsockname(vio->sd, &addr, &addrlen))
+ return;
+ info->protocol= addr.sa_family == AF_UNIX ?
+ MYSQL_VIO_SOCKET : MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ }
+#ifdef _WIN32
+ case VIO_TYPE_NAMEDPIPE:
+ info->protocol= MYSQL_VIO_PIPE;
+ info->handle= vio->hPipe;
+ return;
+ case VIO_TYPE_SHARED_MEMORY:
+ info->protocol= MYSQL_VIO_MEMORY;
+ info->handle= vio->handle_client_file_map; /* or what ? */
+ return;
+#endif
+ default: DBUG_ASSERT(0);
+ }
+}
+
+
+static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)vio;
+ mpvio_info(mpvio->mysql->net.vio, info);
+}
+
+
+/**
+ Client side of the plugin driver authentication.
+
+ @note this is used by both the mysql_real_connect and mysql_change_user
+
+ @param mysql mysql
+ @param data pointer to the plugin auth data (scramble) in the
+ handshake packet
+ @param data_len the length of the data
+ @param data_plugin a plugin that data were prepared for
+ or 0 if it's mysql_change_user()
+ @param db initial db to use, can be 0
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ char *data_plugin, const char *db)
+{
+ const char *auth_plugin_name;
+ auth_plugin_t *auth_plugin;
+ MCPVIO_EXT mpvio;
+ ulong pkt_length;
+ int res;
+
+ /* determine the default/initial plugin to use */
+ if (mysql->options.extension && mysql->options.extension->default_auth &&
+ mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ auth_plugin_name= mysql->options.extension->default_auth;
+ if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ return 1; /* oops, not found */
+ }
+ else
+ {
+ auth_plugin= mysql->server_capabilities & CLIENT_PROTOCOL_41 ?
+ &native_password_client_plugin : &old_password_client_plugin;
+ auth_plugin_name= auth_plugin->name;
+ }
+
+ mysql->net.last_errno= 0; /* just in case */
+
+ if (data_plugin && strcmp(data_plugin, auth_plugin_name))
+ {
+ /* data was prepared for a different plugin, don't show it to this one */
+ data= 0;
+ data_len= 0;
+ }
+
+ mpvio.mysql_change_user= data_plugin == 0;
+ mpvio.cached_server_reply.pkt= (uchar*)data;
+ mpvio.cached_server_reply.pkt_len= data_len;
+ mpvio.read_packet= client_mpvio_read_packet;
+ mpvio.write_packet= client_mpvio_write_packet;
+ mpvio.info= client_mpvio_info;
+ mpvio.mysql= mysql;
+ mpvio.packets_read= mpvio.packets_written= 0;
+ mpvio.db= db;
+ mpvio.plugin= auth_plugin;
+
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ compile_time_assert(CR_OK == -1);
+ compile_time_assert(CR_ERROR == 0);
+ if (res > CR_OK && mysql->net.read_pos[0] != 254)
+ {
+ /*
+ the plugin returned an error. write it down in mysql,
+ unless the error code is CR_ERROR and mysql->net.last_errno
+ is already set (the plugin has done it)
+ */
+ if (res > CR_ERROR)
+ set_mysql_error(mysql, res, unknown_sqlstate);
+ else
+ if (!mysql->net.last_errno)
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return 1;
+ }
+
+ /* read the OK packet (or use the cached value in mysql->net.read_pos */
+ if (res == CR_OK)
+ pkt_length= (*mysql->methods->read_change_user_result)(mysql);
+ else /* res == CR_OK_HANDSHAKE_COMPLETE */
+ pkt_length= mpvio.last_read_packet_len;
+
+ if (pkt_length == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading authorization packet",
+ errno);
+ return 1;
+ }
+
+ if (mysql->net.read_pos[0] == 254)
+ {
+ /* The server asked to use a different authentication plugin */
+ if (pkt_length == 1)
+ {
+ /* old "use short scramble" packet */
+ auth_plugin_name= old_password_plugin_name;
+ mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble;
+ mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* new "use different plugin" packet */
+ uint len;
+ auth_plugin_name= (char*)mysql->net.read_pos + 1;
+ len= strlen(auth_plugin_name); /* safe as my_net_read always appends \0 */
+ mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
+ mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
+ }
+
+ if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ return 1;
+
+ mpvio.plugin= auth_plugin;
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ if (res > CR_OK)
+ {
+ if (res > CR_ERROR)
+ set_mysql_error(mysql, res, unknown_sqlstate);
+ else
+ if (!mysql->net.last_errno)
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return 1;
+ }
+
+ if (res != CR_OK_HANDSHAKE_COMPLETE)
+ {
+ /* Read what server thinks about out new auth message report */
+ if (cli_safe_read(mysql) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading final connect information",
+ errno);
+ return 1;
+ }
+ }
+ }
+ /*
+ net->read_pos[0] should always be 0 here if the server implements
+ the protocol correctly
+ */
+ return mysql->net.read_pos[0] != 0;
+}
+
MYSQL * STDCALL
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
@@ -1863,8 +2538,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100];
- char error_string[1024];
- char *end,*host_info= NULL;
+ int scramble_data_len, pkt_scramble_len;
+ char *end, *host_info=0, *server_version_end, *pkt_end;
+ char *scramble_data, *scramble_plugin;
my_socket sock;
in_addr_t ip_addr;
struct sockaddr_in sock_addr;
@@ -2180,8 +2856,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
errno);
goto error;
}
+ pkt_end= (char*)net->read_pos + pkt_length;
/* Check if version of protocol matches current one */
-
mysql->protocol_version= net->read_pos[0];
DBUG_DUMP("packet",(uchar*) net->read_pos,10);
DBUG_PRINT("info",("mysql protocol version %d, server=%d",
@@ -2193,31 +2869,29 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
PROTOCOL_VERSION);
goto error;
}
- end=strend((char*) net->read_pos+1);
+ server_version_end= end= strend((char*) net->read_pos+1);
mysql->thread_id=uint4korr(end+1);
end+=5;
/*
- Scramble is split into two parts because old clients does not understand
+ Scramble is split into two parts because old clients do not understand
long scrambles; here goes the first part.
*/
- strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
- end+= SCRAMBLE_LENGTH_323+1;
+ scramble_data= end;
+ scramble_data_len= SCRAMBLE_LENGTH_323 + 1;
+ scramble_plugin= old_password_plugin_name;
+ end+= scramble_data_len;
- if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
+ if (pkt_end >= end + 1)
mysql->server_capabilities=uint2korr(end);
- if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
+ if (pkt_end >= end + 18)
{
/* New protocol with 16 bytes to describe server characteristics */
mysql->server_language=end[2];
mysql->server_status=uint2korr(end+3);
+ mysql->server_capabilities|= uint2korr(end+5) << 16;
+ pkt_scramble_len= end[7];
}
end+= 18;
- if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
- (char *) net->read_pos))
- strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
- SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
- else
- mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
if (mysql->options.secure_auth && passwd[0] &&
!(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
@@ -2236,7 +2910,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
&mysql->unix_socket,unix_socket ?
(uint) strlen(unix_socket)+1 : (uint) 1,
&mysql->server_version,
- (uint) (end - (char*) net->read_pos),
+ (uint) (server_version_end - (char*) net->read_pos + 1),
NullS) ||
!(mysql->user=my_strdup(user,MYF(0))) ||
!(mysql->passwd=my_strdup(passwd,MYF(0))))
@@ -2253,203 +2927,47 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port;
- /*
- Part 2: format and send client info to the server for access check
- */
-
- client_flag|=mysql->options.client_flag;
- client_flag|=CLIENT_CAPABILITIES;
- if (client_flag & CLIENT_MULTI_STATEMENTS)
- client_flag|= CLIENT_MULTI_RESULTS;
-
-#ifdef HAVE_OPENSSL
- if (mysql->options.ssl_key || mysql->options.ssl_cert ||
- mysql->options.ssl_ca || mysql->options.ssl_capath ||
- mysql->options.ssl_cipher)
- mysql->options.use_ssl= 1;
- if (mysql->options.use_ssl)
- client_flag|=CLIENT_SSL;
-#endif /* HAVE_OPENSSL */
- if (db)
- client_flag|=CLIENT_CONNECT_WITH_DB;
-
- /* Remove options that server doesn't support */
- client_flag= ((client_flag &
- ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
- (client_flag & mysql->server_capabilities));
-#ifndef HAVE_COMPRESS
- client_flag&= ~CLIENT_COMPRESS;
-#endif
-
- if (client_flag & CLIENT_PROTOCOL_41)
- {
- /* 4.1 server and 4.1 client has a 32 byte option flag */
- int4store(buff,client_flag);
- int4store(buff+4, net->max_packet_size);
- buff[8]= (char) mysql->charset->number;
- bzero(buff+9, 32-9);
- end= buff+32;
- }
- else
- {
- int2store(buff,client_flag);
- int3store(buff+2,net->max_packet_size);
- end= buff+5;
- }
- mysql->client_flag=client_flag;
-
-#ifdef HAVE_OPENSSL
- if (client_flag & CLIENT_SSL)
+ if (pkt_end >= end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1)
{
- /* Do the SSL layering. */
- struct st_mysql_options *options= &mysql->options;
- struct st_VioSSLFd *ssl_fd;
-
/*
- Send client_flag, max_packet_size - unencrypted otherwise
- the server does not know we want to do SSL
+ move the first scramble part - directly in the NET buffer -
+ to get a full continuous scramble. We've read all the header,
+ and can overwrite it now.
*/
- if (my_net_write(net, (uchar*) buff, (uint) (end-buff)) || net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending connection information to server",
- errno);
- goto error;
- }
-
- /* Create the VioSSLConnectorFd - init SSL and load certs */
- if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
- options->ssl_cert,
- options->ssl_ca,
- options->ssl_capath,
- options->ssl_cipher)))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
- goto error;
- }
- mysql->connector_fd= (void*)ssl_fd;
-
- /* Connect to the server */
- DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslconnect(ssl_fd, mysql->net.vio,
- (long) (mysql->options.connect_timeout),
- error_string))
- {
- set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
- unknown_sqlstate,
- "SSL error: %s",
- error_string[0] ? error_string :
- ER(CR_SSL_CONNECTION_ERROR));
- goto error;
- }
- DBUG_PRINT("info", ("IO layer change done!"));
-
- /* Verify server cert */
- if ((client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
- ssl_verify_server_cert(mysql->net.vio, mysql->host))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
- goto error;
- }
-
- }
-#endif /* HAVE_OPENSSL */
-
- DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
- mysql->server_version,mysql->server_capabilities,
- mysql->server_status, client_flag));
- /* This needs to be changed as it's not useful with big packets */
- if (user && user[0])
- strmake(end,user,USERNAME_LENGTH); /* Max user name */
- else
- read_user_name((char*) end);
-
- /* We have to handle different version of handshake here */
-#ifdef _CUSTOMCONFIG_
-#include "_cust_libmysql.h"
-#endif
- DBUG_PRINT("info",("user: %s",end));
- end= strend(end) + 1;
- if (passwd[0])
- {
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- *end++= SCRAMBLE_LENGTH;
- scramble(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH;
+ memmove(end - SCRAMBLE_LENGTH_323, scramble_data,
+ SCRAMBLE_LENGTH_323);
+ scramble_data= end - SCRAMBLE_LENGTH_323;
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ scramble_data_len= pkt_scramble_len;
+ scramble_plugin= scramble_data + scramble_data_len;
+ if (scramble_data + scramble_data_len > pkt_end)
+ scramble_data_len= pkt_end - scramble_data;
}
else
{
- scramble_323(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH_323 + 1;
+ scramble_data_len= pkt_end - scramble_data;
+ scramble_plugin= native_password_plugin_name;
}
}
else
- *end++= '\0'; /* empty password */
+ mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
+
+ mysql->client_flag= client_flag;
- /* Add database if needed */
- if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
- {
- end= strmake(end, db, NAME_LEN) + 1;
- mysql->db= my_strdup(db,MYF(MY_WME));
- db= 0;
- }
- /* Write authentication package */
- if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending authentication information",
- errno);
- goto error;
- }
-
/*
- Part 3: Authorization data's been sent. Now server can reply with
- OK-packet, or re-request scrambled password.
+ Part 2: invoke the plugin to send the authentication data to the server
*/
- if ((pkt_length=cli_safe_read(mysql)) == packet_error)
- {
- if (mysql->net.last_errno == CR_SERVER_LOST)
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "reading authorization packet",
- errno);
+ if (run_plugin_auth(mysql, scramble_data, scramble_data_len,
+ scramble_plugin, db))
goto error;
- }
- if (pkt_length == 1 && net->read_pos[0] == 254 &&
- mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- By sending this very specific reply server asks us to send scrambled
- password in old format.
- */
- scramble_323(buff, mysql->scramble, passwd);
- if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending password information",
- errno);
- goto error;
- }
- /* Read what server thinks about out new auth message report */
- if (cli_safe_read(mysql) == packet_error)
- {
- if (mysql->net.last_errno == CR_SERVER_LOST)
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "reading final connect information",
- errno);
- goto error;
- }
- }
+ /*
+ Part 3: authenticated, finish the initialization of the connection
+ */
- if (client_flag & CLIENT_COMPRESS) /* We will use compression */
+ if (mysql->client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
#ifdef CHECK_LICENSE
@@ -2457,7 +2975,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
goto error;
#endif
- if (db && mysql_select_db(mysql, db))
+ if (db && !mysql->db && mysql_select_db(mysql, db))
{
if (mysql->net.last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
@@ -2510,7 +3028,7 @@ error:
/* Free alloced memory */
end_server(mysql);
mysql_close_free(mysql);
- if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
+ if (!(client_flag & CLIENT_REMEMBER_OPTIONS))
mysql_close_free_options(mysql);
}
DBUG_RETURN(0);
@@ -2655,6 +3173,12 @@ static void mysql_close_free_options(MYS
if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif /* HAVE_SMEM */
+ if (mysql->options.extension)
+ {
+ my_free(mysql->options.extension->plugin_dir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.extension->default_auth,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.extension,MYF(0));
+ }
bzero((char*) &mysql->options,sizeof(mysql->options));
DBUG_VOID_RETURN;
}
@@ -3185,6 +3709,12 @@ mysql_options(MYSQL *mysql,enum mysql_op
else
mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
break;
+ case MYSQL_PLUGIN_DIR:
+ extension_set_string(&mysql->options, plugin_dir, arg);
+ break;
+ case MYSQL_DEFAULT_AUTH:
+ extension_set_string(&mysql->options, default_auth, arg);
+ break;
default:
DBUG_RETURN(1);
}
@@ -3293,3 +3823,99 @@ int STDCALL mysql_set_character_set(MYSQ
}
+/**
+ client authentication plugin that does native MySQL authentication
+ using a 20-byte (4.1+) scramble
+*/
+
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ int pkt_len;
+ uchar *pkt;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble;
+ pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
+ mysql->scramble[SCRAMBLE_LENGTH] = 0;
+ }
+
+ if (mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH + 1];
+ scramble(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
+
+/**
+ client authentication plugin that does old MySQL authentication
+ using an 8-byte (4.0-) scramble
+*/
+
+static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ uchar *pkt;
+ int pkt_len;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble;
+ pkt_len= SCRAMBLE_LENGTH_323 + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH_323 + 1 &&
+ pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memcpy(mysql->scramble, pkt, pkt_len);
+ mysql->scramble[pkt_len] = 0;
+ }
+
+ if (mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH_323 + 1];
+ scramble_323(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH_323 + 1))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
=== added file 'sql-common/client_plugin.c'
--- a/sql-common/client_plugin.c 1970-01-01 00:00:00 +0000
+++ b/sql-common/client_plugin.c 2010-03-29 15:13:53 +0000
@@ -0,0 +1,436 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+
+ Support code for the client side (libmysql) plugins
+
+ Client plugins are somewhat different from server plugins, they are simpler.
+
+ They do not need to be installed or in any way explicitly loaded on the
+ client, they are loaded automatically on demand.
+ One client plugin per shared object, soname *must* match the plugin name.
+
+ There is no reference counting and no unloading either.
+*/
+
+#include <my_global.h>
+#include "mysql.h"
+#include <my_sys.h>
+#include <m_string.h>
+#ifdef THREAD
+#include <my_pthread.h>
+#else
+#include <my_no_pthread.h>
+#endif
+
+#include <sql_common.h>
+#include "errmsg.h"
+#include <mysql/client_plugin.h>
+
+struct st_client_plugin_int {
+ struct st_client_plugin_int *next;
+ void *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+};
+
+static my_bool initialized= 0;
+static MEM_ROOT mem_root;
+
+static const char *plugin_declarations_sym= "_mysql_client_plugin_declaration_";
+static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]=
+{
+ 0, /* these two are taken by Connector/C */
+ 0, /* these two are taken by Connector/C */
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION
+};
+
+/*
+ Loaded plugins are stored in a linked list.
+ The list is append-only, the elements are added to the head (like in a stack).
+ The elements are added under a mutex, but the list can be read and traversed
+ without any mutex because once an element is added to the list, it stays
+ there. The main purpose of a mutex is to prevent two threads from
+ loading the same plugin twice in parallel.
+*/
+struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS];
+#ifdef THREAD
+static pthread_mutex_t LOCK_load_client_plugin;
+#endif
+
+static int is_not_initialized(MYSQL *mysql, const char *name)
+{
+ if (initialized)
+ return 0;
+
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ name, "not initialized");
+ return 1;
+}
+
+
+/**
+ finds a plugin in the list
+
+ @param name plugin name to search for
+ @param type plugin type
+
+ @note this does NOT necessarily need a mutex, take care!
+
+ @retval a pointer to a found plugin or 0
+*/
+
+static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
+{
+ struct st_client_plugin_int *p;
+
+ DBUG_ASSERT(initialized);
+ DBUG_ASSERT(type >= 0 && type < MYSQL_CLIENT_MAX_PLUGINS);
+ if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
+ return 0;
+
+ for (p= plugin_list[type]; p; p= p->next)
+ {
+ if (strcmp(p->plugin->name, name) == 0)
+ return p->plugin;
+ }
+ return NULL;
+}
+
+
+/**
+ verifies the plugin and adds it to the list
+
+ @param mysql MYSQL structure (for error reporting)
+ @param plugin plugin to install
+ @param dlhandle a handle to the shared object (returned by dlopen)
+ or 0 if the plugin was not dynamically loaded
+ @param argc number of arguments in the 'va_list args'
+ @param args arguments passed to the plugin initialization function
+
+ @retval a pointer to an installed plugin or 0
+*/
+
+static struct st_mysql_client_plugin *
+add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ struct st_client_plugin_int plugin_int, *p;
+ char errbuf[1024];
+
+ DBUG_ASSERT(initialized);
+
+ plugin_int.plugin= plugin;
+ plugin_int.dlhandle= dlhandle;
+
+ if (plugin->type >= MYSQL_CLIENT_MAX_PLUGINS)
+ {
+ errmsg= "Unknown client plugin type";
+ goto err1;
+ }
+
+ if (plugin->interface_version < plugin_version[plugin->type] ||
+ (plugin->interface_version >> 8) >
+ (plugin_version[plugin->type] >> 8))
+ {
+ errmsg= "Incompatible client plugin interface";
+ goto err1;
+ }
+
+ /* Call the plugin initialization function, if any */
+ if (plugin->init && plugin->init(errbuf, sizeof(errbuf), argc, args))
+ {
+ errmsg= errbuf;
+ goto err1;
+ }
+
+ p= (struct st_client_plugin_int *)
+ memdup_root(&mem_root, &plugin_int, sizeof(plugin_int));
+
+ if (!p)
+ {
+ errmsg= "Out of memory";
+ goto err2;
+ }
+
+ safe_mutex_assert_owner(&LOCK_load_client_plugin);
+
+ p->next= plugin_list[plugin->type];
+ plugin_list[plugin->type]= p;
+
+ return plugin;
+
+err2:
+ if (plugin->deinit)
+ plugin->deinit();
+err1:
+ if (dlhandle)
+ dlclose(dlhandle);
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name,
+ errmsg);
+ return NULL;
+}
+
+
+/**
+ Loads plugins which are specified in the environment variable
+ LIBMYSQL_PLUGINS.
+
+ Multiple plugins must be separated by semicolon. This function doesn't
+ return or log an error.
+
+ The function is be called by mysql_client_plugin_init
+
+ @todo
+ Support extended syntax, passing parameters to plugins, for example
+ LIBMYSQL_PLUGINS="plugin1(param1,param2);plugin2;..."
+ or
+ LIBMYSQL_PLUGINS="plugin1=int:param1,str:param2;plugin2;..."
+*/
+
+static void load_env_plugins(MYSQL *mysql)
+{
+ char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
+
+ /* no plugins to load */
+ if (!s)
+ return;
+
+ free_env= plugs= my_strdup(s, MYF(MY_WME));
+
+ do {
+ if ((s= strchr(plugs, ';')))
+ *s= '\0';
+ mysql_load_plugin(mysql, plugs, -1, 0);
+ plugs= s + 1;
+ } while (s);
+
+ my_free(free_env, MYF(0));
+}
+
+/********** extern functions to be used by libmysql *********************/
+
+/**
+ Initializes the client plugin layer.
+
+ This function must be called before any other client plugin function.
+
+ @retval 0 successful
+ @retval != 0 error occured
+*/
+
+int mysql_client_plugin_init()
+{
+ MYSQL mysql;
+ struct st_mysql_client_plugin **builtin;
+
+ if (initialized)
+ return 0;
+
+ bzero(&mysql, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
+
+ pthread_mutex_init(&LOCK_load_client_plugin, MY_MUTEX_INIT_SLOW);
+ init_alloc_root(&mem_root, 128, 128);
+
+ bzero(&plugin_list, sizeof(plugin_list));
+
+ initialized= 1;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ for (builtin= mysql_client_builtins; *builtin; builtin++)
+ add_plugin(&mysql, *builtin, 0, 0, 0);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ load_env_plugins(&mysql);
+
+ return 0;
+}
+
+
+/**
+ Deinitializes the client plugin layer.
+
+ Unloades all client plugins and frees any associated resources.
+*/
+
+void mysql_client_plugin_deinit()
+{
+ int i;
+ struct st_client_plugin_int *p;
+
+ if (!initialized)
+ return;
+
+ for (i=0; i < MYSQL_CLIENT_MAX_PLUGINS; i++)
+ for (p= plugin_list[i]; p; p= p->next)
+ {
+ if (p->plugin->deinit)
+ p->plugin->deinit();
+ if (p->dlhandle)
+ dlclose(p->dlhandle);
+ }
+
+ bzero(&plugin_list, sizeof(plugin_list));
+ initialized= 0;
+ free_root(&mem_root, MYF(0));
+ pthread_mutex_destroy(&LOCK_load_client_plugin);
+}
+
+/************* public facing functions, for client consumption *********/
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(MYSQL *mysql,
+ struct st_mysql_client_plugin *plugin)
+{
+ if (is_not_initialized(mysql, plugin->name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (find_plugin(plugin->name, plugin->type))
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ plugin->name, "it is already loaded");
+ plugin= NULL;
+ }
+ else
+ plugin= add_plugin(mysql, plugin, 0, 0, 0);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ return plugin;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ char dlpath[FN_REFLEN+1];
+ void *sym, *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (type >= 0 && find_plugin(name, type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ /* Compile dll path */
+ strxnmov(dlpath, sizeof(dlpath) - 1,
+ mysql->options.extension && mysql->options.extension->plugin_dir ?
+ mysql->options.extension->plugin_dir : PLUGINDIR, "/",
+ name, SO_EXT, NullS);
+
+ /* Open new dll handle */
+ if (!(dlhandle= dlopen(dlpath, RTLD_NOW)))
+ {
+ errmsg= dlerror();
+ goto err;
+ }
+
+ if (!(sym= dlsym(dlhandle, plugin_declarations_sym)))
+ {
+ errmsg= "not a plugin";
+ dlclose(dlhandle);
+ goto err;
+ }
+
+ plugin= (struct st_mysql_client_plugin*)sym;
+
+ if (type >=0 && type != plugin->type)
+ {
+ errmsg= "type mismatch";
+ goto err;
+ }
+
+ if (strcmp(name, plugin->name))
+ {
+ errmsg= "name mismatch";
+ goto err;
+ }
+
+ if (type < 0 && find_plugin(name, plugin->type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ plugin= add_plugin(mysql, plugin, dlhandle, argc, args);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ return plugin;
+
+err:
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, errmsg);
+ return NULL;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_load_plugin(MYSQL *mysql, const char *name, int type, int argc, ...)
+{
+ struct st_mysql_client_plugin *p;
+ va_list args;
+ va_start(args, argc);
+ p= mysql_load_plugin_v(mysql, name, type, argc, args);
+ va_end(args);
+ return p;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
+{
+ struct st_mysql_client_plugin *p;
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name,
+ "invalid type");
+ }
+
+ if ((p= find_plugin(name, type)))
+ return p;
+
+ /* not found, load it */
+ return mysql_load_plugin(mysql, name, type, 0);
+}
+
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2010-03-03 14:44:14 +0000
+++ b/sql/CMakeLists.txt 2010-03-29 15:13:53 +0000
@@ -54,7 +54,7 @@ SET (SQL_SOURCE
log_event.cc rpl_record.cc rpl_reporting.cc
log_event_old.cc rpl_record_old.cc
message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c
- mysqld.cc net_serv.cc
+ mysqld.cc net_serv.cc ../sql-common/client_plugin.c
nt_servc.cc nt_servc.h opt_range.cc opt_range.h opt_sum.cc
../sql-common/pack.c parse_file.cc password.c procedure.cc
protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2010-03-03 14:44:14 +0000
+++ b/sql/Makefile.am 2010-03-29 15:13:53 +0000
@@ -126,7 +126,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.
sql_servers.cc event_parse_data.cc \
opt_table_elimination.cc
-nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
+nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c client_plugin.c
libndb_la_CPPFLAGS= @ndbcluster_includes@
libndb_la_SOURCES= ha_ndbcluster.cc \
@@ -140,10 +140,10 @@ mysql_tzinfo_to_sql_SOURCES = tztime.cc
mysql_tzinfo_to_sql_CXXFLAGS= -DTZINFO2SQL
DEFS = -DMYSQL_SERVER \
- -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
- -DPLUGINDIR="\"$(pkgplugindir)\"" \
+ -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' \
+ -DPLUGINDIR='"$(pkgplugindir)"' \
-DHAVE_EVENT_SCHEDULER \
@DEFS@
@@ -167,6 +167,8 @@ link_sources:
@LN_CP_F@ $(top_srcdir)/sql-common/pack.c pack.c
rm -f client.c
@LN_CP_F@ $(top_srcdir)/sql-common/client.c client.c
+ rm -f client_plugin.c
+ @LN_CP_F@ $(top_srcdir)/sql-common/client_plugin.c client_plugin.c
rm -f my_time.c
@LN_CP_F@ $(top_srcdir)/sql-common/my_time.c my_time.c
rm -f my_user.c
=== modified file 'sql/client_settings.h'
--- a/sql/client_settings.h 2009-08-13 20:07:20 +0000
+++ b/sql/client_settings.h 2010-03-29 15:13:53 +0000
@@ -15,6 +15,7 @@
#include <thr_alarm.h>
+#include <sql_common.h>
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_SECURE_CONNECTION | CLIENT_TRANSACTIONS | \
@@ -31,7 +32,8 @@
#undef HAVE_SMEM
#undef _CUSTOMCONFIG_
-#define mysql_server_init(a,b,c) 0
+#define mysql_server_init(a,b,c) mysql_client_plugin_init()
+#define mysql_server_end() mysql_client_plugin_deinit()
#ifdef HAVE_REPLICATION
C_MODE_START
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-01-06 21:27:53 +0000
+++ b/sql/ha_ndbcluster.cc 2010-03-29 15:13:53 +0000
@@ -9185,7 +9185,7 @@ pthread_handler_t ndb_util_thread_func(v
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
thd->main_security_ctx.master_access= ~0;
- thd->main_security_ctx.priv_user = 0;
+ thd->main_security_ctx.priv_user[0] = 0;
CHARSET_INFO *charset_connection;
charset_connection= get_charset_by_csname("utf8",
=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc 2009-12-03 11:19:05 +0000
+++ b/sql/ha_ndbcluster_binlog.cc 2010-03-29 15:13:53 +0000
@@ -3681,7 +3681,7 @@ pthread_handler_t ndb_binlog_thread_func
thd->client_capabilities= 0;
my_net_init(&thd->net, 0);
thd->main_security_ctx.master_access= ~0;
- thd->main_security_ctx.priv_user= 0;
+ thd->main_security_ctx.priv_user[0]= 0;
/*
Set up ndb binlog
=== modified file 'sql/lex.h'
--- a/sql/lex.h 2009-11-12 04:31:28 +0000
+++ b/sql/lex.h 2010-03-29 15:13:53 +0000
@@ -590,6 +590,7 @@ static SYMBOL symbols[] = {
{ "VARCHARACTER", SYM(VARCHAR)},
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
+ { "VIA", SYM(VIA_SYM)},
{ "VIEW", SYM(VIEW_SYM)},
{ "VIRTUAL", SYM(VIRTUAL_SYM)},
{ "WAIT", SYM(WAIT_SYM)},
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2010-03-15 11:51:23 +0000
+++ b/sql/mysql_priv.h 2010-03-29 15:13:53 +0000
@@ -1067,9 +1067,6 @@ int write_bin_log(THD *thd, bool clear_e
char const *query, ulong query_length);
/* sql_connect.cc */
-int check_user(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count);
pthread_handler_t handle_one_connection(void *arg);
bool init_new_connection_handler_thread();
void reset_mqh(LEX_USER *lu, bool get_them);
@@ -1082,6 +1079,9 @@ bool login_connection(THD *thd);
void end_connection(THD *thd);
void prepare_new_connection_state(THD* thd);
void update_global_user_stats(THD* thd, bool create_user, time_t now);
+int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host, USER_RESOURCES *mqh);
+int check_for_max_user_connections(THD *thd, USER_CONN *uc);
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-03-29 21:16:12 +0000
+++ b/sql/mysqld.cc 2010-03-31 23:03:57 +0000
@@ -22,6 +22,7 @@
#include "rpl_mi.h"
#include "sql_repl.h"
#include "rpl_filter.h"
+#include "client_settings.h"
#include "repl_failsafe.h"
#include <my_stacktrace.h>
#include "mysqld_suffix.h"
@@ -1394,6 +1395,7 @@ void clean_up(bool print_message)
if (print_message && errmesg && server_start_time)
sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
thread_scheduler.end();
+ mysql_library_end();
finish_client_errs();
my_free((uchar*) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
@@ -3489,6 +3491,7 @@ static int init_common_variables(const c
if (init_errmessage()) /* Read error messages from file */
return 1;
init_client_errs();
+ mysql_library_init(never,never,never); /* for replication */
lex_init();
if (item_create_init())
return 1;
=== modified file 'sql/password.c'
--- a/sql/password.c 2009-09-07 20:50:10 +0000
+++ b/sql/password.c 2010-03-29 15:13:53 +0000
@@ -193,13 +193,13 @@ void scramble_323(char *to, const char *
*/
my_bool
-check_scramble_323(const char *scrambled, const char *message,
+check_scramble_323(const unsigned char *scrambled, const char *message,
ulong *hash_pass)
{
struct my_rnd_struct rand_st;
ulong hash_message[2];
- char buff[16],*to,extra; /* Big enough for check */
- const char *pos;
+ uchar buff[16],*to,extra; /* Big enough for check */
+ const uchar *pos;
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
my_rnd_init(&rand_st,hash_pass[0] ^ hash_message[0],
@@ -214,7 +214,7 @@ check_scramble_323(const char *scrambled
to=buff;
while (*scrambled)
{
- if (*scrambled++ != (char) (*to++ ^ extra))
+ if (*scrambled++ != (uchar) (*to++ ^ extra))
return 1; /* Wrong password */
}
return 0;
@@ -481,7 +481,7 @@ scramble(char *to, const char *message,
*/
my_bool
-check_scramble(const char *scramble_arg, const char *message,
+check_scramble(const uchar *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
SHA1_CONTEXT sha1_context;
@@ -494,7 +494,7 @@ check_scramble(const char *scramble_arg,
mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
mysql_sha1_result(&sha1_context, buf);
/* encrypt scramble */
- my_crypt((char *) buf, buf, (const uchar *) scramble_arg, SCRAMBLE_LENGTH);
+ my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
mysql_sha1_reset(&sha1_context);
mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2009-12-03 11:19:05 +0000
+++ b/sql/protocol.cc 2010-03-29 15:13:53 +0000
@@ -341,24 +341,6 @@ static bool write_eof_packet(THD *thd, N
}
/**
- Please client to send scrambled_password in old format.
-
- @param thd thread handle
-
- @retval
- 0 ok
- @retval
- !0 error
-*/
-
-bool send_old_password_request(THD *thd)
-{
- NET *net= &thd->net;
- return my_net_write(net, eof_buff, 1) || net_flush(net);
-}
-
-
-/**
@param thd Thread handler
@param sql_errno The error code to send
@param err A pointer to the error message
=== modified file 'sql/protocol.h'
--- a/sql/protocol.h 2009-12-03 11:19:05 +0000
+++ b/sql/protocol.h 2010-03-29 15:13:53 +0000
@@ -177,7 +177,6 @@ public:
void send_warning(THD *thd, uint sql_errno, const char *err=0);
bool net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
void net_end_statement(THD *thd);
-bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
uchar *net_store_data(uchar *to,int32 from);
uchar *net_store_data(uchar *to,longlong from);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_acl.cc 2010-03-31 18:37:45 +0000
@@ -30,6 +30,8 @@
#include <stdarg.h>
#include "sp_head.h"
#include "sp.h"
+#include <sql_common.h>
+#include <mysql/plugin_auth.h>
static const
TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
@@ -148,6 +150,87 @@ TABLE_FIELD_TYPE mysql_db_table_fields[M
const TABLE_FIELD_DEF
mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields};
+static LEX_STRING native_password_plugin_name= {
+ C_STRING_WITH_LEN("mysql_native_password")
+};
+
+static LEX_STRING old_password_plugin_name= {
+ C_STRING_WITH_LEN("mysql_old_password")
+};
+
+/// @todo make it configurable
+LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
+
+static plugin_ref native_password_plugin;
+#ifndef EMBEDDED_LIBRARY
+static plugin_ref old_password_plugin;
+#endif
+
+/* Classes */
+
+struct acl_host_and_ip
+{
+ char *hostname;
+ long ip,ip_mask; // Used with masked ip:s
+};
+
+class ACL_ACCESS {
+public:
+ ulong sort;
+ ulong access;
+};
+
+/* ACL_HOST is used if no host is specified */
+
+class ACL_HOST :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *db;
+};
+
+class ACL_USER :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ uint hostname_length;
+ USER_RESOURCES user_resource;
+ char *user;
+ uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
+ uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 4.0, 20 - 4.1.1
+ enum SSL_type ssl_type;
+ const char *ssl_cipher, *x509_issuer, *x509_subject;
+ LEX_STRING plugin;
+ LEX_STRING auth_string;
+
+ ACL_USER *copy(MEM_ROOT *root)
+ {
+ ACL_USER *dst= (ACL_USER *)alloc_root(root, sizeof(ACL_USER));
+ if (!dst)
+ return 0;
+ *dst= *this;
+ dst->user= safe_strdup_root(root, user);
+ dst->ssl_cipher= safe_strdup_root(root, ssl_cipher);
+ dst->x509_issuer= safe_strdup_root(root, x509_issuer);
+ dst->x509_subject= safe_strdup_root(root, x509_subject);
+ if (plugin.str == native_password_plugin_name.str ||
+ plugin.str == old_password_plugin_name.str)
+ dst->plugin= plugin;
+ else
+ dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
+ dst->auth_string.str = safe_strdup_root(root, auth_string.str);
+ dst->host.hostname= safe_strdup_root(root, host.hostname);
+ return dst;
+ }
+};
+
+class ACL_DB :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *user,*db;
+};
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#define FIRST_NON_YN_FIELD 26
@@ -171,6 +254,24 @@ static uchar* acl_entry_get_key(acl_entr
#define IP_ADDR_STRLEN (3+1+3+1+3+1+3)
#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1)
+#if defined(HAVE_OPENSSL)
+/*
+ Without SSL the handshake consists of one packet. This packet
+ has both client capabilites and scrambled password.
+ With SSL the handshake might consist of two packets. If the first
+ packet (client capabilities) has CLIENT_SSL flag set, we have to
+ switch to SSL and read the second packet. The scrambled password
+ is in the second packet and client_capabilites field will be ignored.
+ Maybe it is better to accept flags other than CLIENT_SSL from the
+ second packet?
+*/
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
+#else
+#define MIN_HANDSHAKE_SIZE 6
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
+
static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
static bool initialized=0;
@@ -265,6 +366,19 @@ my_bool acl_init(bool dont_read_acl_tabl
(hash_get_key) acl_entry_get_key,
(hash_free_key) free,
&my_charset_utf8_bin);
+
+ /*
+ cache built-in native authentication plugins,
+ to avoid hash searches and a global mutex lock on every connect
+ */
+ native_password_plugin= my_plugin_lock_by_name(0,
+ &native_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
+ old_password_plugin= my_plugin_lock_by_name(0,
+ &old_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
+
+ if (!native_password_plugin || !old_password_plugin)
+ DBUG_RETURN(1);
+
if (dont_read_acl_tables)
{
DBUG_RETURN(0); /* purecov: tested */
@@ -422,6 +536,7 @@ static my_bool acl_load(THD *thd, TABLE_
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
+ bzero(&user, sizeof(user));
update_hostname(&user.host, get_field(&mem, table->field[0]));
user.user= get_field(&mem, table->field[1]);
if (check_no_resolve && hostname_requires_resolving(user.host.hostname))
@@ -433,27 +548,34 @@ static my_bool acl_load(THD *thd, TABLE_
continue;
}
- const char *password= get_field(thd->mem_root, table->field[2]);
+ char *password= get_field(thd->mem_root, table->field[2]);
uint password_len= password ? strlen(password) : 0;
+ user.auth_string.str= password ? password : const_cast<char*>("");
+ user.auth_string.length= password_len;
set_user_salt(&user, password, password_len);
- if (user.salt_len == 0 && password_len != 0)
- {
- switch (password_len) {
- case 45: /* 4.1: to be removed */
- sql_print_warning("Found 4.1 style password for user '%s@%s'. "
- "Ignoring user. "
- "You should change password for this user.",
- user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : "");
- break;
- default:
- sql_print_warning("Found invalid password for user: '%s@%s'; "
- "Ignoring user", user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : "");
- break;
- }
+
+ switch (password_len) {
+ case 0: /* no password */
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH:
+ user.plugin= native_password_plugin_name;
+ break;
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH_323:
+ user.plugin= old_password_plugin_name;
+ break;
+ case 45: /* 4.1: to be removed */
+ sql_print_warning("Found 4.1.0 style password for user '%s@%s'. "
+ "Ignoring user. "
+ "You should change password for this user.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ continue;
+ default:
+ sql_print_warning("Found invalid password for user: '%s@%s'; "
+ "Ignoring user", user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ continue;
}
- else // password is correct
+
{
uint next_field;
user.access= get_access(table,3,&next_field) & GLOBAL_ACLS;
@@ -530,13 +652,43 @@ static my_bool acl_load(THD *thd, TABLE_
ptr= get_field(thd->mem_root, table->field[next_field++]);
user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
}
- else
- user.user_resource.user_conn= 0;
+
+ if (table->s->fields >= 41)
+ {
+ /* We may have plugin & auth_String fields */
+ char *tmpstr= get_field(&mem, table->field[next_field++]);
+ if (tmpstr)
+ {
+ if (user.auth_string.length)
+ {
+ sql_print_warning("'user' entry '%s@%s' has both a password "
+ "and an authentication plugin specified. The "
+ "password will be ignored.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ }
+ if (my_strcasecmp(system_charset_info, tmpstr,
+ native_password_plugin_name.str) == 0)
+ user.plugin= native_password_plugin_name;
+ else
+ if (my_strcasecmp(system_charset_info, tmpstr,
+ old_password_plugin_name.str) == 0)
+ user.plugin= old_password_plugin_name;
+ else
+ {
+ user.plugin.str= tmpstr;
+ user.plugin.length= strlen(tmpstr);
+ }
+ user.auth_string.str= get_field(&mem, table->field[next_field++]);
+ if (!user.auth_string.str)
+ user.auth_string.str= const_cast<char*>("");
+ user.auth_string.length= strlen(user.auth_string.str);
+ }
+ }
}
else
{
user.ssl_type=SSL_TYPE_NONE;
- bzero((char *)&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED
if (table->s->fields <= 13)
{ // Without grant
@@ -639,6 +791,8 @@ void acl_free(bool end)
delete_dynamic(&acl_dbs);
delete_dynamic(&acl_wild_hosts);
hash_free(&acl_check_hosts);
+ plugin_unlock(0, native_password_plugin);
+ plugin_unlock(0, old_password_plugin);
if (!end)
acl_cache->clear(1); /* purecov: inspected */
else
@@ -841,246 +995,10 @@ static int acl_compare(ACL_ACCESS *a,ACL
/*
- Seek ACL entry for a user, check password, SSL cypher, and if
- everything is OK, update THD user data and USER_RESOURCES struct.
-
- IMPLEMENTATION
- This function does not check if the user has any sensible privileges:
- only user's existence and validity is checked.
- Note, that entire operation is protected by acl_cache_lock.
+ Gets user credentials without authentication and resource limit checks.
SYNOPSIS
acl_getroot()
- thd thread handle. If all checks are OK,
- thd->security_ctx->priv_user/master_access are updated.
- thd->security_ctx->host/ip/user are used for checks.
- mqh user resources; on success mqh is reset, else
- unchanged
- passwd scrambled & crypted password, received from client
- (to check): thd->scramble or thd->scramble_323 is
- used to decrypt passwd, so they must contain
- original random string,
- passwd_len length of passwd, must be one of 0, 8,
- SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
- 'thd' and 'mqh' are updated on success; other params are IN.
-
- RETURN VALUE
- 0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
- updated
- 1 user not found or authentication failure
- 2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
- -1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
-*/
-
-int acl_getroot(THD *thd, USER_RESOURCES *mqh,
- const char *passwd, uint passwd_len)
-{
- ulong user_access= NO_ACCESS;
- int res= 1;
- ACL_USER *acl_user= 0;
- Security_context *sctx= thd->security_ctx;
- DBUG_ENTER("acl_getroot");
-
- if (!initialized)
- {
- /*
- here if mysqld's been started with --skip-grant-tables option.
- */
- sctx->skip_grants();
- bzero((char*) mqh, sizeof(*mqh));
- DBUG_RETURN(0);
- }
-
- VOID(pthread_mutex_lock(&acl_cache->lock));
-
- /*
- Find acl entry in user database. Note, that find_acl_user is not the same,
- because it doesn't take into account the case when user is not empty,
- but acl_user->user is empty
- */
-
- for (uint i=0 ; i < acl_users.elements ; i++)
- {
- ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
- if (!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user))
- {
- if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
- {
- /* check password: it should be empty or valid */
- if (passwd_len == acl_user_tmp->salt_len)
- {
- if (acl_user_tmp->salt_len == 0 ||
- (acl_user_tmp->salt_len == SCRAMBLE_LENGTH ?
- check_scramble(passwd, thd->scramble, acl_user_tmp->salt) :
- check_scramble_323(passwd, thd->scramble,
- (ulong *) acl_user_tmp->salt)) == 0)
- {
- acl_user= acl_user_tmp;
- res= 0;
- }
- }
- else if (passwd_len == SCRAMBLE_LENGTH &&
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH_323)
- res= -1;
- else if (passwd_len == SCRAMBLE_LENGTH_323 &&
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH)
- res= 2;
- /* linear search complete: */
- break;
- }
- }
- }
- /*
- This was moved to separate tree because of heavy HAVE_OPENSSL case.
- If acl_user is not null, res is 0.
- */
-
- if (acl_user)
- {
- /* OK. User found and password checked continue validation */
-#ifdef HAVE_OPENSSL
- Vio *vio=thd->net.vio;
- SSL *ssl= (SSL*) vio->ssl_arg;
- X509 *cert;
-#endif
-
- /*
- At this point we know that user is allowed to connect
- from given host by given username/password pair. Now
- we check if SSL is required, if user is using SSL and
- if X509 certificate attributes are OK
- */
- switch (acl_user->ssl_type) {
- case SSL_TYPE_NOT_SPECIFIED: // Impossible
- case SSL_TYPE_NONE: // SSL is not required
- user_access= acl_user->access;
- break;
-#ifdef HAVE_OPENSSL
- case SSL_TYPE_ANY: // Any kind of SSL is ok
- if (vio_type(vio) == VIO_TYPE_SSL)
- user_access= acl_user->access;
- break;
- case SSL_TYPE_X509: /* Client should have any valid certificate. */
- /*
- Connections with non-valid certificates are dropped already
- in sslaccept() anyway, so we do not check validity here.
-
- We need to check for absence of SSL because without SSL
- we should reject connection.
- */
- if (vio_type(vio) == VIO_TYPE_SSL &&
- SSL_get_verify_result(ssl) == X509_V_OK &&
- (cert= SSL_get_peer_certificate(ssl)))
- {
- user_access= acl_user->access;
- X509_free(cert);
- }
- break;
- case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
- /*
- We do not check for absence of SSL because without SSL it does
- not pass all checks here anyway.
- If cipher name is specified, we compare it to actual cipher in
- use.
- */
- if (vio_type(vio) != VIO_TYPE_SSL ||
- SSL_get_verify_result(ssl) != X509_V_OK)
- break;
- if (acl_user->ssl_cipher)
- {
- DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
- acl_user->ssl_cipher,SSL_get_cipher(ssl)));
- if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl)))
- user_access= acl_user->access;
- else
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
- acl_user->ssl_cipher,
- SSL_get_cipher(ssl));
- break;
- }
- }
- /* Prepare certificate (if exists) */
- DBUG_PRINT("info",("checkpoint 1"));
- if (!(cert= SSL_get_peer_certificate(ssl)))
- {
- user_access=NO_ACCESS;
- break;
- }
- DBUG_PRINT("info",("checkpoint 2"));
- /* If X509 issuer is specified, we check it... */
- if (acl_user->x509_issuer)
- {
- DBUG_PRINT("info",("checkpoint 3"));
- char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
- acl_user->x509_issuer, ptr));
- if (strcmp(acl_user->x509_issuer, ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 issuer mismatch: should be '%s' "
- "but is '%s'", acl_user->x509_issuer, ptr);
- free(ptr);
- X509_free(cert);
- user_access=NO_ACCESS;
- break;
- }
- user_access= acl_user->access;
- free(ptr);
- }
- DBUG_PRINT("info",("checkpoint 4"));
- /* X509 subject is specified, we check it .. */
- if (acl_user->x509_subject)
- {
- char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
- acl_user->x509_subject, ptr));
- if (strcmp(acl_user->x509_subject,ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
- acl_user->x509_subject, ptr);
- free(ptr);
- X509_free(cert);
- user_access=NO_ACCESS;
- break;
- }
- user_access= acl_user->access;
- free(ptr);
- }
- /* Deallocate the X509 certificate. */
- X509_free(cert);
- break;
-#else /* HAVE_OPENSSL */
- default:
- /*
- If we don't have SSL but SSL is required for this user the
- authentication should fail.
- */
- break;
-#endif /* HAVE_OPENSSL */
- }
- sctx->master_access= user_access;
- sctx->priv_user= acl_user->user ? sctx->user : (char *) "";
- *mqh= acl_user->user_resource;
-
- if (acl_user->host.hostname)
- strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
- else
- *sctx->priv_host= 0;
- }
- VOID(pthread_mutex_unlock(&acl_cache->lock));
- DBUG_RETURN(res);
-}
-
-
-/*
- This is like acl_getroot() above, but it doesn't check password,
- and we don't care about the user resources.
-
- SYNOPSIS
- acl_getroot_no_password()
sctx Context which should be initialized
user user name
host host name
@@ -1092,13 +1010,13 @@ int acl_getroot(THD *thd, USER_RESOURCES
TRUE Error
*/
-bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
- char *ip, char *db)
+bool acl_getroot(Security_context *sctx, char *user, char *host,
+ char *ip, char *db)
{
int res= 1;
uint i;
ACL_USER *acl_user= 0;
- DBUG_ENTER("acl_getroot_no_password");
+ DBUG_ENTER("acl_getroot");
DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'",
(host ? host : "(NULL)"), (ip ? ip : "(NULL)"),
@@ -1121,8 +1039,7 @@ bool acl_getroot_no_password(Security_co
sctx->master_access= 0;
sctx->db_access= 0;
- sctx->priv_user= (char *) "";
- *sctx->priv_host= 0;
+ *sctx->priv_user= *sctx->priv_host= 0;
/*
Find acl entry in user database.
@@ -1164,7 +1081,11 @@ bool acl_getroot_no_password(Security_co
}
}
sctx->master_access= acl_user->access;
- sctx->priv_user= acl_user->user ? user : (char *) "";
+
+ if (acl_user->user)
+ strmake(sctx->priv_user, user, USERNAME_LENGTH);
+ else
+ *sctx->priv_user= 0;
if (acl_user->host.hostname)
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
@@ -1190,7 +1111,9 @@ static void acl_update_user(const char *
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- ulong privileges)
+ ulong privileges,
+ const LEX_STRING *plugin,
+ const LEX_STRING *auth)
{
safe_mutex_assert_owner(&acl_cache->lock);
@@ -1204,6 +1127,14 @@ static void acl_update_user(const char *
(acl_user->host.hostname &&
!my_strcasecmp(system_charset_info, host, acl_user->host.hostname)))
{
+ if (plugin->str[0])
+ {
+ acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
+ acl_user->plugin.length= plugin->length;
+ acl_user->auth_string.str= auth->str ?
+ strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
+ acl_user->auth_string.length= auth->length;
+ }
acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
@@ -1240,7 +1171,9 @@ static void acl_insert_user(const char *
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- ulong privileges)
+ ulong privileges,
+ const LEX_STRING *plugin,
+ const LEX_STRING *auth)
{
ACL_USER acl_user;
@@ -1248,6 +1181,22 @@ static void acl_insert_user(const char *
acl_user.user=*user ? strdup_root(&mem,user) : 0;
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
+ if (plugin->str[0])
+ {
+ acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
+ acl_user.plugin.length= plugin->length;
+ acl_user.auth_string.str= auth->str ?
+ strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
+ acl_user.auth_string.length= auth->length;
+ }
+ else
+ {
+ acl_user.plugin= password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323 ?
+ old_password_plugin_name : native_password_plugin_name;
+ acl_user.auth_string.str= strmake_root(&mem, password, password_len);
+ acl_user.auth_string.length= password_len;
+ }
+
acl_user.access=privileges;
acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@@ -1966,6 +1915,15 @@ static int replace_user_table(THD *thd,
thd->security_ctx->user, thd->security_ctx->host_or_ip);
goto end;
}
+ else if (combo.plugin.str[0])
+ {
+ if (!plugin_is_ready(&combo.plugin, MYSQL_AUTHENTICATION_PLUGIN))
+ {
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo.plugin.str);
+ goto end;
+ }
+ }
+
old_row_exists = 0;
restore_record(table,s->default_values);
table->field[0]->store(combo.host.str,combo.host.length,
@@ -1979,7 +1937,7 @@ static int replace_user_table(THD *thd,
{
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
- if (combo.password.str) // If password given
+ if (combo.password.str) // If password given
table->field[2]->store(password, password_len, system_charset_info);
else if (!rights && !revoke_grant &&
lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
@@ -2060,7 +2018,17 @@ static int replace_user_table(THD *thd,
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE);
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
+
+ next_field+=4;
+ if (table->s->fields >= 41 && combo.plugin.str[0])
+ {
+ table->field[next_field]->store(combo.plugin.str, combo.plugin.length,
+ system_charset_info);
+ table->field[next_field+1]->store(combo.auth.str, combo.auth.length,
+ system_charset_info);
+ }
}
+
if (old_row_exists)
{
/*
@@ -2104,7 +2072,9 @@ end:
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
- rights);
+ rights,
+ &combo.plugin,
+ &combo.auth);
else
acl_insert_user(combo.user.str, combo.host.str, password, password_len,
lex->ssl_type,
@@ -2112,7 +2082,9 @@ end:
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
- rights);
+ rights,
+ &combo.plugin,
+ &combo.auth);
}
DBUG_RETURN(error);
}
@@ -4445,14 +4417,14 @@ bool check_routine_level_acl(THD *thd, c
ulong get_table_grant(THD *thd, TABLE_LIST *table)
{
ulong privilege;
- Security_context *sctx= thd->security_ctx;
- const char *db = table->db ? table->db : thd->db;
GRANT_TABLE *grant_table;
rw_rdlock(&LOCK_grant);
#ifdef EMBEDDED_LIBRARY
grant_table= NULL;
#else
+ Security_context *sctx= thd->security_ctx;
+ const char *db = table->db ? table->db : thd->db;
grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user,
table->table_name, 0);
#endif
@@ -6328,38 +6300,44 @@ bool sp_grant_privileges(THD *thd, const
tables->db= (char*)sp_db;
tables->table_name= tables->alias= (char*)sp_name;
- combo->host.length= strlen(combo->host.str);
- combo->user.length= strlen(combo->user.str);
- combo->host.str= thd->strmake(combo->host.str,combo->host.length);
- combo->user.str= thd->strmake(combo->user.str,combo->user.length);
+ thd->make_lex_string(&combo->user,
+ combo->user.str, strlen(combo->user.str), 0);
+ thd->make_lex_string(&combo->host,
+ combo->host.str, strlen(combo->host.str), 0);
+ combo->password= empty_lex_str;
+ combo->plugin= empty_lex_str;
+ combo->auth= empty_lex_str;
- if(au && au->salt_len)
+ if(au)
{
- if (au->salt_len == SCRAMBLE_LENGTH)
- {
- make_password_from_salt(passwd_buff, au->salt);
- combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
- }
- else if (au->salt_len == SCRAMBLE_LENGTH_323)
+ if (au->salt_len)
{
- make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
- combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ if (au->salt_len == SCRAMBLE_LENGTH)
+ {
+ make_password_from_salt(passwd_buff, au->salt);
+ combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+ }
+ else if (au->salt_len == SCRAMBLE_LENGTH_323)
+ {
+ make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
+ combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ }
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
+ ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ return TRUE;
+ }
+ combo->password.str= passwd_buff;
}
- else
+
+ if (au->plugin.str != native_password_plugin_name.str &&
+ au->plugin.str != old_password_plugin_name.str)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PASSWD_LENGTH,
- ER(ER_PASSWD_LENGTH),
- SCRAMBLED_PASSWORD_CHAR_LENGTH);
- return TRUE;
+ combo->plugin= au->plugin;
+ combo->auth= au->auth_string;
}
- combo->password.str= passwd_buff;
- }
- else
- {
- combo->password.str= (char*)"";
- combo->password.length= 0;
}
if (user_list.push_back(combo))
@@ -6853,3 +6831,1429 @@ bool check_routine_level_acl(THD *thd, c
}
#endif
+
+/****************************************************************************
+ AUTHENTICATION CODE
+ including initial connect handshake, invoking appropriate plugins,
+ client-server plugin negotiation, COM_CHANGE_USER, and native
+ MySQL authentication plugins.
+****************************************************************************/
+
+/* few defines to have less ifdef's in the code below */
+#ifdef EMBEDDED_LIBRARY
+#undef HAVE_OPENSSL
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+#define initialized 0
+#define decrease_user_connections(X) /* nothing */
+#define check_for_max_user_connections(X,Y) 0
+#endif
+#endif
+#ifndef HAVE_OPENSSL
+#define ssl_acceptor_fd 0
+#define sslaccept(A,B,C,D) 1
+#define NORMAL_HANDSHAKE_SIZE 6
+#endif
+
+/**
+ The internal version of what plugins know as MYSQL_PLUGIN_VIO,
+ basically the context of the authentication session
+*/
+struct MPVIO_EXT : public MYSQL_PLUGIN_VIO
+{
+ MYSQL_SERVER_AUTH_INFO auth_info;
+ THD *thd;
+ ACL_USER *acl_user; ///< a copy, independent from acl_users array
+ plugin_ref plugin; ///< what plugin we're under
+ LEX_STRING db; ///< db name from the handshake packet
+ /** when restarting a plugin this caches the last client reply */
+ struct {
+ char *plugin, *pkt; ///< pointers into NET::buff
+ uint pkt_len;
+ } cached_client_reply;
+ /** this caches the first plugin packet for restart request on the client */
+ struct {
+ char *pkt;
+ uint pkt_len;
+ } cached_server_packet;
+ int packets_read, packets_written; ///< counters for send/received packets
+ uint connect_errors; ///< if there were connect errors for this host
+ /** when plugin returns a failure this tells us what really happened */
+ enum { SUCCESS, FAILURE, RESTART } status;
+};
+
+
+/**
+ a helper function to report an access denied error in all the proper places
+*/
+
+static void login_failed_error(THD *thd, bool passwd_used)
+{
+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ status_var_increment(thd->status_var.access_denied_errors);
+ /*
+ Log access denied messages to the error log when log-warnings = 2
+ so that the overhead of the general query log is not required to track
+ failed connections.
+ */
+ if (global_system_variables.log_warnings > 1)
+ {
+ sql_print_warning(ER(ER_ACCESS_DENIED_ERROR),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ }
+}
+
+
+/**
+ sends a server handshake initialization packet, the very first packet
+ after the connection was established
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ 1 protocol version (always 10)
+ n server version string, \0-terminated
+ 4 thread id
+ 8 first 8 bytes of the plugin provided data (scramble)
+ 1 \0 byte, terminating the first part of a scramble
+ 2 server capabilities (two lower bytes)
+ 1 server character set
+ 2 server status
+ 2 server capabilities (two upper bytes)
+ 1 length of the scramble
+ 10 reserved, always 0
+ n rest of the plugin provided data (at least 12 bytes)
+ 1 \0 byte, terminating the second part of a scramble
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static bool send_server_handshake_packet(MPVIO_EXT *mpvio,
+ const char *data, uint data_len)
+{
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
+ DBUG_ASSERT(data_len <= 255);
+
+ THD *thd= mpvio->thd;
+ char *buff= (char *)my_alloca(1 + SERVER_VERSION_LENGTH + 1 + data_len + 64);
+ char scramble_buf[SCRAMBLE_LENGTH];
+ char *end= buff;
+
+ *end++= protocol_version;
+
+ thd->client_capabilities= CLIENT_BASIC_FLAGS;
+
+ if (data_len)
+ {
+ mpvio->cached_server_packet.pkt= (char*)thd->memdup(data, data_len);
+ mpvio->cached_server_packet.pkt_len= data_len;
+ }
+
+ if (data_len < SCRAMBLE_LENGTH)
+ {
+ if (data_len)
+ { /*
+ the first packet *must* have at least 20 bytes of a scramble.
+ if a plugin provided less, we pad it to 20 with zeros
+ */
+ memcpy(scramble_buf, data, data_len);
+ bzero(scramble_buf+data_len, SCRAMBLE_LENGTH-data_len);
+ data= scramble_buf;
+ }
+ else
+ {
+ /*
+ if the default plugin does not provide the data for the scramble at
+ all, we generate a scramble internally anyway, just in case the
+ user account (that will be known only later) uses a
+ native_password_plugin (which needs a scramble). If we don't send a
+ scramble now - wasting 20 bytes in the packet -
+ native_password_plugin will have to send it in a separate packet,
+ adding one more round trip.
+ */
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+ data= thd->scramble;
+ }
+ data_len= SCRAMBLE_LENGTH;
+ }
+
+ if (opt_using_transactions)
+ thd->client_capabilities|= CLIENT_TRANSACTIONS;
+
+ thd->client_capabilities|= CAN_CLIENT_COMPRESS;
+
+ if (ssl_acceptor_fd)
+ {
+ thd->client_capabilities |= CLIENT_SSL;
+ thd->client_capabilities |= CLIENT_SSL_VERIFY_SERVER_CERT;
+ }
+
+ end= strnmov(end, server_version, SERVER_VERSION_LENGTH) + 1;
+ int4store((uchar*) end, mpvio->thd->thread_id);
+ end+= 4;
+
+ /*
+ Old clients does not understand long scrambles, but can ignore packet
+ tail: that's why first part of the scramble is placed here, and second
+ part at the end of packet.
+ */
+ end= (char*)memcpy(end, data, SCRAMBLE_LENGTH_323);
+ end+= SCRAMBLE_LENGTH_323;
+ *end++= 0;
+
+ int2store(end, thd->client_capabilities);
+ /* write server characteristics: up to 16 bytes allowed */
+ end[2]=(char) default_charset_info->number;
+ int2store(end+3, mpvio->thd->server_status);
+ int2store(end+5, thd->client_capabilities >> 16);
+ end[7]= data_len;
+ bzero(end+8, 10);
+ end+= 18;
+ /* write scramble tail */
+ end= (char*)memcpy(end, data + SCRAMBLE_LENGTH_323,
+ data_len - SCRAMBLE_LENGTH_323);
+ end+= data_len - SCRAMBLE_LENGTH_323;
+ end= strmake(end, plugin_name(mpvio->plugin)->str,
+ plugin_name(mpvio->plugin)->length);
+
+ int res= my_net_write(&mpvio->thd->net, (uchar*) buff, (size_t) (end-buff)) ||
+ net_flush(&mpvio->thd->net);
+ my_afree(buff);
+ return res;
+}
+
+static bool secure_auth(THD *thd)
+{
+ if (!opt_secure_auth)
+ return 0;
+
+ /*
+ If the server is running in secure auth mode, short scrambles are
+ forbidden. Extra juggling to report the same error as the old code.
+ */
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
+ thd->security_ctx->user,
+ thd->security_ctx->host_or_ip);
+ general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
+ thd->security_ctx->user,
+ thd->security_ctx->host_or_ip);
+ }
+ else
+ {
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ }
+ return 1;
+}
+
+/**
+ sends a "change plugin" packet, requesting a client to restart authentication
+ using a different authentication plugin
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ 1 byte with the value 254
+ n client plugin to use, \0-terminated
+ n plugin provided data
+
+ In a special case of switching from native_password_plugin to
+ old_password_plugin, the packet contains only one - the first - byte,
+ plugin name is omitted, plugin data aren't needed as the scramble was
+ already sent. This one-byte packet is identical to the "use the short
+ scramble" packet in the protocol before plugins were introduced.
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
+ const uchar *data, uint data_len)
+{
+ DBUG_ASSERT(mpvio->packets_written == 1);
+ DBUG_ASSERT(mpvio->packets_read == 1);
+ NET *net= &mpvio->thd->net;
+ static uchar switch_plugin_request_buf[]= { 254 };
+
+
+ mpvio->status= MPVIO_EXT::FAILURE; // the status is no longer RESTART
+
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+
+ DBUG_ASSERT(client_auth_plugin);
+
+ /*
+ we send an old "short 4.0 scramble request", if we need to request a
+ client to use 4.0 auth plugin (short scramble) and the scramble was
+ already sent to the client
+
+ below, cached_client_reply.plugin is the plugin name that client has used,
+ client_auth_plugin is derived from mysql.user table, for the given
+ user account, it's the plugin that the client need to use to login.
+ */
+ bool switch_from_long_to_short_scramble=
+ native_password_plugin_name.str == mpvio->cached_client_reply.plugin &&
+ client_auth_plugin == old_password_plugin_name.str;
+
+ if (switch_from_long_to_short_scramble)
+ return secure_auth(mpvio->thd) ||
+ my_net_write(net, switch_plugin_request_buf, 1) ||
+ net_flush(net);
+
+ /*
+ We never request a client to switch from a short to long scramble.
+ Plugin-aware clients can do that, but traditionally it meant to
+ ask an old 4.0 client to use the new 4.1 authentication protocol.
+ */
+ bool switch_from_short_to_long_scramble=
+ old_password_plugin_name.str == mpvio->cached_client_reply.plugin &&
+ client_auth_plugin == native_password_plugin_name.str;
+
+ if (switch_from_short_to_long_scramble)
+ {
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ return 1;
+ }
+
+ return net_write_command(net, switch_plugin_request_buf[0],
+ (uchar*)client_auth_plugin,
+ strlen(client_auth_plugin)+1,
+ (uchar*)data, data_len);
+}
+
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+/**
+ Finds acl entry in user database for authentication purposes.
+
+ Finds a user and copies it into mpvio. Reports an authentication
+ failure if a user is not found.
+
+ @note find_acl_user is not the same, because it doesn't take into
+ account the case when user is not empty, but acl_user->user is empty
+
+ @retval 0 found
+ @retval 1 not found
+*/
+
+static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx)
+{
+ DBUG_ASSERT(mpvio->acl_user == 0);
+
+ pthread_mutex_lock(&acl_cache->lock);
+ for (uint i=0 ; i < acl_users.elements ; i++)
+ {
+ ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
+ if ((!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user)) &&
+ compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
+ {
+ mpvio->acl_user= acl_user_tmp->copy(mpvio->thd->mem_root);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&acl_cache->lock);
+
+ if (!mpvio->acl_user)
+ {
+ login_failed_error(mpvio->thd, 0);
+ return 1;
+ }
+
+ /* user account requires non-default plugin and the client is too old */
+ if (mpvio->acl_user->plugin.str != native_password_plugin_name.str &&
+ mpvio->acl_user->plugin.str != old_password_plugin_name.str &&
+ !(mpvio->thd->client_capabilities & CLIENT_PLUGIN_AUTH))
+ {
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ native_password_plugin_name.str));
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ old_password_plugin_name.str));
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ return 1;
+ }
+
+ mpvio->auth_info.user_name= sctx->user;
+ mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str;
+ strmake(mpvio->auth_info.authenticated_as, mpvio->acl_user->user ?
+ mpvio->acl_user->user : "", USERNAME_LENGTH);
+
+ return 0;
+}
+#endif
+
+
+/* the packet format is described in send_change_user_packet() */
+static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
+{
+ THD *thd= mpvio->thd;
+ NET *net= &thd->net;
+ Security_context *sctx= thd->security_ctx;
+
+ char *user= (char*) net->read_pos;
+ char *end= user + packet_length;
+ /* Safe because there is always a trailing \0 at the end of the packet */
+ char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1;
+ char *db= passwd;
+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
+ uint dummy_errors;
+
+ if (passwd >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
+
+ Cast *passwd to an unsigned char, so that it doesn't extend the sign for
+ *passwd > 127 and become 2**32-127+ after casting to uint.
+ */
+ uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ (uchar)(*passwd++) : strlen(passwd));
+
+ db+= passwd_len + 1;
+ /*
+ Database name is always NUL-terminated, so in case of empty database
+ the packet must contain at least the trailing '\0'.
+ */
+ if (db >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+
+ uint db_len= strlen(db);
+
+ char *ptr= db + db_len + 1;
+
+ if (ptr+1 < end)
+ {
+ uint cs_number= uint2korr(ptr);
+ thd_init_client_charset(thd, cs_number);
+ thd->update_charset();
+ }
+
+ /* Convert database and user names to utf8 */
+ db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
+ db, db_len, thd->charset(), &dummy_errors);
+
+ user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors);
+
+ if (!(sctx->user= my_strndup(user_buff, user_len, MYF(MY_WME))))
+ return 1;
+
+ /* Clear variables that are allocated */
+ thd->user_connect= 0;
+ strmake(sctx->priv_user, sctx->user, USERNAME_LENGTH);
+
+ if (thd->make_lex_string(&mpvio->db, db_buff, db_len, 0) == 0)
+ return 1; /* The error is set by make_lex_string(). */
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed.
+ */
+ thd->reset_db(NULL, 0);
+
+ if (!initialized)
+ {
+ // if mysqld's been started with --skip-grant-tables option
+ mpvio->status= MPVIO_EXT::SUCCESS;
+ return 0;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (find_mpvio_user(mpvio, sctx))
+ return 1;
+
+ char *client_plugin;
+ if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ client_plugin= ptr + 2;
+ if (client_plugin >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+ }
+ else
+ {
+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+ client_plugin= native_password_plugin_name.str;
+ else
+ {
+ client_plugin= old_password_plugin_name.str;
+ /*
+ For a passwordless accounts we use native_password_plugin.
+ But when an old 4.0 client connects to it, we change it to
+ old_password_plugin, otherwise MySQL will think that server
+ and client plugins don't match.
+ */
+ if (mpvio->acl_user->auth_string.length == 0)
+ mpvio->acl_user->plugin= old_password_plugin_name;
+ }
+ }
+
+ /* remember the data part of the packet, to present it to plugin in read_packet() */
+ mpvio->cached_client_reply.pkt= passwd;
+ mpvio->cached_client_reply.pkt_len= passwd_len;
+ mpvio->cached_client_reply.plugin= client_plugin;
+ mpvio->status= MPVIO_EXT::RESTART;
+#endif
+
+ return 0;
+}
+
+
+/* the packet format is described in send_client_reply_packet() */
+static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
+ uchar **buff, ulong pkt_len)
+{
+#ifndef EMBEDDED_LIBRARY
+ THD *thd= mpvio->thd;
+ NET *net= &thd->net;
+ char *end;
+
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
+
+ if (pkt_len < MIN_HANDSHAKE_SIZE)
+ return packet_error;
+
+ if (mpvio->connect_errors)
+ reset_host_errors(&net->vio->remote.sin_addr);
+
+ ulong client_capabilities= uint2korr(net->read_pos);
+ if (client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
+ thd->max_client_packet_length= uint4korr(net->read_pos+4);
+ DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
+ thd_init_client_charset(thd, (uint) net->read_pos[8]);
+ thd->update_charset();
+ end= (char*) net->read_pos+32;
+ }
+ else
+ {
+ thd->max_client_packet_length= uint3korr(net->read_pos+2);
+ end= (char*) net->read_pos+5;
+ }
+
+ /* Disable those bits which are not supported by the client. */
+ thd->client_capabilities&= client_capabilities;
+
+ if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
+ thd->variables.sql_mode|= MODE_IGNORE_SPACE;
+
+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
+ if (thd->client_capabilities & CLIENT_SSL)
+ {
+ char error_string[1024] __attribute__((unused));
+
+ /* Do the SSL layering. */
+ if (!ssl_acceptor_fd)
+ return packet_error;
+
+ DBUG_PRINT("info", ("IO layer change in progress..."));
+ if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, error_string))
+ {
+ DBUG_PRINT("error", ("Failed to accept new SSL connection"));
+ return packet_error;
+ }
+
+ DBUG_PRINT("info", ("Reading user information over SSL layer"));
+ pkt_len= my_net_read(net);
+ if (pkt_len == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE)
+ {
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
+ return packet_error;
+ }
+ }
+
+ if (end >= (char*) net->read_pos+ pkt_len +2)
+ return packet_error;
+
+ if (thd->client_capabilities & CLIENT_INTERACTIVE)
+ thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
+ if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
+ opt_using_transactions)
+ net->return_status= &thd->server_status;
+
+ char *user= end;
+ char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1, db_len;
+ char *db= passwd;
+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
+ uint dummy_errors;
+
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
+
+ Cast *passwd to an unsigned char, so that it doesn't extend the sign for
+ *passwd > 127 and become 2**32-127+ after casting to uint.
+ */
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ (uchar)(*passwd++) : strlen(passwd);
+
+ if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
+ {
+ db= db + passwd_len + 1;
+ /* strlen() can't be easily deleted without changing protocol */
+ db_len= strlen(db);
+ }
+ else
+ {
+ db= 0;
+ db_len= 0;
+ }
+
+ if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
+ return packet_error;
+
+ char *client_plugin= passwd + passwd_len + (db ? db_len + 1 : 0);
+
+ /* Since 4.1 all database names are stored in utf8 */
+ if (db)
+ {
+ db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
+ db, db_len, thd->charset(), &dummy_errors);
+ db= db_buff;
+ }
+
+ user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors);
+ user= user_buff;
+
+ /* If username starts and ends in "'", chop them off */
+ if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
+ {
+ user++;
+ user_len-= 2;
+ }
+
+ Security_context *sctx= thd->security_ctx;
+
+ if (thd->make_lex_string(&mpvio->db, db, db_len, 0) == 0)
+ return packet_error; /* The error is set by make_lex_string(). */
+ if (sctx->user)
+ x_free(sctx->user);
+ if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME))))
+ return packet_error; /* The error is set by my_strdup(). */
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed.
+ */
+ thd->reset_db(NULL, 0);
+
+ if (!initialized)
+ {
+ // if mysqld's been started with --skip-grant-tables option
+ mpvio->status= MPVIO_EXT::SUCCESS;
+ return packet_error;
+ }
+
+ if (find_mpvio_user(mpvio, sctx))
+ return packet_error;
+
+ if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ if ((client_plugin + strlen(client_plugin)) >
+ (char *)net->read_pos + pkt_len)
+ return packet_error;
+ }
+ else
+ {
+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+ client_plugin= native_password_plugin_name.str;
+ else
+ {
+ client_plugin= old_password_plugin_name.str;
+ /*
+ For a passwordless accounts we use native_password_plugin.
+ But when an old 4.0 client connects to it, we change it to
+ old_password_plugin, otherwise MySQL will think that server
+ and client plugins don't match.
+ */
+ if (mpvio->acl_user->auth_string.length == 0)
+ mpvio->acl_user->plugin= old_password_plugin_name;
+ }
+ }
+
+ /*
+ if the acl_user needs a different plugin to authenticate
+ (specified in GRANT ... AUTHENTICATED VIA plugin_name ..)
+ we need to restart the authentication in the server.
+ But perhaps the client has already used the correct plugin -
+ in that case the authentication on the client may not need to be
+ restarted and a server auth plugin will read the data that the client
+ has just send. Cache them to return in the next server_mpvio_read_packet().
+ */
+ if (my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ plugin_name(mpvio->plugin)->str) != 0)
+ {
+ mpvio->cached_client_reply.pkt= passwd;
+ mpvio->cached_client_reply.pkt_len= passwd_len;
+ mpvio->cached_client_reply.plugin= client_plugin;
+ mpvio->status= MPVIO_EXT::RESTART;
+ return packet_error;
+ }
+
+ /*
+ ok, we don't need to restart the authentication on the server.
+ but if the client used the wrong plugin, we need to restart
+ the authentication on the client. Do it here, the server plugin
+ doesn't need to know.
+ */
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+
+ if (client_auth_plugin &&
+ my_strcasecmp(system_charset_info, client_plugin, client_auth_plugin))
+ {
+ mpvio->cached_client_reply.plugin= client_plugin;
+ if (send_plugin_request_packet(mpvio,
+ (uchar*)mpvio->cached_server_packet.pkt,
+ mpvio->cached_server_packet.pkt_len))
+ return packet_error;
+
+ passwd_len= my_net_read(&mpvio->thd->net);
+ passwd = (char*)mpvio->thd->net.read_pos;
+ }
+
+ *buff= (uchar*)passwd;
+ return passwd_len;
+#else
+ return 0;
+#endif
+}
+
+
+/**
+ vio->write_packet() callback method for server authentication plugins
+
+ This function is called by a server authentication plugin, when it wants
+ to send data to the client.
+
+ It transparently wraps the data into a handshake packet,
+ and handles plugin negotiation with the client. If necessary,
+ it escapes the plugin data, if it starts with a mysql protocol packet byte.
+*/
+
+static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param,
+ const uchar *packet, int packet_len)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)param;
+ int res;
+
+ /* reset cached_client_reply */
+ mpvio->cached_client_reply.pkt= 0;
+ /* for the 1st packet we wrap plugin data into the handshake packet */
+ if (mpvio->packets_written == 0)
+ res= send_server_handshake_packet(mpvio, (char*)packet, packet_len);
+ else if (mpvio->status == MPVIO_EXT::RESTART)
+ res= send_plugin_request_packet(mpvio, packet, packet_len);
+ else if (packet_len > 0 && (*packet == 1 || *packet == 255 || *packet == 254))
+ {
+ /*
+ we cannot allow plugin data packet to start from 255 or 254 -
+ as the client will treat it as an error or "change plugin" packet.
+ We'll escape these bytes with \1. Consequently, we
+ have to escape \1 byte too.
+ */
+ res= net_write_command(&mpvio->thd->net, 1, (uchar*)"", 0,
+ packet, packet_len);
+ }
+ else
+ {
+ res= my_net_write(&mpvio->thd->net, packet, packet_len) ||
+ net_flush(&mpvio->thd->net);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+
+/**
+ vio->read_packet() callback method for server authentication plugins
+
+ This function is called by a server authentication plugin, when it wants
+ to read data from the client.
+
+ It transparently extracts the client plugin data, if embedded into
+ a client authentication handshake packet, and handles plugin negotiation
+ with the client, if necessary.
+*/
+
+static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)param;
+ ulong pkt_len;
+
+ if (mpvio->packets_written == 0)
+ {
+ /*
+ plugin wants to read the data without sending anything first.
+ send an empty packet to force a server handshake packet to be sent
+ */
+ if (server_mpvio_write_packet(mpvio, 0, 0))
+ pkt_len= packet_error;
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+ }
+ else
+ if (mpvio->cached_client_reply.pkt)
+ {
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::RESTART);
+ DBUG_ASSERT(mpvio->packets_read > 0);
+ /*
+ if the have the data cached from the last server_mpvio_read_packet
+ (which can be the case if it's a restarted authentication)
+ and a client has used the correct plugin, then we can return the
+ cached data straight away and avoid one round trip.
+ */
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+ if (client_auth_plugin == 0 ||
+ my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin,
+ client_auth_plugin) == 0)
+ {
+ mpvio->status= MPVIO_EXT::FAILURE;
+ *buf= (uchar*)mpvio->cached_client_reply.pkt;
+ mpvio->cached_client_reply.pkt= 0;
+ mpvio->packets_read++;
+ return (int)mpvio->cached_client_reply.pkt_len;
+ }
+ /*
+ But if the client has used the wrong plugin, the cached data are
+ useless. Furthermore, we have to send a "change plugin" request
+ to the client.
+ */
+ if (server_mpvio_write_packet(mpvio, 0, 0))
+ pkt_len= packet_error;
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+ }
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+
+ if (pkt_len == packet_error)
+ goto err;
+
+ mpvio->packets_read++;
+
+ /*
+ the 1st packet has the plugin data wrapped into the client authentication
+ handshake packet
+ */
+ if (mpvio->packets_read == 1)
+ {
+ pkt_len= parse_client_handshake_packet(mpvio, buf, pkt_len);
+ if (pkt_len == packet_error)
+ goto err;
+ }
+ else
+ *buf = mpvio->thd->net.read_pos;
+
+ return (int)pkt_len;
+
+err:
+ if (mpvio->status == MPVIO_EXT::FAILURE && !mpvio->thd->is_error())
+ {
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0),
+ mpvio->thd->security_ctx->host_or_ip);
+ }
+ return -1;
+}
+
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+static void server_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)vio;
+ mpvio_info(mpvio->thd->net.vio, info);
+}
+
+
+static bool acl_check_ssl(THD *thd, ACL_USER *acl_user)
+{
+#if defined(HAVE_OPENSSL)
+ Vio *vio=thd->net.vio;
+ SSL *ssl= (SSL*) vio->ssl_arg;
+ X509 *cert;
+#endif
+
+ /*
+ At this point we know that user is allowed to connect
+ from given host by given username/password pair. Now
+ we check if SSL is required, if user is using SSL and
+ if X509 certificate attributes are OK
+ */
+ switch (acl_user->ssl_type) {
+ case SSL_TYPE_NOT_SPECIFIED: // Impossible
+ case SSL_TYPE_NONE: // SSL is not required
+ return 0;
+#if defined(HAVE_OPENSSL)
+ case SSL_TYPE_ANY: // Any kind of SSL is ok
+ return vio_type(vio) != VIO_TYPE_SSL;
+ case SSL_TYPE_X509: /* Client should have any valid certificate. */
+ /*
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
+ */
+ if (vio_type(vio) == VIO_TYPE_SSL &&
+ SSL_get_verify_result(ssl) == X509_V_OK &&
+ (cert= SSL_get_peer_certificate(ssl)))
+ {
+ X509_free(cert);
+ return 0;
+ }
+ return 1;
+ case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
+ /* If a cipher name is specified, we compare it to actual cipher in use. */
+ if (vio_type(vio) != VIO_TYPE_SSL ||
+ SSL_get_verify_result(ssl) != X509_V_OK)
+ return 1;
+ if (acl_user->ssl_cipher)
+ {
+ DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
+ acl_user->ssl_cipher,SSL_get_cipher(ssl)));
+ if (strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl)))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
+ acl_user->ssl_cipher, SSL_get_cipher(ssl));
+ return 1;
+ }
+ }
+ /* Prepare certificate (if exists) */
+ if (!(cert= SSL_get_peer_certificate(ssl)))
+ return 1;
+ /* If X509 issuer is specified, we check it... */
+ if (acl_user->x509_issuer)
+ {
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ acl_user->x509_issuer, ptr));
+ if (strcmp(acl_user->x509_issuer, ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 issuer mismatch: should be '%s' "
+ "but is '%s'", acl_user->x509_issuer, ptr);
+ free(ptr);
+ X509_free(cert);
+ return 1;
+ }
+ free(ptr);
+ }
+ /* X509 subject is specified, we check it .. */
+ if (acl_user->x509_subject)
+ {
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
+ acl_user->x509_subject, ptr);
+ free(ptr);
+ X509_free(cert);
+ return 1;
+ }
+ free(ptr);
+ }
+ X509_free(cert);
+ return 0;
+#else /* HAVE_OPENSSL */
+ default:
+ /*
+ If we don't have SSL but SSL is required for this user the
+ authentication should fail.
+ */
+ return 1;
+#endif /* HAVE_OPENSSL */
+ }
+ return 1;
+}
+
+static int do_auth_once(THD *thd, LEX_STRING *auth_plugin_name,
+ MPVIO_EXT *mpvio)
+{
+ int res= CR_OK, old_status= MPVIO_EXT::FAILURE;
+ bool unlock_plugin= false;
+ plugin_ref plugin;
+
+ if (auth_plugin_name->str == native_password_plugin_name.str)
+ plugin= native_password_plugin;
+ else
+#ifndef EMBEDDED_LIBRARY
+ if (auth_plugin_name->str == old_password_plugin_name.str)
+ plugin= old_password_plugin;
+ else
+ if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
+ MYSQL_AUTHENTICATION_PLUGIN)))
+ unlock_plugin= true;
+#endif
+
+ mpvio->plugin= plugin;
+ old_status= mpvio->status;
+
+ if (plugin)
+ {
+ st_mysql_auth *auth= (st_mysql_auth*)plugin_decl(plugin)->info;
+ res= auth->authenticate_user(mpvio, &mpvio->auth_info);
+
+ if (unlock_plugin)
+ plugin_unlock(thd, plugin);
+ }
+ else
+ {
+ /* Server cannot load the required plugin. */
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth_plugin_name->str);
+ res= CR_ERROR;
+ }
+
+ /*
+ If the status was MPVIO_EXT::RESTART before the authenticate_user() call
+ it can never be MPVIO_EXT::RESTART after the call, because any call
+ to write_packet() or read_packet() will reset the status.
+
+ But (!) if a plugin never called a read_packet() or write_packet(), the
+ status will stay unchanged. We'll fix it, by resetting the status here.
+ */
+ if (old_status == MPVIO_EXT::RESTART && mpvio->status == MPVIO_EXT::RESTART)
+ mpvio->status= MPVIO_EXT::FAILURE; // reset to the default
+
+ return res;
+}
+
+/**
+ Perform the handshake, authorize the client and update thd sctx variables.
+
+ @param thd thread handle
+ @param connect_errors number of previous failed connect attemps
+ from this host
+ @param com_change_user_pkt_len size of the COM_CHANGE_USER packet
+ (without the first, command, byte) or 0
+ if it's not a COM_CHANGE_USER (that is, if
+ it's a new connection)
+
+ @retval 0 success, thd is updated.
+ @retval 1 error
+*/
+
+bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
+{
+ int res= CR_OK;
+ MPVIO_EXT mpvio;
+ LEX_STRING *auth_plugin_name= default_auth_plugin_name;
+ enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER
+ : COM_CONNECT;
+ DBUG_ENTER("acl_authenticate");
+
+ compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
+
+ bzero(&mpvio, sizeof(mpvio));
+ mpvio.read_packet= server_mpvio_read_packet;
+ mpvio.write_packet= server_mpvio_write_packet;
+ mpvio.info= server_mpvio_info;
+ mpvio.thd= thd;
+ mpvio.connect_errors= connect_errors;
+ mpvio.status= MPVIO_EXT::FAILURE;
+
+ if (command == COM_CHANGE_USER)
+ {
+ mpvio.packets_written++; // pretend that a server handshake packet was sent
+ mpvio.packets_read++; // take COM_CHANGE_USER packet into account
+
+ if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len))
+ DBUG_RETURN(1);
+
+ DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
+ mpvio.status == MPVIO_EXT::SUCCESS);
+ }
+ else
+ {
+ /* mark the thd as having no scramble yet */
+ thd->scramble[SCRAMBLE_LENGTH]= 1;
+
+ /*
+ perform the first authentication attempt, with the default plugin.
+ This sends the server handshake packet, reads the client reply
+ with a user name, and performs the authentication if everyone has used
+ the correct plugin.
+ */
+ res= do_auth_once(thd, auth_plugin_name, &mpvio);
+ }
+
+ /*
+ retry the authentication, if - after receiving the user name -
+ we found that we need to switch to a non-default plugin
+ */
+ if (mpvio.status == MPVIO_EXT::RESTART)
+ {
+ DBUG_ASSERT(mpvio.acl_user);
+ DBUG_ASSERT(command == COM_CHANGE_USER ||
+ my_strcasecmp(system_charset_info, auth_plugin_name->str,
+ mpvio.acl_user->plugin.str));
+ auth_plugin_name= &mpvio.acl_user->plugin;
+ res= do_auth_once(thd, auth_plugin_name, &mpvio);
+ }
+
+ Security_context *sctx= thd->security_ctx;
+ ACL_USER *acl_user= mpvio.acl_user;
+
+ thd->password= mpvio.auth_info.password_used; // remember for error messages
+
+ /*
+ Log the command here so that the user can check the log
+ for the tried logins and also to detect break-in attempts.
+
+ if sctx->user is unset it's protocol failure, bad packet.
+ */
+ if (sctx->user)
+ {
+ if (strcmp(sctx->priv_user, sctx->user))
+ {
+ general_log_print(thd, command, "%s@%s as %s on %s",
+ sctx->user, sctx->host_or_ip,
+ sctx->priv_user[0] ? sctx->priv_user : "anonymous",
+ mpvio.db.str ? mpvio.db.str : (char*) "");
+ }
+ else
+ general_log_print(thd, command, (char*) "%s@%s on %s",
+ sctx->user, sctx->host_or_ip,
+ mpvio.db.str ? mpvio.db.str : (char*) "");
+ }
+
+ if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
+ {
+ DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
+
+ if (!thd->is_error())
+ login_failed_error(thd, thd->password);
+ DBUG_RETURN(1);
+ }
+
+ if (initialized) // if not --skip-grant-tables
+ {
+ sctx->master_access= acl_user->access;
+ strmake(sctx->priv_user, mpvio.auth_info.authenticated_as, USERNAME_LENGTH);
+ if (acl_user->host.hostname)
+ strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *sctx->priv_host= 0;
+
+ /*
+ OK. Let's check the SSL. Historically it was checked after the password,
+ as an additional layer, not instead of the password
+ (in which case it would've been a plugin too).
+ */
+ if (acl_check_ssl(thd, acl_user))
+ {
+ login_failed_error(thd, thd->password);
+ DBUG_RETURN(1);
+ }
+
+ /* Don't allow the user to connect if he has done too many queries */
+ if ((acl_user->user_resource.questions || acl_user->user_resource.updates ||
+ acl_user->user_resource.conn_per_hour ||
+ acl_user->user_resource.user_conn || max_user_connections) &&
+ get_or_create_user_conn(thd,
+ (opt_old_style_user_limits ? sctx->user : sctx->priv_user),
+ (opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
+ &acl_user->user_resource))
+ DBUG_RETURN(1); // The error is set by get_or_create_user_conn()
+ }
+ else
+ sctx->skip_grants();
+
+ if (thd->user_connect &&
+ (thd->user_connect->user_resources.conn_per_hour ||
+ thd->user_connect->user_resources.user_conn ||
+ max_user_connections) &&
+ check_for_max_user_connections(thd, thd->user_connect))
+ {
+ status_var_increment(denied_connections);
+ DBUG_RETURN(1); // The error is set in check_for_max_user_connections()
+ }
+
+ DBUG_PRINT("info",
+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
+ "Login user: '%s' Priv_user: '%s' Using password: %s "
+ "Access: %lu db: '%s'",
+ thd->client_capabilities, thd->max_client_packet_length,
+ sctx->host_or_ip, sctx->user, sctx->priv_user,
+ thd->password ? "yes": "no",
+ sctx->master_access, mpvio.db.str));
+
+ if (command == COM_CONNECT &&
+ !(thd->main_security_ctx.master_access & SUPER_ACL))
+ {
+ pthread_mutex_lock(&LOCK_connection_count);
+ bool count_ok= (*thd->scheduler->connection_count <=
+ *thd->scheduler->max_connections);
+ VOID(pthread_mutex_unlock(&LOCK_connection_count));
+ if (!count_ok)
+ { // too many connections
+ my_error(ER_CON_COUNT_ERROR, MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+
+ /*
+ This is the default access rights for the current database. It's
+ set to 0 here because we don't have an active database yet (and we
+ may not have an active database to set.
+ */
+ sctx->db_access=0;
+
+ /* Change a database if necessary */
+ if (mpvio.db.length)
+ {
+ if (mysql_change_db(thd, &mpvio.db, FALSE))
+ {
+ /* mysql_change_db() has pushed the error message. */
+ if (thd->user_connect)
+ {
+ status_var_increment(thd->status_var.access_denied_errors);
+ decrease_user_connections(thd->user_connect);
+ thd->user_connect= 0;
+ }
+ DBUG_RETURN(1);
+ }
+ }
+
+ thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
+
+ if (res == CR_OK_HANDSHAKE_COMPLETE)
+ thd->main_da.disable_status();
+ else
+ my_ok(thd);
+
+ /* Ready to handle queries */
+ DBUG_RETURN(0);
+}
+
+
+/**
+ MySQL Server Password Authentication Plugin
+
+ In the MySQL authentication protocol:
+ 1. the server sends the random scramble to the client
+ 2. client sends the encrypted password back to the server
+ 3. the server checks the password.
+*/
+
+static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ uchar *pkt;
+ int pkt_len;
+ MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
+ THD *thd=mpvio->thd;
+
+ /* generate the scramble, or reuse the old one */
+ if (thd->scramble[SCRAMBLE_LENGTH])
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+
+ /* send it to the client */
+ if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+ return CR_ERROR;
+
+ /* reply and authenticate */
+
+ /*
+ <digression>
+ This is more complex than it looks.
+
+ The plugin (we) may be called right after the client was connected -
+ and will need to send a scramble, read reply, authenticate.
+
+ Or the plugin may be called after another plugin has sent a scramble,
+ and read the reply. If the client has used the correct client-plugin,
+ we won't need to read anything here from the client, the client
+ has already sent a reply with everything we need for authentication.
+
+ Or the plugin may be called after another plugin has sent a scramble,
+ and read the reply, but the client has used the wrong client-plugin.
+ We'll need to sent a "switch to another plugin" packet to the
+ client and read the reply. "Use the short scramble" packet is a special
+ case of "switch to another plugin" packet.
+
+ Or, perhaps, the plugin may be called after another plugin has
+ done the handshake but did not send a useful scramble. We'll need
+ to send a scramble (and perhaps a "switch to another plugin" packet)
+ and read the reply.
+
+ Besides, a client may be an old one, that doesn't understand plugins.
+ Or doesn't even understand 4.0 scramble.
+
+ And we want to keep the same protocol on the wire unless non-native
+ plugins are involved.
+
+ Anyway, it still looks simple from a plugin point of view:
+ "send the scramble, read the reply and authenticate".
+ All the magic is transparently handled by the server.
+ </digression>
+ */
+
+ /* read the reply with the encrypted password */
+ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+ return CR_ERROR;
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return CR_OK;
+#endif
+
+ if (pkt_len == 0) /* no password */
+ return info->auth_string[0] ? CR_ERROR : CR_OK;
+
+ info->password_used = 1;
+ if (pkt_len == SCRAMBLE_LENGTH)
+ return check_scramble(pkt, thd->scramble, mpvio->acl_user->salt) ?
+ CR_ERROR : CR_OK;
+
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ return CR_ERROR;
+}
+
+
+static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ uchar *pkt;
+ int pkt_len;
+ MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
+ THD *thd=mpvio->thd;
+
+ /* generate the scramble, or reuse the old one */
+ if (thd->scramble[SCRAMBLE_LENGTH])
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+
+ /* send it to the client */
+ if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+ return CR_ERROR;
+
+ /* read the reply and authenticate */
+ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+ return CR_ERROR;
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return CR_OK;
+#endif
+
+ /*
+ legacy: if switch_from_long_to_short_scramble,
+ the password is sent \0-terminated, the pkt_len is always 9 bytes.
+ We need to figure out the correct scramble length here.
+ */
+ if (pkt_len == SCRAMBLE_LENGTH_323+1)
+ pkt_len= strnlen((char*)pkt, pkt_len);
+
+ if (pkt_len == 0) /* no password */
+ return info->auth_string[0] ? CR_ERROR : CR_OK;
+
+ if (secure_auth(thd))
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ if (pkt_len == SCRAMBLE_LENGTH_323)
+ return check_scramble_323(pkt, thd->scramble,
+ (ulong *)mpvio->acl_user->salt) ? CR_ERROR : CR_OK;
+
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ return CR_ERROR;
+}
+
+static struct st_mysql_auth native_password_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ native_password_plugin_name.str,
+ native_password_authenticate
+};
+
+static struct st_mysql_auth old_password_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ old_password_plugin_name.str,
+ old_password_authenticate
+};
+
+mysql_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
+
=== modified file 'sql/sql_acl.h'
--- a/sql/sql_acl.h 2009-11-21 11:18:21 +0000
+++ b/sql/sql_acl.h 2010-03-29 15:13:53 +0000
@@ -161,53 +161,6 @@ enum mysql_db_table_field
extern const TABLE_FIELD_DEF mysql_db_table_def;
-/* Classes */
-
-struct acl_host_and_ip
-{
- char *hostname;
- long ip,ip_mask; // Used with masked ip:s
-};
-
-
-class ACL_ACCESS {
-public:
- ulong sort;
- ulong access;
-};
-
-
-/* ACL_HOST is used if no host is specified */
-
-class ACL_HOST :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *db;
-};
-
-
-class ACL_USER :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- uint hostname_length;
- USER_RESOURCES user_resource;
- char *user;
- uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
- uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 3.23, 20 - 4.1.1
- enum SSL_type ssl_type;
- const char *ssl_cipher, *x509_issuer, *x509_subject;
-};
-
-
-class ACL_DB :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *user,*db;
-};
-
/* prototypes */
bool hostname_requires_resolving(const char *hostname);
@@ -216,10 +169,9 @@ my_bool acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip,
const char *user, const char *db, my_bool db_is_pattern);
-int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd,
- uint passwd_len);
-bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
- char *ip, char *db);
+bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len);
+bool acl_getroot(Security_context *sctx, char *user, char *host,
+ char *ip, char *db);
bool acl_check_host(const char *host, const char *ip);
int check_change_password(THD *thd, const char *host, const char *user,
char *password, uint password_len);
=== modified file 'sql/sql_builtin.cc.in'
--- a/sql/sql_builtin.cc.in 2009-11-29 23:08:56 +0000
+++ b/sql/sql_builtin.cc.in 2010-03-29 15:13:53 +0000
@@ -19,10 +19,10 @@
typedef struct st_mysql_plugin builtin_plugin[];
extern builtin_plugin
- builtin_binlog_plugin@mysql_plugin_defs@;
+ builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@;
struct st_mysql_plugin *mysqld_builtins[]=
{
- builtin_binlog_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_binlog_plugin, builtin_mysql_password_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
};
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_class.cc 2010-03-29 15:13:53 +0000
@@ -2984,9 +2984,9 @@ void THD::set_status_var_init()
void Security_context::init()
{
- host= user= priv_user= ip= 0;
+ host= user= ip= 0;
host_or_ip= "connecting host";
- priv_host[0]= '\0';
+ priv_user[0]= priv_host[0]= '\0';
master_access= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access= NO_ACCESS;
@@ -3010,8 +3010,7 @@ void Security_context::skip_grants()
/* privileges for the user are unknown everything is allowed */
host_or_ip= (char *)"";
master_access= ~NO_ACCESS;
- priv_user= (char *)"";
- *priv_host= '\0';
+ *priv_user= *priv_host= '\0';
}
@@ -3053,7 +3052,7 @@ bool Security_context::set_user(char *us
of a statement under credentials of a different user, e.g.
definer of a procedure, we authenticate this user in a local
instance of Security_context by means of this method (and
- ultimately by means of acl_getroot_no_password), and make the
+ ultimately by means of acl_getroot), and make the
local instance active in the thread by re-setting
thd->security_ctx pointer.
@@ -3087,19 +3086,12 @@ change_security_context(THD *thd,
DBUG_ASSERT(definer_user->str && definer_host->str);
*backup= NULL;
- /*
- The current security context may have NULL members
- if we have just started the thread and not authenticated
- any user. This use case is currently in events worker thread.
- */
- needs_change= (thd->security_ctx->priv_user == NULL ||
- strcmp(definer_user->str, thd->security_ctx->priv_user) ||
- thd->security_ctx->priv_host == NULL ||
+ needs_change= (strcmp(definer_user->str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info, definer_host->str,
thd->security_ctx->priv_host));
if (needs_change)
{
- if (acl_getroot_no_password(this, definer_user->str, definer_host->str,
+ if (acl_getroot(this, definer_user->str, definer_host->str,
definer_host->str, db->str))
{
my_error(ER_NO_SUCH_USER, MYF(0), definer_user->str,
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_class.h 2010-03-29 15:13:53 +0000
@@ -805,7 +805,8 @@ public:
priv_user - The user privilege we are using. May be "" for anonymous user.
ip - client IP
*/
- char *host, *user, *priv_user, *ip;
+ char *host, *user, *ip;
+ char priv_user[USERNAME_LENGTH];
/* The host privilege we are using */
char priv_host[MAX_HOSTNAME];
/* points to host if host is available, otherwise points to ip */
=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_connect.cc 2010-03-29 15:13:53 +0000
@@ -27,24 +27,6 @@ extern pthread_mutex_t LOCK_global_user_
extern pthread_mutex_t LOCK_global_table_stats;
extern pthread_mutex_t LOCK_global_index_stats;
-#ifdef HAVE_OPENSSL
-/*
- Without SSL the handshake consists of one packet. This packet
- has both client capabilites and scrambled password.
- With SSL the handshake might consist of two packets. If the first
- packet (client capabilities) has CLIENT_SSL flag set, we have to
- switch to SSL and read the second packet. The scrambled password
- is in the second packet and client_capabilites field will be ignored.
- Maybe it is better to accept flags other than CLIENT_SSL from the
- second packet?
-*/
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
-#else
-#define MIN_HANDSHAKE_SIZE 6
-#endif /* HAVE_OPENSSL */
-
#ifdef __WIN__
extern void win_install_sigabrt_handler();
#endif
@@ -56,9 +38,9 @@ extern void win_install_sigabrt_handler(
#ifndef NO_EMBEDDED_ACCESS_CHECKS
static HASH hash_user_connections;
-static int get_or_create_user_conn(THD *thd, const char *user,
- const char *host,
- USER_RESOURCES *mqh)
+int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host,
+ USER_RESOURCES *mqh)
{
int return_val= 0;
size_t temp_len, user_len;
@@ -124,7 +106,6 @@ end:
1 error
*/
-static
int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
@@ -276,240 +257,6 @@ end:
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-
-/**
- Check if user exist and password supplied is correct.
-
- @param thd thread handle, thd->security_ctx->{host,user,ip} are used
- @param command originator of the check: now check_user is called
- during connect and change user procedures; used for
- logging.
- @param passwd scrambled password received from client
- @param passwd_len length of scrambled password
- @param db database name to connect to, may be NULL
- @param check_count TRUE if establishing a new connection. In this case
- check that we have not exceeded the global
- max_connections limist
-
- @note Host, user and passwd may point to communication buffer.
- Current implementation does not depend on that, but future changes
- should be done with this in mind; 'thd' is INOUT, all other params
- are 'IN'.
-
- @retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and
- thd->db are updated; OK is sent to the client.
- @retval 1 error, e.g. access denied or handshake error, not sent to
- the client. A message is pushed into the error stack.
-*/
-
-int
-check_user(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count)
-{
- DBUG_ENTER("check_user");
- LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
-
- /*
- Clear thd->db as it points to something, that will be freed when
- connection is closed. We don't want to accidentally free a wrong
- pointer if connect failed. Also in case of 'CHANGE USER' failure,
- current database will be switched to 'no database selected'.
- */
- thd->reset_db(NULL, 0);
-
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
- thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights
- /* Change database if necessary */
- if (db && db[0])
- {
- if (mysql_change_db(thd, &db_str, FALSE))
- DBUG_RETURN(1);
- }
- my_ok(thd);
- DBUG_RETURN(0);
-#else
-
- my_bool opt_secure_auth_local;
- pthread_mutex_lock(&LOCK_global_system_variables);
- opt_secure_auth_local= opt_secure_auth;
- pthread_mutex_unlock(&LOCK_global_system_variables);
-
- /*
- If the server is running in secure auth mode, short scrambles are
- forbidden.
- */
- if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
- {
- my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
- general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
- DBUG_RETURN(1);
- }
- if (passwd_len != 0 &&
- passwd_len != SCRAMBLE_LENGTH &&
- passwd_len != SCRAMBLE_LENGTH_323)
- {
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
-
- USER_RESOURCES ur;
- int res= acl_getroot(thd, &ur, passwd, passwd_len);
-#ifndef EMBEDDED_LIBRARY
- if (res == -1)
- {
- /*
- This happens when client (new) sends password scrambled with
- scramble(), but database holds old value (scrambled with
- scramble_323()). Here we please client to send scrambled_password
- in old format.
- */
- NET *net= &thd->net;
- if (opt_secure_auth_local)
- {
- my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip);
- general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
- /* We have to read very specific packet size */
- if (send_old_password_request(thd) ||
- my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
- /* Final attempt to check the user based on reply */
- /* So as passwd is short, errcode is always >= 0 */
- res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
- }
-#endif /*EMBEDDED_LIBRARY*/
- /* here res is always >= 0 */
- if (res == 0)
- {
- if (!(thd->main_security_ctx.master_access &
- NO_ACCESS)) // authentication is OK
- {
- DBUG_PRINT("info",
- ("Capabilities: %lu packet_length: %ld Host: '%s' "
- "Login user: '%s' Priv_user: '%s' Using password: %s "
- "Access: %lu db: '%s'",
- thd->client_capabilities,
- thd->max_client_packet_length,
- thd->main_security_ctx.host_or_ip,
- thd->main_security_ctx.user,
- thd->main_security_ctx.priv_user,
- passwd_len ? "yes": "no",
- thd->main_security_ctx.master_access,
- (thd->db ? thd->db : "*none*")));
-
- if (check_count)
- {
- bool count_ok= 1;
-
- if (!(thd->main_security_ctx.master_access & SUPER_ACL))
- {
- pthread_mutex_lock(&LOCK_connection_count);
- count_ok= (*thd->scheduler->connection_count <=
- *thd->scheduler->max_connections);
- VOID(pthread_mutex_unlock(&LOCK_connection_count));
- }
- if (!count_ok)
- { // too many connections
- my_error(ER_CON_COUNT_ERROR, MYF(0));
- DBUG_RETURN(1);
- }
- }
-
- /*
- Log the command before authentication checks, so that the user can
- check the log for the tried login tried and also to detect
- break-in attempts.
- */
- general_log_print(thd, command,
- (thd->main_security_ctx.priv_user ==
- thd->main_security_ctx.user ?
- (char*) "%s@%s on %s" :
- (char*) "%s@%s as anonymous on %s"),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- db ? db : (char*) "");
-
- /*
- This is the default access rights for the current database. It's
- set to 0 here because we don't have an active database yet (and we
- may not have an active database to set.
- */
- thd->main_security_ctx.db_access=0;
-
- /* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
- max_user_connections) &&
- get_or_create_user_conn(thd,
- (opt_old_style_user_limits ? thd->main_security_ctx.user :
- thd->main_security_ctx.priv_user),
- (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
- thd->main_security_ctx.priv_host),
- &ur))
- {
- /* The error is set by get_or_create_user_conn(). */
- DBUG_RETURN(1);
- }
- if (thd->user_connect &&
- (thd->user_connect->user_resources.conn_per_hour ||
- thd->user_connect->user_resources.user_conn ||
- max_user_connections) &&
- check_for_max_user_connections(thd, thd->user_connect))
- {
- /* The error is set in check_for_max_user_connections(). */
- status_var_increment(denied_connections);
- DBUG_RETURN(1);
- }
-
- /* Change database if necessary */
- if (db && db[0])
- {
- if (mysql_change_db(thd, &db_str, FALSE))
- {
- /* mysql_change_db() has pushed the error message. */
- if (thd->user_connect)
- decrease_user_connections(thd->user_connect);
- status_var_increment(thd->status_var.access_denied_errors);
- DBUG_RETURN(1);
- }
- }
- my_ok(thd);
- thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
- thd->password= test(passwd_len); // remember for error messages
- /* Ready to handle queries */
- DBUG_RETURN(0);
- }
- }
- else if (res == 2) // client gave short hash, server has long hash
- {
- my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
- general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
- DBUG_RETURN(1);
- }
- my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
- general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
- status_var_increment(thd->status_var.access_denied_errors);
-
- DBUG_RETURN(1);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-}
-
-
/*
Check for maximum allowable user connections, if the mysqld server is
started with corresponding variable that is greater then 0.
@@ -1088,9 +835,8 @@ bool init_new_connection_handler_thread(
thd thread handle
RETURN
- 0 success, OK is sent to user, thd is updated.
- -1 error, which is sent to user
- > 0 error code (not sent to user)
+ 0 success, thd is updated.
+ 1 error
*/
#ifndef EMBEDDED_LIBRARY
@@ -1098,8 +844,6 @@ static int check_connection(THD *thd)
{
uint connect_errors= 0;
NET *net= &thd->net;
- ulong pkt_len= 0;
- char *end;
DBUG_PRINT("info",
("New connection received on %s", vio_description(net->vio)));
@@ -1161,200 +905,10 @@ static int check_connection(THD *thd)
}
vio_keepalive(net->vio, TRUE);
- ulong server_capabilites;
- {
- /* buff[] needs to big enough to hold the server_version variable */
- char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64];
- server_capabilites= CLIENT_BASIC_FLAGS;
-
- if (opt_using_transactions)
- server_capabilites|= CLIENT_TRANSACTIONS;
-#ifdef HAVE_COMPRESS
- server_capabilites|= CLIENT_COMPRESS;
-#endif /* HAVE_COMPRESS */
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- {
- server_capabilites |= CLIENT_SSL; /* Wow, SSL is available! */
- server_capabilites |= CLIENT_SSL_VERIFY_SERVER_CERT;
- }
-#endif /* HAVE_OPENSSL */
-
- end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
- int4store((uchar*) end, thd->thread_id);
- end+= 4;
- /*
- So as check_connection is the only entry point to authorization
- procedure, scramble is set here. This gives us new scramble for
- each handshake.
- */
- create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
- /*
- Old clients does not understand long scrambles, but can ignore packet
- tail: that's why first part of the scramble is placed here, and second
- part at the end of packet.
- */
- end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
-
- int2store(end, server_capabilites);
- /* write server characteristics: up to 16 bytes allowed */
- end[2]=(char) default_charset_info->number;
- int2store(end+3, thd->server_status);
- bzero(end+5, 13);
- end+= 18;
- /* write scramble tail */
- end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
- SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
-
- /* At this point we write connection message and read reply */
- if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
- (uchar*) buff, (size_t) (end-buff)) ||
- (pkt_len= my_net_read(net)) == packet_error ||
- pkt_len < MIN_HANDSHAKE_SIZE)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0),
- thd->main_security_ctx.host_or_ip);
- return 1;
- }
- }
-#ifdef _CUSTOMCONFIG_
-#include "_cust_sql_parse.h"
-#endif
- if (connect_errors)
- reset_host_errors(&thd->remote.sin_addr);
if (thd->packet.alloc(thd->variables.net_buffer_length))
return 1; /* The error is set by alloc(). */
- thd->client_capabilities= uint2korr(net->read_pos);
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
- thd->max_client_packet_length= uint4korr(net->read_pos+4);
- DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
- thd_init_client_charset(thd, (uint) net->read_pos[8]);
- thd->update_charset();
- end= (char*) net->read_pos+32;
- }
- else
- {
- thd->max_client_packet_length= uint3korr(net->read_pos+2);
- end= (char*) net->read_pos+5;
- }
- /*
- Disable those bits which are not supported by the server.
- This is a precautionary measure, if the client lies. See Bug#27944.
- */
- thd->client_capabilities&= server_capabilites;
-
- if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
- thd->variables.sql_mode|= MODE_IGNORE_SPACE;
-#ifdef HAVE_OPENSSL
- DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
- if (thd->client_capabilities & CLIENT_SSL)
- {
- char error_string[1024];
- /* Do the SSL layering. */
- if (!ssl_acceptor_fd)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, error_string))
- {
- DBUG_PRINT("error", ("Failed to accept new SSL connection"));
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- DBUG_PRINT("info", ("Reading user information over SSL layer"));
- if ((pkt_len= my_net_read(net)) == packet_error ||
- pkt_len < NORMAL_HANDSHAKE_SIZE)
- {
- DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
- pkt_len));
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- }
-#endif /* HAVE_OPENSSL */
-
- if (end >= (char*) net->read_pos+ pkt_len +2)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
-
- if (thd->client_capabilities & CLIENT_INTERACTIVE)
- thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
- if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
- opt_using_transactions)
- net->return_status= &thd->server_status;
-
- char *user= end;
- char *passwd= strend(user)+1;
- uint user_len= passwd - user - 1;
- char *db= passwd;
- char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
- char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
- uint dummy_errors;
-
- /*
- Old clients send null-terminated string as password; new clients send
- the size (1 byte) + string (not null-terminated). Hence in case of empty
- password both send '\0'.
-
- This strlen() can't be easily deleted without changing protocol.
-
- Cast *passwd to an unsigned char, so that it doesn't extend the sign for
- *passwd > 127 and become 2**32-127+ after casting to uint.
- */
- uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- (uchar)(*passwd++) : strlen(passwd);
- db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
- db + passwd_len + 1 : 0;
- /* strlen() can't be easily deleted without changing protocol */
- uint db_len= db ? strlen(db) : 0;
-
- if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
-
- /* Since 4.1 all database names are stored in utf8 */
- if (db)
- {
- db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info,
- db, db_len,
- thd->charset(), &dummy_errors)]= 0;
- db= db_buff;
- }
-
- user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
- system_charset_info, user, user_len,
- thd->charset(), &dummy_errors)]= '\0';
- user= user_buff;
-
- /* If username starts and ends in "'", chop them off */
- if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
- {
- user[user_len-1]= 0;
- user++;
- user_len-= 2;
- }
-
- if (thd->main_security_ctx.user)
- x_free(thd->main_security_ctx.user);
- if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
- return 1; /* The error is set by my_strdup(). */
- return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
+ return acl_authenticate(thd, connect_errors, 0);
}
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_insert.cc 2010-03-29 15:13:53 +0000
@@ -1778,8 +1778,10 @@ public:
table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0),
group_count(0)
{
- thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user;
+ thd.security_ctx->user=(char*) delayed_user;
thd.security_ctx->host=(char*) my_localhost;
+ strmake(thd.security_ctx->priv_user, thd.security_ctx->user,
+ USERNAME_LENGTH);
thd.current_tablenr=0;
thd.version=refresh_version;
thd.command=COM_DELAYED_INSERT;
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-03-15 11:51:23 +0000
+++ b/sql/sql_lex.h 2010-03-29 15:13:53 +0000
@@ -952,6 +952,8 @@ extern sys_var *trg_new_row_fake_var;
enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE,
XA_SUSPEND, XA_FOR_MIGRATE};
+extern const LEX_STRING null_lex_str;
+extern const LEX_STRING empty_lex_str;
/*
Class representing list of all tables used by statement.
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-03-16 12:38:35 +0000
+++ b/sql/sql_parse.cc 2010-03-29 15:13:53 +0000
@@ -444,9 +444,8 @@ static void handle_bootstrap_impl(THD *t
thd_proc_info(thd, 0);
thd->version=refresh_version;
- thd->security_ctx->priv_user=
- thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
- thd->security_ctx->priv_host[0]=0;
+ thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
+ thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0;
/*
Make the "client" handle multiple results. This is necessary
to enable stored procedures with SELECTs and Dynamic SQL
@@ -1093,96 +1092,34 @@ bool dispatch_command(enum enum_server_c
case COM_CHANGE_USER:
{
status_var_increment(thd->status_var.com_other);
- char *user= (char*) packet, *packet_end= packet + packet_length;
- /* Safe because there is always a trailing \0 at the end of the packet */
- char *passwd= strend(user)+1;
thd->change_user();
thd->clear_error(); // if errors from rollback
- /*
- Old clients send null-terminated string ('\0' for empty string) for
- password. New clients send the size (1 byte) + string (not null
- terminated, so also '\0' for empty string).
-
- Cast *passwd to an unsigned char, so that it doesn't extend the sign
- for *passwd > 127 and become 2**32-127 after casting to uint.
- */
- char db_buff[NAME_LEN+1]; // buffer to store db in utf8
- char *db= passwd;
- char *save_db;
- /*
- If there is no password supplied, the packet must contain '\0',
- in any type of handshake (4.1 or pre-4.1).
- */
- if (passwd >= packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
- uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- (uchar)(*passwd++) : strlen(passwd));
- uint dummy_errors, save_db_length, db_length;
- int res;
- Security_context save_security_ctx= *thd->security_ctx;
- USER_CONN *save_user_connect;
-
- db+= passwd_len + 1;
- /*
- Database name is always NUL-terminated, so in case of empty database
- the packet must contain at least the trailing '\0'.
- */
- if (db >= packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
- db_length= strlen(db);
-
- char *ptr= db + db_length + 1;
- uint cs_number= 0;
-
- if (ptr < packet_end)
- {
- if (ptr + 2 > packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
-
- cs_number= uint2korr(ptr);
- }
-
- /* Convert database name to utf8 */
- db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info, db, db_length,
- thd->charset(), &dummy_errors)]= 0;
- db= db_buff;
-
- /* Save user and privileges */
- save_db_length= thd->db_length;
- save_db= thd->db;
- save_user_connect= thd->user_connect;
+ /* acl_authenticate() takes the data from net->read_pos */
+ net->read_pos= (uchar*)packet;
- if (!(thd->security_ctx->user= my_strdup(user, MYF(0))))
- {
- thd->security_ctx->user= save_security_ctx.user;
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- break;
- }
-
- /* Clear variables that are allocated */
- thd->user_connect= 0;
- thd->security_ctx->priv_user= thd->security_ctx->user;
- res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
+ uint save_db_length= thd->db_length;
+ char *save_db= thd->db;
+ USER_CONN *save_user_connect= thd->user_connect;
+ Security_context save_security_ctx= *thd->security_ctx;
+ CHARSET_INFO *save_character_set_client=
+ thd->variables.character_set_client;
+ CHARSET_INFO *save_collation_connection=
+ thd->variables.collation_connection;
+ CHARSET_INFO *save_character_set_results=
+ thd->variables.character_set_results;
- if (res)
+ if (acl_authenticate(thd, 0, packet_length))
{
x_free(thd->security_ctx->user);
*thd->security_ctx= save_security_ctx;
thd->user_connect= save_user_connect;
- thd->db= save_db;
- thd->db_length= save_db_length;
+ thd->reset_db(save_db, save_db_length);
+ thd->variables.character_set_client= save_character_set_client;
+ thd->variables.collation_connection= save_collation_connection;
+ thd->variables.character_set_results= save_character_set_results;
+ thd->update_charset();
}
else
{
@@ -1193,12 +1130,6 @@ bool dispatch_command(enum enum_server_c
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
x_free(save_db);
x_free(save_security_ctx.user);
-
- if (cs_number)
- {
- thd_init_client_charset(thd, cs_number);
- thd->update_charset();
- }
}
break;
}
@@ -4348,8 +4279,8 @@ end_with_restore_list:
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL,
- ER(ER_PROC_AUTO_GRANT_FAIL));
+ ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL));
+ thd->clear_error();
}
/*
@@ -7727,8 +7658,9 @@ void get_default_definer(THD *thd, LEX_U
definer->host.str= (char *) sctx->priv_host;
definer->host.length= strlen(definer->host.str);
- definer->password.str= NULL;
- definer->password.length= 0;
+ definer->password= null_lex_str;
+ definer->plugin= empty_lex_str;
+ definer->auth= empty_lex_str;
}
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2010-03-15 11:51:23 +0000
+++ b/sql/sql_plugin.cc 2010-03-29 15:13:53 +0000
@@ -16,6 +16,7 @@
#include "mysql_priv.h"
#include <my_pthread.h>
#include <my_getopt.h>
+#include <mysql/plugin_auth.h>
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
@@ -46,7 +47,10 @@ const LEX_STRING plugin_type_names[MYSQL
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
{ C_STRING_WITH_LEN("FTPARSER") },
{ C_STRING_WITH_LEN("DAEMON") },
- { C_STRING_WITH_LEN("INFORMATION SCHEMA") }
+ { C_STRING_WITH_LEN("INFORMATION SCHEMA") },
+ { C_STRING_WITH_LEN("AUDIT") },
+ { C_STRING_WITH_LEN("REPLICATION") },
+ { C_STRING_WITH_LEN("AUTHENTICATION") }
};
extern int initialize_schema_table(st_plugin_int *plugin);
@@ -59,12 +63,12 @@ extern int finalize_schema_table(st_plug
*/
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
- 0,ha_initialize_handlerton,0,0,initialize_schema_table
+ 0,ha_initialize_handlerton,0,0,initialize_schema_table, 0, 0, 0
};
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
- 0,ha_finalize_handlerton,0,0,finalize_schema_table
+ 0,ha_finalize_handlerton,0,0,finalize_schema_table, 0, 0, 0
};
#ifdef HAVE_DLOPEN
@@ -85,7 +89,10 @@ static int min_plugin_info_interface_ver
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION,
MYSQL_DAEMON_INTERFACE_VERSION,
- MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+ 0xff00, /* audit plugins are supported in a later versions */
+ 0xff00, /* replication plugins are supported in a later versions */
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION
};
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
@@ -93,7 +100,10 @@ static int cur_plugin_info_interface_ver
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION,
MYSQL_DAEMON_INTERFACE_VERSION,
- MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+ 0x0000, /* audit plugins are supported in a later versions */
+ 0x0000, /* replication plugins are supported in a later versions */
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION
};
/* support for Services */
@@ -1013,6 +1023,9 @@ void plugin_unlock_list(THD *thd, plugin
{
LEX *lex= thd ? thd->lex : 0;
DBUG_ENTER("plugin_unlock_list");
+ if (count == 0)
+ DBUG_VOID_RETURN;
+
DBUG_ASSERT(list);
pthread_mutex_lock(&LOCK_plugin);
while (count--)
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-03-15 11:51:23 +0000
+++ b/sql/sql_yacc.yy 2010-03-29 15:13:53 +0000
@@ -56,6 +56,7 @@
int yylex(void *yylval, void *yythd);
const LEX_STRING null_lex_str= {0,0};
+const LEX_STRING empty_lex_str= { (char*) "", 0 };
#define yyoverflow(A,B,C,D,E,F) \
{ \
@@ -1260,8 +1261,9 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token VARIANCE_SYM
%token VARYING /* SQL-2003-R */
%token VAR_SAMP_SYM
-%token VIRTUAL_SYM
+%token VIA_SYM
%token VIEW_SYM /* SQL-2003-N */
+%token VIRTUAL_SYM
%token WAIT_SYM
%token WARNINGS
%token WEEK_SYM
@@ -11673,6 +11675,9 @@ user:
$$->user = $1;
$$->host.str= (char *) "%";
$$->host.length= 1;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
if (check_string_char_length(&$$->user, ER(ER_USERNAME),
USERNAME_CHAR_LENGTH,
@@ -11685,6 +11690,9 @@ user:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1; $$->host=$3;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
if (check_string_char_length(&$$->user, ER(ER_USERNAME),
USERNAME_CHAR_LENGTH,
@@ -12941,6 +12949,18 @@ grant_user:
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$= $1; $1->password= $5; }
+ | user IDENTIFIED_SYM VIA_SYM ident_or_text
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= empty_lex_str;
+ }
+ | user IDENTIFIED_SYM VIA_SYM ident_or_text USING TEXT_STRING_sys
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= $6;
+ }
| user
{ $$= $1; $1->password= null_lex_str; }
;
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2010-02-01 06:14:12 +0000
+++ b/sql/structs.h 2010-03-29 15:13:53 +0000
@@ -178,7 +178,7 @@ extern const char *show_comp_option_name
typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
typedef struct st_lex_user {
- LEX_STRING user, host, password;
+ LEX_STRING user, host, password, plugin, auth;
} LEX_USER;
/*
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2010-03-15 11:51:23 +0000
+++ b/sql/table.cc 2010-03-29 15:13:53 +0000
@@ -4163,11 +4163,8 @@ bool TABLE_LIST::prepare_view_securety_c
{
DBUG_PRINT("info", ("This table is suid view => load contest"));
DBUG_ASSERT(view && view_sctx);
- if (acl_getroot_no_password(view_sctx,
- definer.user.str,
- definer.host.str,
- definer.host.str,
- thd->db))
+ if (acl_getroot(view_sctx, definer.user.str, definer.host.str,
+ definer.host.str, thd->db))
{
if ((thd->lex->sql_command == SQLCOM_SHOW_CREATE) ||
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS))
=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c 2010-03-15 11:51:23 +0000
+++ b/storage/maria/ma_loghandler.c 2010-03-30 12:35:15 +0000
@@ -1275,6 +1275,7 @@ static my_bool translog_set_lsn_for_file
{
LOGHANDLER_FILE_INFO info;
File fd= open_logfile_by_number_no_cache(file);
+ LINT_INIT_STRUCT(info);
if ((fd < 0) ||
((translog_read_file_header(&info, fd) ||
(cmp_translog_addr(lsn, info.max_lsn) > 0 &&
@@ -1457,8 +1458,8 @@ LSN translog_get_file_max_lsn_stored(uin
{
LOGHANDLER_FILE_INFO info;
- LINT_INIT_STRUCT(info);
File fd= open_logfile_by_number_no_cache(file);
+ LINT_INIT_STRUCT(info);
if ((fd < 0) ||
(translog_read_file_header(&info, fd) | my_close(fd, MYF(MY_WME))))
{
@@ -3966,6 +3967,7 @@ my_bool translog_init_with_table(const c
if (!old_log_was_recovered && old_flags == flags)
{
LOGHANDLER_FILE_INFO info;
+ LINT_INIT_STRUCT(info);
/*
Accessing &log_descriptor.open_files without mutex is safe
because it is initialization
@@ -7934,6 +7936,7 @@ my_bool translog_flush(TRANSLOG_ADDRESS
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
LINT_INIT(sent_to_disk);
+ LINT_INIT(flush_interval);
pthread_mutex_lock(&log_descriptor.log_flush_lock);
DBUG_PRINT("info", ("Everything is flushed up to (%lu,0x%lx)",
@@ -8060,18 +8063,14 @@ retest:
/* keep values for soft sync() and forced sync() actual */
{
uint32 fileno= LSN_FILE_NO(lsn);
- my_atomic_rwlock_wrlock(&soft_sync_rwl);
- my_atomic_store32(&soft_sync_min, fileno);
- my_atomic_store32(&soft_sync_max, fileno);
- my_atomic_rwlock_wrunlock(&soft_sync_rwl);
+ soft_sync_min= fileno;
+ soft_sync_max= fileno;
}
}
else
{
- my_atomic_rwlock_wrlock(&soft_sync_rwl);
- my_atomic_store32(&soft_sync_max, LSN_FILE_NO(lsn));
- my_atomic_store32(&soft_need_sync, 1);
- my_atomic_rwlock_wrunlock(&soft_sync_rwl);
+ soft_sync_max= lsn;
+ soft_need_sync= 1;
}
DBUG_ASSERT(flush_horizon <= log_descriptor.horizon);
@@ -8464,9 +8463,7 @@ my_bool translog_purge(TRANSLOG_ADDRESS
translog_status == TRANSLOG_READONLY);
soft= soft_sync;
- my_atomic_rwlock_wrlock(&soft_sync_rwl);
- min_unsync= my_atomic_load32(&soft_sync_min);
- my_atomic_rwlock_wrunlock(&soft_sync_rwl);
+ min_unsync= soft_sync_min;
DBUG_PRINT("info", ("min_unsync: %lu", (ulong) min_unsync));
if (soft && min_unsync < last_need_file)
{
@@ -8748,9 +8745,7 @@ void translog_sync()
uint32 min;
DBUG_ENTER("ma_translog_sync");
- my_atomic_rwlock_rdlock(&soft_sync_rwl);
- min= my_atomic_load32(&soft_sync_min);
- my_atomic_rwlock_rdunlock(&soft_sync_rwl);
+ min= soft_sync_min;
if (!min)
min= max;
@@ -8796,13 +8791,11 @@ ma_soft_sync_background( void *arg __att
ulonglong prev_loop= my_micro_time();
ulonglong time, sleep;
uint32 min, max, sync_request;
- my_atomic_rwlock_rdlock(&soft_sync_rwl);
- min= my_atomic_load32(&soft_sync_min);
- max= my_atomic_load32(&soft_sync_max);
- sync_request= my_atomic_load32(&soft_need_sync);
- my_atomic_store32(&soft_sync_min, max);
- my_atomic_store32(&soft_need_sync, 0);
- my_atomic_rwlock_rdunlock(&soft_sync_rwl);
+ min= soft_sync_min;
+ max= soft_sync_max;
+ sync_request= soft_need_sync;
+ soft_sync_min= max;
+ soft_need_sync= 0;
sleep= group_commit_wait;
if (sync_request)
@@ -8834,15 +8827,13 @@ int translog_soft_sync_start(void)
DBUG_ENTER("translog_soft_sync_start");
/* check and init variables */
- my_atomic_rwlock_rdlock(&soft_sync_rwl);
- min= my_atomic_load32(&soft_sync_min);
- max= my_atomic_load32(&soft_sync_max);
+ min= soft_sync_min;
+ max= soft_sync_max;
if (!max)
- my_atomic_store32(&soft_sync_max, (max= get_current_logfile()->number));
+ soft_sync_max= max= get_current_logfile()->number;
if (!min)
- my_atomic_store32(&soft_sync_min, max);
- my_atomic_store32(&soft_need_sync, 1);
- my_atomic_rwlock_rdunlock(&soft_sync_rwl);
+ soft_sync_min= max;
+ soft_need_sync= 1;
if (!(res= ma_service_thread_control_init(&soft_sync_control)))
if (!(res= pthread_create(&th, NULL, ma_soft_sync_background, NULL)))
@@ -8985,6 +8976,7 @@ static void dump_header_page(uchar *buff
{
LOGHANDLER_FILE_INFO desc;
char strbuff[21];
+ LINT_INIT_STRUCT(desc);
translog_interpret_file_header(&desc, buff);
printf(" This can be header page:\n"
" Timestamp: %s\n"
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-03 14:44:14 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-03-31 18:37:45 +0000
@@ -1215,8 +1215,6 @@ static int pbxt_init(void *p)
THD *thd = NULL;
#ifndef DRIZZLED
- extern myxt_mutex_t LOCK_plugin;
-
/* {MYSQL QUIRK}
* I have to release this lock for PBXT recovery to
* work, because it needs to open .frm files.
=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c 2010-01-11 13:15:28 +0000
+++ b/tests/mysql_client_test.c 2010-03-29 15:13:53 +0000
@@ -34,6 +34,7 @@
#include <m_string.h>
#include <mysqld_error.h>
#include <my_handler.h>
+#include <sql_common.h>
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
1
0

31 Mar '10
Arjen Lentz <arjen(a)openquery.com> writes:
>> On 31 Mar 2010, at 05:14, Arjen Lentz wrote:
>>> I think we need something like
>>> %attr(644, root, root) %{_libdir}/mysql/plugin
Ok, I got it sorted out (it wasn't quite like this, but should be ok now).
> So my preference would be to make it a built-in/regular as it will
> make adopton and subsequent use much easier.
Understand, unfortunately I am out of cycles to look into changing this (I
think it requires some (probably simple) changes in at least plug.in and
mysql-test-run.pl). But I personally have no strong opinion one way or the
other.
Anyway, the good news is I seem to have got everything sorted out. It's
running in Buildbot now, and first few builds look correct on both .deb and
.rpm.
https://buildbot.askmonty.org/buildbot/grid?branch=mariadb-5.2-knielsen
Arjen, I'll try to remember to put the packages up somewhere in case you want
to check them out.
So if everything looks ok to you, I will ask Serg to do second review, and
hopefully things will be sorted!
I'll push here once Launchpad gets back up:
lp:~knielsen/maria/5.2-oqgraph
- Kristian.
3
3

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2838: Added missing space from last push
by noreply@launchpad.net 31 Mar '10
by noreply@launchpad.net 31 Mar '10
31 Mar '10
------------------------------------------------------------
revno: 2838
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Wed 2010-03-31 23:50:54 +0300
message:
Added missing space from last push
Fixed compiler warnings
modified:
mysys/my_gethostbyname.c
storage/xtradb/handler/i_s.cc
storage/xtradb/log/log0recv.c
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2838)
by Michael Widenius 31 Mar '10
by Michael Widenius 31 Mar '10
31 Mar '10
#At lp:maria based on revid:monty@askmonty.org-20100331191221-xg8yj34ld36r2mhe
2838 Michael Widenius 2010-03-31
Added missing space from last push
Fixed compiler warnings
modified:
mysys/my_gethostbyname.c
storage/xtradb/handler/i_s.cc
storage/xtradb/log/log0recv.c
per-file messages:
mysys/my_gethostbyname.c
Added missing space from last push
storage/xtradb/handler/i_s.cc
Removed not used variable
storage/xtradb/log/log0recv.c
Removed not used variable
=== modified file 'mysys/my_gethostbyname.c'
--- a/mysys/my_gethostbyname.c 2010-03-30 12:36:49 +0000
+++ b/mysys/my_gethostbyname.c 2010-03-31 20:50:54 +0000
@@ -95,7 +95,7 @@ struct hostent *
my_gethostbyname_r(const char *name,
struct hostent *result __attribute__((unused)),
char *buffer __attribute__((unused)),
- int buflen__attribute__((unused)),
+ int buflen __attribute__((unused)),
int *h_errnop)
{
struct hostent *hp;
=== modified file 'storage/xtradb/handler/i_s.cc'
--- a/storage/xtradb/handler/i_s.cc 2010-01-28 11:35:10 +0000
+++ b/storage/xtradb/handler/i_s.cc 2010-03-31 20:50:54 +0000
@@ -2988,7 +2988,6 @@ i_s_innodb_admin_command_fill(
COND* cond)
{
TABLE* i_s_table = (TABLE *) tables->table;
- CHARSET_INFO *cs= system_charset_info;
char** query_str;
char* ptr;
char quote = '\0';
=== modified file 'storage/xtradb/log/log0recv.c'
--- a/storage/xtradb/log/log0recv.c 2010-01-15 15:58:25 +0000
+++ b/storage/xtradb/log/log0recv.c 2010-03-31 20:50:54 +0000
@@ -3280,7 +3280,6 @@ recv_recovery_from_checkpoint_finish(voi
#endif /* UNIV_DEBUG */
if (recv_needed_recovery && srv_recovery_stats) {
- FILE* file = stderr;
ulint i;
fprintf(stderr,
1
0

[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2837: Fixed compiler warnings
by noreply@launchpad.net 31 Mar '10
by noreply@launchpad.net 31 Mar '10
31 Mar '10
------------------------------------------------------------
revno: 2837
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Wed 2010-03-31 22:12:21 +0300
message:
Fixed compiler warnings
Fixed random failure in test system
modified:
BUILD/compile-solaris-sparc
cmd-line-utils/libedit/filecomplete.c
mysql-test/suite/rpl/r/rpl_optimize.result
mysql-test/suite/rpl/t/rpl_optimize.test
support-files/compiler_warnings.supp
--
lp:maria
https://code.launchpad.net/~maria-captains/maria/5.1
Your team Maria developers is subscribed to branch lp:maria.
To unsubscribe from this branch go to https://code.launchpad.net/~maria-captains/maria/5.1/+edit-subscription
1
0

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2837)
by Michael Widenius 31 Mar '10
by Michael Widenius 31 Mar '10
31 Mar '10
#At lp:maria based on revid:monty@askmonty.org-20100330123649-z64q052mcmpe049v
2837 Michael Widenius 2010-03-31
Fixed compiler warnings
Fixed random failure in test system
modified:
BUILD/compile-solaris-sparc
cmd-line-utils/libedit/filecomplete.c
mysql-test/suite/rpl/r/rpl_optimize.result
mysql-test/suite/rpl/t/rpl_optimize.test
support-files/compiler_warnings.supp
per-file messages:
BUILD/compile-solaris-sparc
Addex EXTRA_FLAGS to configure line (to get rid of warnings for not initialzed variables on buildbot)
cmd-line-utils/libedit/filecomplete.c
Remove not used variables
mysql-test/suite/rpl/r/rpl_optimize.result
Updated result
mysql-test/suite/rpl/t/rpl_optimize.test
Use sync_salve_with_master to ensure cleanup on slave
support-files/compiler_warnings.supp
Added suppression of libedit files
=== modified file 'BUILD/compile-solaris-sparc'
--- a/BUILD/compile-solaris-sparc 2008-09-30 20:57:48 +0000
+++ b/BUILD/compile-solaris-sparc 2010-03-31 19:12:21 +0000
@@ -9,6 +9,6 @@ PATH=$PATH:/usr/ccs/bin:/usr/local/bin
path=`dirname $0`
. "$path/autorun.sh"
-CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" LIBS="-lmtmalloc" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa $EXTRA_FLAGS $EXTRA_CFLAGS" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g $EXTRA_FLAGS $EXTRA_CXXFLAGS" LIBS="-lmtmalloc" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
make -j 4
=== modified file 'cmd-line-utils/libedit/filecomplete.c'
--- a/cmd-line-utils/libedit/filecomplete.c 2009-04-30 11:53:30 +0000
+++ b/cmd-line-utils/libedit/filecomplete.c 2010-03-31 19:12:21 +0000
@@ -95,10 +95,9 @@ static char break_chars[] = { ' ', '\t',
char *
fn_tilde_expand(const char *txt)
{
- struct passwd pwres, *pass;
+ struct passwd *pass;
char *temp;
size_t len = 0;
- char pwbuf[1024];
if (txt[0] != '~')
return (strdup(txt));
=== modified file 'mysql-test/suite/rpl/r/rpl_optimize.result'
--- a/mysql-test/suite/rpl/r/rpl_optimize.result 2010-01-13 09:00:03 +0000
+++ b/mysql-test/suite/rpl/r/rpl_optimize.result 2010-03-31 19:12:21 +0000
@@ -4,6 +4,7 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+drop tables if exists t1;
CALL mtr.add_suppression('Statement may not be safe to log in statement format.');
create table t1 (a int not null auto_increment primary key, b int, key(b));
INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
=== modified file 'mysql-test/suite/rpl/t/rpl_optimize.test'
--- a/mysql-test/suite/rpl/t/rpl_optimize.test 2010-03-04 08:03:07 +0000
+++ b/mysql-test/suite/rpl/t/rpl_optimize.test 2010-03-31 19:12:21 +0000
@@ -15,6 +15,10 @@
-- source include/not_staging.inc
-- source include/master-slave.inc
+--disable_warnings
+drop tables if exists t1;
+--enable_warnings
+
CALL mtr.add_suppression('Statement may not be safe to log in statement format.');
create table t1 (a int not null auto_increment primary key, b int, key(b));
@@ -51,10 +55,9 @@ sync_with_master; # won't work if slave
connection master; # cleanup
drop table t1;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
# If the machine is so fast that slave syncs before OPTIMIZE
-# starts, this test wil demonstrate nothing but will pass.
+# starts, this test will demonstrate nothing but will pass.
# End of 4.1 tests
=== modified file 'support-files/compiler_warnings.supp'
--- a/support-files/compiler_warnings.supp 2010-03-30 12:36:49 +0000
+++ b/support-files/compiler_warnings.supp 2010-03-31 19:12:21 +0000
@@ -54,6 +54,12 @@ db_vrfy.c : .*comparison is always false
# readline is not maintained by us
#
.*/cmd-line-utils/readline/.* : .*
+readline\.c : unused parameter
+term\.c : unused parameter
+vi\.c : unused parameter
+common\.c : unused parameter
+term\.c : *.*
+
#
# Ignore some warnings in libevent, which is not maintained by us.
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2744)
by Igor Babaev 31 Mar '10
by Igor Babaev 31 Mar '10
31 Mar '10
#At lp:maria/5.2 based on revid:igor@askmonty.org-20100329211612-d7f7utiqasfk0ups
2744 Igor Babaev 2010-03-31
Adjusted results
modified:
mysql-test/r/key_cache.result
mysql-test/suite/pbxt/r/mysqlshow.result
mysql-test/t/key_cache.test
=== modified file 'mysql-test/r/key_cache.result'
--- a/mysql-test/r/key_cache.result 2010-02-16 16:41:11 +0000
+++ b/mysql-test/r/key_cache.result 2010-03-31 18:45:41 +0000
@@ -467,18 +467,18 @@ Key_write_requests 26
Key_writes 6
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 3 # 0 10 0 13 4
-default 2 2 1048576 1024 1 # 0 12 0 13 2
-default 2 NULL 2097152 1024 4 # 0 22 0 26 6
-small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+default 2 1 1048576 1024 # # 0 10 0 13 4
+default 2 2 1048576 1024 # # 0 12 0 13 2
+default 2 NULL 2097152 1024 # # 0 22 0 26 6
+small NULL NULL 1048576 1024 # # 0 1 0 2 1
delete from t1;
delete from t2;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
-default 2 1 1048576 1024 3 # 0 10 0 13 4
-default 2 2 1048576 1024 1 # 0 12 0 13 2
-default 2 NULL 2097152 1024 4 # 0 22 0 26 6
-small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+default 2 1 1048576 1024 # # 0 10 0 13 4
+default 2 2 1048576 1024 # # 0 12 0 13 2
+default 2 NULL 2097152 1024 # # 0 22 0 26 6
+small NULL NULL 1048576 1024 # # 0 1 0 2 1
set global key_cache_partitions=1;
select @@key_cache_partitions;
@@key_cache_partitions
=== modified file 'mysql-test/suite/pbxt/r/mysqlshow.result'
--- a/mysql-test/suite/pbxt/r/mysqlshow.result 2010-02-01 06:14:12 +0000
+++ b/mysql-test/suite/pbxt/r/mysqlshow.result 2010-03-31 18:45:41 +0000
@@ -91,6 +91,7 @@ Database: information_schema
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -144,6 +145,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
=== modified file 'mysql-test/t/key_cache.test'
--- a/mysql-test/t/key_cache.test 2010-02-16 16:41:11 +0000
+++ b/mysql-test/t/key_cache.test 2010-03-31 18:45:41 +0000
@@ -316,12 +316,12 @@ update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
---replace_column 7 #
+--replace_column 6 # 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
---replace_column 7 #
+--replace_column 6 # 7 #
select * from information_schema.key_caches;
# Check that we can work with one partition with the same results
1
0

[Maria-developers] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (monty:2761)
by Michael Widenius 31 Mar '10
by Michael Widenius 31 Mar '10
31 Mar '10
#At lp:maria/5.2 based on revid:sanja@askmonty.org-20100330123515-4p8q03xccl3d6k59
2761 Michael Widenius 2010-03-31
Fixed some compiler warnings
modified:
include/m_ctype.h
plugin/auth/dialog.c
sql/sql_acl.cc
storage/pbxt/src/ha_pbxt.cc
per-file messages:
include/m_ctype.h
MY_UNICASE_INFO already includes 'const'
plugin/auth/dialog.c
Fixed parameters to have correct signed/unsigned type
sql/sql_acl.cc
old_password_plugin is not used for EMBEDDED_LIBRARY
storage/pbxt/src/ha_pbxt.cc
Remove not used variable
=== modified file 'include/m_ctype.h'
--- a/include/m_ctype.h 2010-01-06 19:20:16 +0000
+++ b/include/m_ctype.h 2010-03-31 18:37:45 +0000
@@ -291,7 +291,7 @@ struct charset_info_st
const uint16 *const *sort_order_big;
const uint16 *tab_to_uni;
MY_UNI_IDX *tab_from_uni;
- const MY_UNICASE_INFO *const *caseinfo;
+ MY_UNICASE_INFO *const *caseinfo;
const uchar *state_map;
const uchar *ident_map;
uint strxfrm_multiply;
=== modified file 'plugin/auth/dialog.c'
--- a/plugin/auth/dialog.c 2010-03-29 15:13:53 +0000
+++ b/plugin/auth/dialog.c 2010-03-31 18:37:45 +0000
@@ -51,6 +51,8 @@
#define PASSWORD_QUESTION "\4"
#define LAST_PASSWORD "\5"
+typedef unsigned char uchar;
+
/********************* SERVER SIDE ****************************************/
/**
@@ -63,7 +65,9 @@ static int two_questions(MYSQL_PLUGIN_VI
int pkt_len;
/* send a password question */
- if (vio->write_packet(vio, PASSWORD_QUESTION "Password, please:", 18))
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"),
+ 18))
return CR_ERROR;
/* read the answer */
@@ -73,11 +77,12 @@ static int two_questions(MYSQL_PLUGIN_VI
info->password_used = 1;
/* fail if the password is wrong */
- if (strcmp(pkt, info->auth_string))
+ if (strcmp((char*) pkt, info->auth_string))
return CR_ERROR;
/* send the last, ordinary, question */
- if (vio->write_packet(vio, LAST_QUESTION "Are you sure ?", 15))
+ if (vio->write_packet(vio,
+ (const uchar*) (LAST_QUESTION "Are you sure ?"), 15))
return CR_ERROR;
/* read the answer */
@@ -85,7 +90,7 @@ static int two_questions(MYSQL_PLUGIN_VI
return CR_ERROR;
/* check the reply */
- return strcmp(pkt, "yes, of course") ? CR_ERROR : CR_OK;
+ return strcmp((char*) pkt, "yes, of course") ? CR_ERROR : CR_OK;
}
static struct st_mysql_auth two_handler=
@@ -108,7 +113,8 @@ static int three_attempts(MYSQL_PLUGIN_V
for (i= 0; i < 3; i++)
{
/* send the prompt */
- if (vio->write_packet(vio, PASSWORD_QUESTION "Password, please:", 18))
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"), 18))
return CR_ERROR;
/* read the password */
@@ -121,7 +127,7 @@ static int three_attempts(MYSQL_PLUGIN_V
finish, if the password is correct.
note, that we did not mark the prompt packet as "last"
*/
- if (strcmp(pkt, info->auth_string) == 0)
+ if (strcmp((char*) pkt, info->auth_string) == 0)
return CR_OK;
}
@@ -255,12 +261,12 @@ static int perform_dialog(MYSQL_PLUGIN_V
if ((cmd >> 1) == 2 && *pkt == 0)
reply= mysql->passwd;
else
- reply= ask(mysql, cmd >> 1, pkt, reply_buf, sizeof(reply_buf));
+ reply= ask(mysql, cmd >> 1, (char*) pkt, reply_buf, sizeof(reply_buf));
if (!reply)
return CR_ERROR;
}
/* send the reply to the server */
- res= vio->write_packet(vio, reply, strlen(reply)+1);
+ res= vio->write_packet(vio, (uchar*) reply, strlen(reply)+1);
if (reply != mysql->passwd && reply != reply_buf)
free(reply);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-03-29 15:13:53 +0000
+++ b/sql/sql_acl.cc 2010-03-31 18:37:45 +0000
@@ -161,7 +161,10 @@ static LEX_STRING old_password_plugin_na
/// @todo make it configurable
LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
-static plugin_ref native_password_plugin, old_password_plugin;
+static plugin_ref native_password_plugin;
+#ifndef EMBEDDED_LIBRARY
+static plugin_ref old_password_plugin;
+#endif
/* Classes */
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc 2010-03-03 14:44:14 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc 2010-03-31 18:37:45 +0000
@@ -1215,8 +1215,6 @@ static int pbxt_init(void *p)
THD *thd = NULL;
#ifndef DRIZZLED
- extern myxt_mutex_t LOCK_plugin;
-
/* {MYSQL QUIRK}
* I have to release this lock for PBXT recovery to
* work, because it needs to open .frm files.
1
0

[Maria-developers] Rev 31: Merge. in file:///Users/hakan/work/monty_program/mariadb-tools/
by Hakan Kuecuekyilmaz 31 Mar '10
by Hakan Kuecuekyilmaz 31 Mar '10
31 Mar '10
At file:///Users/hakan/work/monty_program/mariadb-tools/
------------------------------------------------------------
revno: 31 [merge]
revision-id: hakan(a)askmonty.org-20100331181744-71hyuyjjlijrsl68
parent: hakan(a)askmonty.org-20100331181651-pxx2ep0u5658d6q1
parent: knielsen@hasky-20100329172857-9qy2lqbl892ikh89
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: mariadb-tools
timestamp: Wed 2010-03-31 20:17:44 +0200
message:
Merge.
modified:
buildbot/maria-master.cfg mariamaster.cfg-20091218103450-cvifjz3i70oerkej-1
=== modified file 'buildbot/maria-master.cfg'
--- a/buildbot/maria-master.cfg 2010-02-23 07:48:54 +0000
+++ b/buildbot/maria-master.cfg 2010-03-29 17:28:57 +0000
@@ -114,7 +114,8 @@
"lp:~maria-captains/maria/5.2-dsmrr" : "5.2-dsmrr",
"lp:~maria-captains/maria/5.3" : "5.3",
"lp:~maria-captains/maria/5.3-sj-subqueries" : "5.3-sj-subqueries",
- "lp:~maria-captains/maria/5.3-subqueries" : "5.3-subqueries"
+ "lp:~maria-captains/maria/5.3-subqueries" : "5.3-subqueries",
+ "lp:~maria-captains/maria/maria-5.2-wl85" : "maria-5.2-wl85"
}
mailSource = mail.BzrLaunchpadEmailMaildirSource("/var/lib/buildbot/Maildir",
branchMap=myBranchMap)
@@ -155,11 +156,11 @@
"mariadb-5.1-monty", "mariadb-5.2-monty",
"mariadb-5.1-knielsen","5.1-release", "5.1-merge",
"maria-5.1-wl24", "maria-5.1-vcol","maria-5.1-wl36","mysql-5.1-mwl36",
- "5.1.39-oqgraph", "5.2-dsmrr", "5.3", "5.3-sj-subqueries", "5.3-subqueries"
+ "5.1.39-oqgraph", "5.2-dsmrr", "5.3", "5.3-sj-subqueries", "5.3-subqueries",
+ "maria-5.2-wl85"
],
treeStableTimer=60, # 1 sec for bzr
- builderNames=["centos5-debug", "hardy-x86-rtai", "hardy-amd64-makedist",
- "hardy-amd64-dbg",
+ builderNames=["centos5-debug", "hardy-amd64-makedist",
# "lenny-amd64-dbg", "adutko-alpha",
"debian5-i386-fulltest",
"jaunty-x86-valgrind", "jaunty-amd64-rel",
@@ -170,6 +171,19 @@
"sol10-amd64-dbg", "sol10-sparc32-forte", "sol10-sparc64-forte",
"sol-sparc-32"]))
+# A scheduler for less powerful hosts, only run on most important branches.
+c['schedulers'].append(AnyBranchScheduler(
+ name="mariadb-light",
+ branches=["5.1", "5.2",
+ "mariadb-5.1-knielsen",
+ "5.1-release", "5.1-merge",
+ "5.2-release", "5.2-merge",
+ "5.3-release", "5.3-merge",
+ ],
+ treeStableTimer=60, # 1 sec for bzr
+ builderNames=["hardy-x86-rtai", "hardy-amd64-dbg",
+ ]))
+
c['schedulers'].append(Triggerable(
name="tarbuild-sched",
builderNames=["win32-tarball", "win32-make-noinstall-zip", "centos5-amd64-minimal"]))
@@ -298,7 +312,7 @@
f1.addStep(getMTR(
test_type="nm",
test_info="Valgrind run, no --ps-protocol",
- command=["sh", "-c", "cd mysql-test && exec perl mysql-test-run.pl --mem --parallel=3 --valgrind --force --retry=3 --skip-ndb"]))
+ command=["sh", "-c", "cd mysql-test && exec perl mysql-test-run.pl --mem --parallel=3 --valgrind --valgrind-option=--show-reachable=yes --valgrind-option=--gen-suppressions=all --force --retry=3 --skip-ndb"]))
bld_valgrind = {'name': "hardy-amd64-valgrind",
'slavename': "valgrind",
@@ -428,7 +442,8 @@
f_rel_1_32 = factory.BuildFactory()
f_rel_1_32.addStep(bzr_checkout)
-f_rel_1_32.addStep(getCompileStep(["BUILD/compile-pentium-max"]))
+f_rel_1_32.addStep(getCompileStep(["BUILD/compile-pentium-max"],
+ env={"AM_MAKEFLAGS": "-j1", "EXTRA_FLAGS": "-DFORCE_INIT_OF_VARS"}))
# --testcase-timeout as this host is really slow at some tests.
f_rel_1_32.addStep(getMTR(
test_type="nm",
@@ -482,6 +497,7 @@
'slavename': "archivist-cnc",
'builddir': "archivist-cnc",
'factory': f_rel_1_32,
+ "env": { "AM_MAKEFLAGS": "-j1" },
"category": "experimental",
}
@@ -489,6 +505,7 @@
'slavename': "archivist-amd64",
'builddir': "archivist-amd64",
'factory': f_dbg_2_64,
+ "env": { "AM_MAKEFLAGS": "-j1" },
"category": "main",
}
@@ -514,7 +531,7 @@
command=["sh", "-c", WithProperties("rm -Rf %(distname)s && tar zxf %(distname)s.tar.gz")]))
f_minimal.addStep(getCompileStep(
["sh", "-c", WithProperties("cd %(distname)s && ./configure --without-uca --without-query-cache --without-geomery --without-readline --without-libedit --without-embedded-server --without-plugin-example --without-plugin-innobase --without-plugin-federated --without-plugin-pbxt --without-plugin-partition --without-plugin-daemon_example --without-plugin-ftexample --without-plugin-archive --without-plugin-blackhole --without-plugin-ibmdb2i --without-plugin-ndbcluster && make -j3")],
- subdir="%(distname)s"))
+ subdir="%(distname)s/"))
f_minimal.addStep(getMTR(
test_type="nm",
test_info="Normal run, no --ps-protocol",
@@ -1134,8 +1151,9 @@
bld_kvm_deb_lucid_x86 = getDebBuilder("kvm-deb-lucid-x86", "vm-lucid-i386", "2239", "qemu32,-nx")
bld_kvm_deb_debian5_amd64 = getDebBuilder("kvm-deb-debian5-amd64", "vm-debian5-amd64", "2234", "qemu64")
bld_kvm_deb_debian5_x86 = getDebBuilder("kvm-deb-debian5-x86", "vm-debian5-i386", "2226", "qemu32,-nx")
-bld_kvm_deb_debian4_amd64 = getDebBuilder("kvm-deb-debian4-amd64", "vm-debian4-amd64", "2240", "qemu64", kvmargs=["--netdev=e1000", "--kvm=-cdrom", "--kvm=/kvm/debian-40r8-amd64-netinst.iso"])
-bld_kvm_deb_debian4_x86 = getDebBuilder("kvm-deb-debian4-x86", "vm-debian4-i386", "2241", "qemu32,-nx", kvmargs=["--netdev=e1000", "--kvm=-cdrom", "--kvm=/kvm/debian-40r8-i386-netinst.iso"])
+# Some serious kvm/kernel problem on debian4, need aggressive retry
+bld_kvm_deb_debian4_amd64 = getDebBuilder("kvm-deb-debian4-amd64", "vm-debian4-amd64", "2240", "qemu64", kvmargs=["--netdev=e1000", "--kvm-retries=20", "--kvm=-cdrom", "--kvm=/kvm/debian-40r8-amd64-netinst.iso"])
+bld_kvm_deb_debian4_x86 = getDebBuilder("kvm-deb-debian4-x86", "vm-debian4-i386", "2241", "qemu32,-nx", kvmargs=["--netdev=e1000", "--kvm-retries=20", "--kvm=-cdrom", "--kvm=/kvm/debian-40r8-i386-netinst.iso"])
def getBintarBuilder(name, kvm_image, port, cpu):
@@ -1221,7 +1239,7 @@
description="untarring", descriptionDone="untar",
command=["sh", "-c", WithProperties("rm -Rf %(distdirname)s && tar zxf %(distname)s")]))
f_sol_64_bintar.addStep(getCompileStep(["sh", "-c", WithProperties("cd %(distdirname)s && BUILD/compile-solaris-amd64-debug")],
- subdir="%(distdirname)s"))
+ subdir="%(distdirname)s/"))
f_sol_64_bintar.addStep(ShellCommand(
description="packaging", descriptionDone="package",
command=["sh", "-c", WithProperties("""
1
0

[Maria-developers] Rev 30: Added necessary options for mysql client calls. in file:///Users/hakan/work/monty_program/mariadb-tools/
by Hakan Kuecuekyilmaz 31 Mar '10
by Hakan Kuecuekyilmaz 31 Mar '10
31 Mar '10
At file:///Users/hakan/work/monty_program/mariadb-tools/
------------------------------------------------------------
revno: 30
revision-id: hakan(a)askmonty.org-20100331181651-pxx2ep0u5658d6q1
parent: hakan(a)askmonty.org-20100329105306-6hthpbelo9xop3kw
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: mariadb-tools
timestamp: Wed 2010-03-31 20:16:51 +0200
message:
Added necessary options for mysql client calls.
=== modified file 'sysbench/run-sysbench-myisam.sh'
--- a/sysbench/run-sysbench-myisam.sh 2010-03-29 10:53:06 +0000
+++ b/sysbench/run-sysbench-myisam.sh 2010-03-31 18:16:51 +0000
@@ -70,6 +70,7 @@
# Variables.
#
MY_SOCKET="/tmp/mysql.sock"
+MYSQL_OPTIONS="-uroot --socket=$MY_SOCKET"
MYSQLADMIN_OPTIONS="--no-defaults -uroot --socket=$MY_SOCKET"
MYSQLD_OPTIONS="--no-defaults \
--datadir=$DATA_DIR \
@@ -334,10 +335,11 @@
start_mysqld
sync
+ echo ""
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting warm up of $WARM_UP_TIME seconds."
$SYSBENCH $SYSBENCH_OPTIONS_WARM_UP run
sync
- echo 'FLUSH STATUS' | $MYSQL -uroot
+ echo 'FLUSH STATUS' | $MYSQL $MYSQL_OPTIONS
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Finnished warm up."
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting actual sysbench run."
@@ -345,7 +347,7 @@
grep "write requests:" ${THIS_RESULT_DIR}/result${k}.txt | awk '{ print $4 }' | sed -e 's/(//' >> ${THIS_RESULT_DIR}/results.txt
- echo 'SELECT * FROM INFORMATION_SCHEMA.KEY_CACHES' | $MYSQL -uroot > ${THIS_RESULT_DIR}/key_cache_stats${k}.txt
+ echo 'SELECT * FROM INFORMATION_SCHEMA.KEY_CACHES' | $MYSQL $MYSQL_OPTIONS > ${THIS_RESULT_DIR}/key_cache_stats${k}.txt
k=$(($k + 1))
done
=== modified file 'sysbench/run-sysbench.sh'
--- a/sysbench/run-sysbench.sh 2010-03-25 01:42:05 +0000
+++ b/sysbench/run-sysbench.sh 2010-03-31 18:16:51 +0000
@@ -327,6 +327,7 @@
start_mysqld
sync
+ echo ""
echo "[$(date "+%Y-%m-%d %H:%M:%S")] Starting warm up of $WARM_UP_TIME seconds."
$SYSBENCH $SYSBENCH_OPTIONS_WARM_UP run
sync
1
0

[Maria-developers] Updated (by Knielsen): Merge OQGraph into MariaDB (112)
by worklog-noreply@askmonty.org 31 Mar '10
by worklog-noreply@askmonty.org 31 Mar '10
31 Mar '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Merge OQGraph into MariaDB
CREATION DATE..: Mon, 29 Mar 2010, 18:00
SUPERVISOR.....: Knielsen
IMPLEMENTOR....: Knielsen
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 112 (http://askmonty.org/worklog/?tid=112)
VERSION........: Server-5.2
STATUS.........: Code-Review
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 15 (hours remain)
ORIG. ESTIMATE.: 15
PROGRESS NOTES:
-=-=(Knielsen - Wed, 31 Mar 2010, 13:38)=-=-
Status updated.
--- /tmp/wklog.112.old.12166 2010-03-31 13:38:25.000000000 +0000
+++ /tmp/wklog.112.new.12166 2010-03-31 13:38:25.000000000 +0000
@@ -1 +1 @@
-Assigned
+Code-Review
-=-=(Knielsen - Wed, 31 Mar 2010, 13:38)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.12070 2010-03-31 13:38:08.000000000 +0000
+++ /tmp/wklog.112.new.12070 2010-03-31 13:38:08.000000000 +0000
@@ -15,3 +15,5 @@
Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
if such boost is found.
+Update the packaging in ourdelta/bakery to include the oqgraph_engine.so and
+link with g++ rather than gcc.
-=-=(Knielsen - Mon, 29 Mar 2010, 21:46)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.31142 2010-03-29 21:46:11.000000000 +0000
+++ /tmp/wklog.112.new.31142 2010-03-29 21:46:11.000000000 +0000
@@ -1,28 +1,17 @@
Tasks:
-Find the latest version of OQGraph to base this on (there should be a
-Launchpad branch somewhere, match it up with what is in the OQGraph patch for
-MySQL 5.0 in the ourdelta stuff).
-
-Extract the correct version of Boost from the MySQL 5.0 ourdelta patch. This
-is a patched version of Boost fixing a bug that is supposedly fatal for
-OQGraph (details are not known at the time of writing).
+Base work on the Launchpad branch lp:~knielsen/maria/mariadb-5.1-oqgraph
-Document in OQGraph README the need for boost of a specific version, and point
-to where it can be obtained. Also include the patch for boost if the correct
-base version of boost to do this against can be determined.
+OQGraph requires Boost >= 1.40.0 (earlier versions have a bug that affects
+OQGraph).
-Install the patched boost in /usr/local/ on the build machines (release builds
-and selected Buildbot slaves).
+Document in OQGraph README the need for boost of a specific version, and point
+to where it can be obtained.
-Fix OQGraph plug.in to detect correct version of OQGraph that makes the build
-not break. Check which version in Ubuntu starts working (I think it was
-Jaunty), and require at least that version.
-
-Setup some repository or source tarball of the patched boost
-somewhere. Preferably a Launchpad branch or similar (if upstream project can
-be found).
+Install the patched boost in /usr/local/include/boost on the build machines
+(release builds and selected Buildbot slaves). G++ seems to by default look in
+/usr/local/include, so that is sufficient to find it.
-Setup in plug.in or /configure.in appropriate --with-boost=xxx. Or in a pinch,
-we can make do with CFLAGS=-Ixxx, or even default look in /usr/local/.
+Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
+if such boost is found.
-=-=(Knielsen - Mon, 29 Mar 2010, 18:09)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.23061 2010-03-29 18:09:27.000000000 +0000
+++ /tmp/wklog.112.new.23061 2010-03-29 18:09:27.000000000 +0000
@@ -1 +1,28 @@
+Tasks:
+
+Find the latest version of OQGraph to base this on (there should be a
+Launchpad branch somewhere, match it up with what is in the OQGraph patch for
+MySQL 5.0 in the ourdelta stuff).
+
+Extract the correct version of Boost from the MySQL 5.0 ourdelta patch. This
+is a patched version of Boost fixing a bug that is supposedly fatal for
+OQGraph (details are not known at the time of writing).
+
+Document in OQGraph README the need for boost of a specific version, and point
+to where it can be obtained. Also include the patch for boost if the correct
+base version of boost to do this against can be determined.
+
+Install the patched boost in /usr/local/ on the build machines (release builds
+and selected Buildbot slaves).
+
+Fix OQGraph plug.in to detect correct version of OQGraph that makes the build
+not break. Check which version in Ubuntu starts working (I think it was
+Jaunty), and require at least that version.
+
+Setup some repository or source tarball of the patched boost
+somewhere. Preferably a Launchpad branch or similar (if upstream project can
+be found).
+
+Setup in plug.in or /configure.in appropriate --with-boost=xxx. Or in a pinch,
+we can make do with CFLAGS=-Ixxx, or even default look in /usr/local/.
DESCRIPTION:
Get the OQGraph storage engine merged into MariaDB, fixing the remaining
problems blocking the merge.
HIGH-LEVEL SPECIFICATION:
Tasks:
Base work on the Launchpad branch lp:~knielsen/maria/mariadb-5.1-oqgraph
OQGraph requires Boost >= 1.40.0 (earlier versions have a bug that affects
OQGraph).
Document in OQGraph README the need for boost of a specific version, and point
to where it can be obtained.
Install the patched boost in /usr/local/include/boost on the build machines
(release builds and selected Buildbot slaves). G++ seems to by default look in
/usr/local/include, so that is sufficient to find it.
Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
if such boost is found.
Update the packaging in ourdelta/bakery to include the oqgraph_engine.so and
link with g++ rather than gcc.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Knielsen): Merge OQGraph into MariaDB (112)
by worklog-noreply@askmonty.org 31 Mar '10
by worklog-noreply@askmonty.org 31 Mar '10
31 Mar '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Merge OQGraph into MariaDB
CREATION DATE..: Mon, 29 Mar 2010, 18:00
SUPERVISOR.....: Knielsen
IMPLEMENTOR....: Knielsen
COPIES TO......:
CATEGORY.......: Server-Sprint
TASK ID........: 112 (http://askmonty.org/worklog/?tid=112)
VERSION........: Server-5.2
STATUS.........: Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 15 (hours remain)
ORIG. ESTIMATE.: 15
PROGRESS NOTES:
-=-=(Knielsen - Wed, 31 Mar 2010, 13:38)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.12070 2010-03-31 13:38:08.000000000 +0000
+++ /tmp/wklog.112.new.12070 2010-03-31 13:38:08.000000000 +0000
@@ -15,3 +15,5 @@
Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
if such boost is found.
+Update the packaging in ourdelta/bakery to include the oqgraph_engine.so and
+link with g++ rather than gcc.
-=-=(Knielsen - Mon, 29 Mar 2010, 21:46)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.31142 2010-03-29 21:46:11.000000000 +0000
+++ /tmp/wklog.112.new.31142 2010-03-29 21:46:11.000000000 +0000
@@ -1,28 +1,17 @@
Tasks:
-Find the latest version of OQGraph to base this on (there should be a
-Launchpad branch somewhere, match it up with what is in the OQGraph patch for
-MySQL 5.0 in the ourdelta stuff).
-
-Extract the correct version of Boost from the MySQL 5.0 ourdelta patch. This
-is a patched version of Boost fixing a bug that is supposedly fatal for
-OQGraph (details are not known at the time of writing).
+Base work on the Launchpad branch lp:~knielsen/maria/mariadb-5.1-oqgraph
-Document in OQGraph README the need for boost of a specific version, and point
-to where it can be obtained. Also include the patch for boost if the correct
-base version of boost to do this against can be determined.
+OQGraph requires Boost >= 1.40.0 (earlier versions have a bug that affects
+OQGraph).
-Install the patched boost in /usr/local/ on the build machines (release builds
-and selected Buildbot slaves).
+Document in OQGraph README the need for boost of a specific version, and point
+to where it can be obtained.
-Fix OQGraph plug.in to detect correct version of OQGraph that makes the build
-not break. Check which version in Ubuntu starts working (I think it was
-Jaunty), and require at least that version.
-
-Setup some repository or source tarball of the patched boost
-somewhere. Preferably a Launchpad branch or similar (if upstream project can
-be found).
+Install the patched boost in /usr/local/include/boost on the build machines
+(release builds and selected Buildbot slaves). G++ seems to by default look in
+/usr/local/include, so that is sufficient to find it.
-Setup in plug.in or /configure.in appropriate --with-boost=xxx. Or in a pinch,
-we can make do with CFLAGS=-Ixxx, or even default look in /usr/local/.
+Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
+if such boost is found.
-=-=(Knielsen - Mon, 29 Mar 2010, 18:09)=-=-
High-Level Specification modified.
--- /tmp/wklog.112.old.23061 2010-03-29 18:09:27.000000000 +0000
+++ /tmp/wklog.112.new.23061 2010-03-29 18:09:27.000000000 +0000
@@ -1 +1,28 @@
+Tasks:
+
+Find the latest version of OQGraph to base this on (there should be a
+Launchpad branch somewhere, match it up with what is in the OQGraph patch for
+MySQL 5.0 in the ourdelta stuff).
+
+Extract the correct version of Boost from the MySQL 5.0 ourdelta patch. This
+is a patched version of Boost fixing a bug that is supposedly fatal for
+OQGraph (details are not known at the time of writing).
+
+Document in OQGraph README the need for boost of a specific version, and point
+to where it can be obtained. Also include the patch for boost if the correct
+base version of boost to do this against can be determined.
+
+Install the patched boost in /usr/local/ on the build machines (release builds
+and selected Buildbot slaves).
+
+Fix OQGraph plug.in to detect correct version of OQGraph that makes the build
+not break. Check which version in Ubuntu starts working (I think it was
+Jaunty), and require at least that version.
+
+Setup some repository or source tarball of the patched boost
+somewhere. Preferably a Launchpad branch or similar (if upstream project can
+be found).
+
+Setup in plug.in or /configure.in appropriate --with-boost=xxx. Or in a pinch,
+we can make do with CFLAGS=-Ixxx, or even default look in /usr/local/.
DESCRIPTION:
Get the OQGraph storage engine merged into MariaDB, fixing the remaining
problems blocking the merge.
HIGH-LEVEL SPECIFICATION:
Tasks:
Base work on the Launchpad branch lp:~knielsen/maria/mariadb-5.1-oqgraph
OQGraph requires Boost >= 1.40.0 (earlier versions have a bug that affects
OQGraph).
Document in OQGraph README the need for boost of a specific version, and point
to where it can be obtained.
Install the patched boost in /usr/local/include/boost on the build machines
(release builds and selected Buildbot slaves). G++ seems to by default look in
/usr/local/include, so that is sufficient to find it.
Fix OQGraph plug.in to detect boost version >= 1.40.0, and only enable OQGraph
if such boost is found.
Update the packaging in ourdelta/bakery to include the oqgraph_engine.so and
link with g++ rather than gcc.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0