developers
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 5 participants
- 6819 discussions
[Maria-developers] Updated (by Alexi): Add a mysqlbinlog option to filter updates to certain tables (40)
by worklog-noreply@askmonty.org 02 Nov '09
by worklog-noreply@askmonty.org 02 Nov '09
02 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add a mysqlbinlog option to filter updates to certain tables
CREATION DATE..: Mon, 10 Aug 2009, 13:25
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Psergey
CATEGORY.......: Server-RawIdeaBin
TASK ID........: 40 (http://askmonty.org/worklog/?tid=40)
VERSION........: Server-9.x
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Alexi - Mon, 02 Nov 2009, 11:20)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.4848 2009-11-02 11:20:24.000000000 +0200
+++ /tmp/wklog.40.new.4848 2009-11-02 11:20:24.000000000 +0200
@@ -90,3 +90,25 @@
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
+2.5 Extend Query Events With Tables Info
+----------------------------------------
+
+We could extend query events structure with a tables info - a list of tables
+which the query refers to:
+
+ <current query event structure>
+ tables_info_len
+ dbase_len dbase
+ table_len table
+ ...
+ dbase_len dbase
+ table_len table
+
+Note. In case of <dbase> = current data base, we can set dbase_len = 0
+ and dbase = empty because current query event structure already
+ includes current data base name.
+
+Note. Possibly it is reasonable also to add a --binlog-with-tables-info
+ option which defines whether tables info must be included to the
+ query events.
+
-=-=(Knielsen - Fri, 14 Aug 2009, 15:47)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.10896 2009-08-14 15:47:39.000000000 +0300
+++ /tmp/wklog.40.new.10896 2009-08-14 15:47:39.000000000 +0300
@@ -72,3 +72,21 @@
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
+
+2.4 Implement server functionality to ignore certain tables
+-----------------------------------------------------------
+
+We could add a general facility in the server to ignore certain tables:
+
+ SET SESSION ignored_tables = "db1.t1,db2.t2";
+
+This would work similar to --replicate-ignore-table, but in a general way not
+restricted to the slave SQL thread.
+
+It would then be trivial for mysqlbinlog to add such statements at the start
+of the output, or probably the user could just do it manually with no need for
+additional options for mysqlbinlog.
+
+It might be useful to integrate this with the code that already handles
+--replicate-ignore-db and similar slave options.
+
-=-=(Psergey - Mon, 10 Aug 2009, 15:41)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.12989 2009-08-10 15:41:23.000000000 +0300
+++ /tmp/wklog.40.new.12989 2009-08-10 15:41:23.000000000 +0300
@@ -1,6 +1,7 @@
-
1. Context
----------
+(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
+overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
-=-=(Guest - Mon, 10 Aug 2009, 14:52)=-=-
Dependency created: 39 now depends on 40
-=-=(Guest - Mon, 10 Aug 2009, 14:51)=-=-
High Level Description modified.
--- /tmp/wklog.40.old.16985 2009-08-10 14:51:59.000000000 +0300
+++ /tmp/wklog.40.new.16985 2009-08-10 14:51:59.000000000 +0300
@@ -1,3 +1,4 @@
Replication slave can be set to filter updates to certain tables with
---replicate-[wild-]{do,ignore}-table options. This task is about adding similar
-functionality to mysqlbinlog.
+--replicate-[wild-]{do,ignore}-table options.
+
+This task is about adding similar functionality to mysqlbinlog.
-=-=(Guest - Mon, 10 Aug 2009, 14:51)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.16949 2009-08-10 14:51:33.000000000 +0300
+++ /tmp/wklog.40.new.16949 2009-08-10 14:51:33.000000000 +0300
@@ -1 +1,73 @@
+1. Context
+----------
+At the moment, the server has these replication slave options:
+
+ --replicate-do-table=db.tbl
+ --replicate-ignore-table=db.tbl
+ --replicate-wild-do-table=pattern.pattern
+ --replicate-wild-ignore-table=pattern.pattern
+
+They affect both RBR and SBR events. SBR events are checked after the
+statement has been parsed, the server iterates over list of used tables and
+checks them againist --replicate instructions.
+
+What is interesting is that this scheme still allows to update the ignored
+table through a VIEW.
+
+2. Table filtering in mysqlbinlog
+---------------------------------
+
+Per-table filtering of RBR events is easy (as it is relatively easy to extract
+the name of the table that the event applies to).
+
+Per-table filtering of SBR events is hard, as generally it is not apparent
+which tables the statement refers to.
+
+This opens possible options:
+
+2.1 Put the parser into mysqlbinlog
+-----------------------------------
+Once we have a full parser in mysqlbinlog, we'll be able to check which tables
+are used by a statement, and will allow to show behaviour identical to those
+that one obtains when using --replicate-* slave options.
+
+(It is not clear how much effort is needed to put the parser into mysqlbinlog.
+Any guesses?)
+
+
+2.2 Use dumb regexp match
+-------------------------
+Use a really dumb approach. A query is considered to be modifying table X if
+it matches an expression
+
+CREATE TABLE $tablename
+DROP $tablename
+UPDATE ...$tablename ... SET // here '...' can't contain the word 'SET'
+DELETE ...$tablename ... WHERE // same as above
+ALTER TABLE $tablename
+.. etc (go get from the grammar) ..
+
+The advantage over doing the same in awk is that mysqlbinlog will also process
+RBR statements, and together with that will provide a working solution for
+those who are careful with their table names not mixing with string constants
+and such.
+
+(TODO: string constants are of particular concern as they come from
+[potentially hostile] users, unlike e.g. table aliases which come from
+[not hostile] developers. Remove also all string constants before attempting
+to do match?)
+
+2.3 Have the master put annotations
+-----------------------------------
+We could add a master option so that it injects into query a mark that tells
+which tables the query will affect, e.g. for the query
+
+ UPDATE t1 LEFT JOIN db3.t2 ON ... WHERE ...
+
+
+the binlog will have
+
+ /* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
+
+and further processing in mysqlbinlog will be trivial.
DESCRIPTION:
Replication slave can be set to filter updates to certain tables with
--replicate-[wild-]{do,ignore}-table options.
This task is about adding similar functionality to mysqlbinlog.
HIGH-LEVEL SPECIFICATION:
1. Context
----------
(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
--replicate-ignore-table=db.tbl
--replicate-wild-do-table=pattern.pattern
--replicate-wild-ignore-table=pattern.pattern
They affect both RBR and SBR events. SBR events are checked after the
statement has been parsed, the server iterates over list of used tables and
checks them againist --replicate instructions.
What is interesting is that this scheme still allows to update the ignored
table through a VIEW.
2. Table filtering in mysqlbinlog
---------------------------------
Per-table filtering of RBR events is easy (as it is relatively easy to extract
the name of the table that the event applies to).
Per-table filtering of SBR events is hard, as generally it is not apparent
which tables the statement refers to.
This opens possible options:
2.1 Put the parser into mysqlbinlog
-----------------------------------
Once we have a full parser in mysqlbinlog, we'll be able to check which tables
are used by a statement, and will allow to show behaviour identical to those
that one obtains when using --replicate-* slave options.
(It is not clear how much effort is needed to put the parser into mysqlbinlog.
Any guesses?)
2.2 Use dumb regexp match
-------------------------
Use a really dumb approach. A query is considered to be modifying table X if
it matches an expression
CREATE TABLE $tablename
DROP $tablename
UPDATE ...$tablename ... SET // here '...' can't contain the word 'SET'
DELETE ...$tablename ... WHERE // same as above
ALTER TABLE $tablename
.. etc (go get from the grammar) ..
The advantage over doing the same in awk is that mysqlbinlog will also process
RBR statements, and together with that will provide a working solution for
those who are careful with their table names not mixing with string constants
and such.
(TODO: string constants are of particular concern as they come from
[potentially hostile] users, unlike e.g. table aliases which come from
[not hostile] developers. Remove also all string constants before attempting
to do match?)
2.3 Have the master put annotations
-----------------------------------
We could add a master option so that it injects into query a mark that tells
which tables the query will affect, e.g. for the query
UPDATE t1 LEFT JOIN db3.t2 ON ... WHERE ...
the binlog will have
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
2.4 Implement server functionality to ignore certain tables
-----------------------------------------------------------
We could add a general facility in the server to ignore certain tables:
SET SESSION ignored_tables = "db1.t1,db2.t2";
This would work similar to --replicate-ignore-table, but in a general way not
restricted to the slave SQL thread.
It would then be trivial for mysqlbinlog to add such statements at the start
of the output, or probably the user could just do it manually with no need for
additional options for mysqlbinlog.
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
2.5 Extend Query Events With Tables Info
----------------------------------------
We could extend query events structure with a tables info - a list of tables
which the query refers to:
<current query event structure>
tables_info_len
dbase_len dbase
table_len table
...
dbase_len dbase
table_len table
Note. In case of <dbase> = current data base, we can set dbase_len = 0
and dbase = empty because current query event structure already
includes current data base name.
Note. Possibly it is reasonable also to add a --binlog-with-tables-info
option which defines whether tables info must be included to the
query events.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] Updated (by Alexi): Add a mysqlbinlog option to filter updates to certain tables (40)
by worklog-noreply@askmonty.org 02 Nov '09
by worklog-noreply@askmonty.org 02 Nov '09
02 Nov '09
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add a mysqlbinlog option to filter updates to certain tables
CREATION DATE..: Mon, 10 Aug 2009, 13:25
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......: Psergey
CATEGORY.......: Server-RawIdeaBin
TASK ID........: 40 (http://askmonty.org/worklog/?tid=40)
VERSION........: Server-9.x
STATUS.........: Un-Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Alexi - Mon, 02 Nov 2009, 11:20)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.4848 2009-11-02 11:20:24.000000000 +0200
+++ /tmp/wklog.40.new.4848 2009-11-02 11:20:24.000000000 +0200
@@ -90,3 +90,25 @@
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
+2.5 Extend Query Events With Tables Info
+----------------------------------------
+
+We could extend query events structure with a tables info - a list of tables
+which the query refers to:
+
+ <current query event structure>
+ tables_info_len
+ dbase_len dbase
+ table_len table
+ ...
+ dbase_len dbase
+ table_len table
+
+Note. In case of <dbase> = current data base, we can set dbase_len = 0
+ and dbase = empty because current query event structure already
+ includes current data base name.
+
+Note. Possibly it is reasonable also to add a --binlog-with-tables-info
+ option which defines whether tables info must be included to the
+ query events.
+
-=-=(Knielsen - Fri, 14 Aug 2009, 15:47)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.10896 2009-08-14 15:47:39.000000000 +0300
+++ /tmp/wklog.40.new.10896 2009-08-14 15:47:39.000000000 +0300
@@ -72,3 +72,21 @@
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
+
+2.4 Implement server functionality to ignore certain tables
+-----------------------------------------------------------
+
+We could add a general facility in the server to ignore certain tables:
+
+ SET SESSION ignored_tables = "db1.t1,db2.t2";
+
+This would work similar to --replicate-ignore-table, but in a general way not
+restricted to the slave SQL thread.
+
+It would then be trivial for mysqlbinlog to add such statements at the start
+of the output, or probably the user could just do it manually with no need for
+additional options for mysqlbinlog.
+
+It might be useful to integrate this with the code that already handles
+--replicate-ignore-db and similar slave options.
+
-=-=(Psergey - Mon, 10 Aug 2009, 15:41)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.12989 2009-08-10 15:41:23.000000000 +0300
+++ /tmp/wklog.40.new.12989 2009-08-10 15:41:23.000000000 +0300
@@ -1,6 +1,7 @@
-
1. Context
----------
+(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
+overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
-=-=(Guest - Mon, 10 Aug 2009, 14:52)=-=-
Dependency created: 39 now depends on 40
-=-=(Guest - Mon, 10 Aug 2009, 14:51)=-=-
High Level Description modified.
--- /tmp/wklog.40.old.16985 2009-08-10 14:51:59.000000000 +0300
+++ /tmp/wklog.40.new.16985 2009-08-10 14:51:59.000000000 +0300
@@ -1,3 +1,4 @@
Replication slave can be set to filter updates to certain tables with
---replicate-[wild-]{do,ignore}-table options. This task is about adding similar
-functionality to mysqlbinlog.
+--replicate-[wild-]{do,ignore}-table options.
+
+This task is about adding similar functionality to mysqlbinlog.
-=-=(Guest - Mon, 10 Aug 2009, 14:51)=-=-
High-Level Specification modified.
--- /tmp/wklog.40.old.16949 2009-08-10 14:51:33.000000000 +0300
+++ /tmp/wklog.40.new.16949 2009-08-10 14:51:33.000000000 +0300
@@ -1 +1,73 @@
+1. Context
+----------
+At the moment, the server has these replication slave options:
+
+ --replicate-do-table=db.tbl
+ --replicate-ignore-table=db.tbl
+ --replicate-wild-do-table=pattern.pattern
+ --replicate-wild-ignore-table=pattern.pattern
+
+They affect both RBR and SBR events. SBR events are checked after the
+statement has been parsed, the server iterates over list of used tables and
+checks them againist --replicate instructions.
+
+What is interesting is that this scheme still allows to update the ignored
+table through a VIEW.
+
+2. Table filtering in mysqlbinlog
+---------------------------------
+
+Per-table filtering of RBR events is easy (as it is relatively easy to extract
+the name of the table that the event applies to).
+
+Per-table filtering of SBR events is hard, as generally it is not apparent
+which tables the statement refers to.
+
+This opens possible options:
+
+2.1 Put the parser into mysqlbinlog
+-----------------------------------
+Once we have a full parser in mysqlbinlog, we'll be able to check which tables
+are used by a statement, and will allow to show behaviour identical to those
+that one obtains when using --replicate-* slave options.
+
+(It is not clear how much effort is needed to put the parser into mysqlbinlog.
+Any guesses?)
+
+
+2.2 Use dumb regexp match
+-------------------------
+Use a really dumb approach. A query is considered to be modifying table X if
+it matches an expression
+
+CREATE TABLE $tablename
+DROP $tablename
+UPDATE ...$tablename ... SET // here '...' can't contain the word 'SET'
+DELETE ...$tablename ... WHERE // same as above
+ALTER TABLE $tablename
+.. etc (go get from the grammar) ..
+
+The advantage over doing the same in awk is that mysqlbinlog will also process
+RBR statements, and together with that will provide a working solution for
+those who are careful with their table names not mixing with string constants
+and such.
+
+(TODO: string constants are of particular concern as they come from
+[potentially hostile] users, unlike e.g. table aliases which come from
+[not hostile] developers. Remove also all string constants before attempting
+to do match?)
+
+2.3 Have the master put annotations
+-----------------------------------
+We could add a master option so that it injects into query a mark that tells
+which tables the query will affect, e.g. for the query
+
+ UPDATE t1 LEFT JOIN db3.t2 ON ... WHERE ...
+
+
+the binlog will have
+
+ /* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
+
+and further processing in mysqlbinlog will be trivial.
DESCRIPTION:
Replication slave can be set to filter updates to certain tables with
--replicate-[wild-]{do,ignore}-table options.
This task is about adding similar functionality to mysqlbinlog.
HIGH-LEVEL SPECIFICATION:
1. Context
----------
(See http://askmonty.org/wiki/index.php/Scratch/ReplicationOptions for global
overview)
At the moment, the server has these replication slave options:
--replicate-do-table=db.tbl
--replicate-ignore-table=db.tbl
--replicate-wild-do-table=pattern.pattern
--replicate-wild-ignore-table=pattern.pattern
They affect both RBR and SBR events. SBR events are checked after the
statement has been parsed, the server iterates over list of used tables and
checks them againist --replicate instructions.
What is interesting is that this scheme still allows to update the ignored
table through a VIEW.
2. Table filtering in mysqlbinlog
---------------------------------
Per-table filtering of RBR events is easy (as it is relatively easy to extract
the name of the table that the event applies to).
Per-table filtering of SBR events is hard, as generally it is not apparent
which tables the statement refers to.
This opens possible options:
2.1 Put the parser into mysqlbinlog
-----------------------------------
Once we have a full parser in mysqlbinlog, we'll be able to check which tables
are used by a statement, and will allow to show behaviour identical to those
that one obtains when using --replicate-* slave options.
(It is not clear how much effort is needed to put the parser into mysqlbinlog.
Any guesses?)
2.2 Use dumb regexp match
-------------------------
Use a really dumb approach. A query is considered to be modifying table X if
it matches an expression
CREATE TABLE $tablename
DROP $tablename
UPDATE ...$tablename ... SET // here '...' can't contain the word 'SET'
DELETE ...$tablename ... WHERE // same as above
ALTER TABLE $tablename
.. etc (go get from the grammar) ..
The advantage over doing the same in awk is that mysqlbinlog will also process
RBR statements, and together with that will provide a working solution for
those who are careful with their table names not mixing with string constants
and such.
(TODO: string constants are of particular concern as they come from
[potentially hostile] users, unlike e.g. table aliases which come from
[not hostile] developers. Remove also all string constants before attempting
to do match?)
2.3 Have the master put annotations
-----------------------------------
We could add a master option so that it injects into query a mark that tells
which tables the query will affect, e.g. for the query
UPDATE t1 LEFT JOIN db3.t2 ON ... WHERE ...
the binlog will have
/* !mysqlbinlog: updates t1,db3.t2 */ UPDATE t1 LEFT JOIN ...
and further processing in mysqlbinlog will be trivial.
2.4 Implement server functionality to ignore certain tables
-----------------------------------------------------------
We could add a general facility in the server to ignore certain tables:
SET SESSION ignored_tables = "db1.t1,db2.t2";
This would work similar to --replicate-ignore-table, but in a general way not
restricted to the slave SQL thread.
It would then be trivial for mysqlbinlog to add such statements at the start
of the output, or probably the user could just do it manually with no need for
additional options for mysqlbinlog.
It might be useful to integrate this with the code that already handles
--replicate-ignore-db and similar slave options.
2.5 Extend Query Events With Tables Info
----------------------------------------
We could extend query events structure with a tables info - a list of tables
which the query refers to:
<current query event structure>
tables_info_len
dbase_len dbase
table_len table
...
dbase_len dbase
table_len table
Note. In case of <dbase> = current data base, we can set dbase_len = 0
and dbase = empty because current query event structure already
includes current data base name.
Note. Possibly it is reasonable also to add a --binlog-with-tables-info
option which defines whether tables info must be included to the
query events.
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0
[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2756: Merge.
by noreply@launchpad.net 01 Nov '09
by noreply@launchpad.net 01 Nov '09
01 Nov '09
Merge authors:
Hakan Küçükyılmaz (hakan-askmonty)
------------------------------------------------------------
revno: 2756 [merge]
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: maria-local-master
timestamp: Sun 2009-11-01 18:41:16 +0100
message:
Merge.
renamed:
storage/federatedx/CMakeFiles.txt => storage/federatedx/CMakeLists.txt
modified:
storage/federatedx/Makefile.am
--
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] [Branch ~maria-captains/maria/5.1] Rev 2755: Compilation under windows x64 made possible.
by noreply@launchpad.net 01 Nov '09
by noreply@launchpad.net 01 Nov '09
01 Nov '09
------------------------------------------------------------
revno: 2755
committer: sanja(a)askmonty.org
branch nick: work-maria-5.1-win64
timestamp: Sat 2009-10-31 21:22:50 +0200
message:
Compilation under windows x64 made possible.
modified:
sql/mysqld.cc
storage/xtradb/include/srv0srv.h
storage/xtradb/srv/srv0srv.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
Hi Alexander,
Please find the feedback for post-review fixes below:
> === modified file 'client/mysqlbinlog.cc'
> --- client/mysqlbinlog.cc 2009-10-24 19:43:39 +0000
> +++ client/mysqlbinlog.cc 2009-10-27 13:42:47 +0000
> @@ -38,8 +38,8 @@
> /* Needed for Rpl_filter */
> CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
>
> -#include "sql_string.h" // needed for Rpl_filter
> -#include "sql_list.h" // needed for Rpl_filter
> +#include "sql_string.h" // needed for Rpl_filter
> +#include "sql_list.h" // needed for Rpl_filter
> #include "rpl_filter.h"
>
> Rpl_filter *binlog_filter;
> @@ -1190,7 +1190,8 @@
> (uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG,
> REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
> {"rewrite-db", OPT_REWRITE_DB,
> - "Updates to a database with a different name than the original.",
> + "Updates to a database with a different name than the original. \
> +Example: rewrite-db='from->to'.",
Please change to use multiple-strings;
"Updates to a database with a different name than the original."
"Example: rewrite-db='from->to'.",
as that is what is done around the codebase.
> 0, 0, 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}
> };
>
> === modified file 'mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result'
> --- mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result 2009-10-24 21:48:58 +0000
> +++ mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result 2009-10-27 13:42:47 +0000
> @@ -216,6 +216,201 @@
> # End of log file
> ROLLBACK /* added by mysqlbinlog */;
> /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
> +#
> +# mysqlbinlog output
> +# --base64-output = decode-rows
> +# --rewrite-db = test1->new_test1
> +# --rewrite-db = test3->new_test3
> +# --read-from-remote-server
> +#
> +/*!40019 SET @@session.max_insert_delayed_threads=0*/;
> +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
> +DELIMITER /*!*/;
> +# at #
> +#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
Apparently this testcase will succeed only at 4:40 on 01-Sept-2009. Please make a stable testcase.
> +ROLLBACK/*!*/;
> +# at #
> +use new_test1/*!*/;
> +#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
> +SET TIMESTAMP=1000000000/*!*/;
> +SET @@session.pseudo_thread_id=#/*!*/;
After the above is fixed, we'll need to do another push and buildbot run to see if there are any problems.
BR
Sergey
--
Sergey Petrunia, Software Developer
Monty Program AB, http://askmonty.org
Blog: http://s.petrunia.net/blog
3
4
[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2754: Merge with 5.1-release
by noreply@launchpad.net 30 Oct '09
by noreply@launchpad.net 30 Oct '09
30 Oct '09
Merge authors:
Michael Widenius (monty)
Sergey Petrunia (sergefp)
------------------------------------------------------------
revno: 2754 [merge]
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Fri 2009-10-30 22:28:11 +0200
message:
Merge with 5.1-release
modified:
scripts/make_binary_distribution.sh
win/make_mariadb_win_dist
--
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:2754)
by Michael Widenius 30 Oct '09
by Michael Widenius 30 Oct '09
30 Oct '09
#At lp:maria based on revid:monty@askmonty.org-20091030201608-t2p53ssllnmcvufz
2754 Michael Widenius 2009-10-30 [merge]
Merge with 5.1-release
modified:
scripts/make_binary_distribution.sh
win/make_mariadb_win_dist
=== modified file 'scripts/make_binary_distribution.sh'
--- a/scripts/make_binary_distribution.sh 2009-10-29 00:04:56 +0000
+++ b/scripts/make_binary_distribution.sh 2009-10-30 20:28:11 +0000
@@ -305,11 +305,6 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; t
fi
fi
- # FIXME let this script be in "bin/", where it is in the RPMs?
- # http://dev.mysql.com/doc/refman/5.1/en/mysql-install-db-problems.html
- mkdir $DEST/scripts
- mv $DEST/bin/mysql_install_db $DEST/scripts/
-
# Note, no legacy "safe_mysqld" link to "mysqld_safe" in 5.1
# Copy readme and license files
@@ -342,18 +337,25 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; t
#
# Move things to make them easier to find in tar installation
#
- mv $DEST/libexec/* $DEST/bin
+
+ # The following test is needed if the original configure was done with
+ # something like --libexecdir=/usr/local/mysql/bin
+ if test -f $DEST/libexec/mysqld
+ then
+ mv $DEST/libexec/* $DEST/bin
+ rmdir $DEST/libexec
+ fi
mv $DEST/share/man $DEST
mv $DEST/share/mysql/binary-configure $DEST/configure
mv $DEST/share/mysql/*.sql $DEST/share
mv $DEST/share/mysql/*.cnf $DEST/share/mysql/*.server $DEST/share/mysql/mysql-log-rotate $DEST/support-files
- rmdir $DEST/libexec
#
# Move some scripts that are only run once to 'scripts' directory
# but add symbolic links instead to old place for compatibility
#
- for i in mysql_secure_installation mysql_fix_extensions mysql_fix_privilege_tables
+ mkdir $DEST/scripts
+ for i in mysql_secure_installation mysql_fix_extensions mysql_fix_privilege_tables mysql_install_db
do
mv $DEST/bin/$i $DEST/scripts
ln -s "../scripts/$i" $DEST/bin/$i
=== modified file 'win/make_mariadb_win_dist'
--- a/win/make_mariadb_win_dist 2009-10-12 16:50:20 +0000
+++ b/win/make_mariadb_win_dist 2009-10-30 10:50:48 +0000
@@ -66,7 +66,7 @@ ls -lah $ZIPFILE
echo "$ZIPFILE is the Windows noinstall binary zip"
if [ $RES ] ; then
- echo "Archive contents differ from the standard file list, check the diff output above"
+ echo "Archive contents differ from the standard file list, check the diff output above"
else
echo "Archive contents match the standard list, OK"
fi
1
0
[Maria-developers] [Branch ~maria-captains/maria/5.1] Rev 2753: Merge of FederatedX code
by noreply@launchpad.net 30 Oct '09
by noreply@launchpad.net 30 Oct '09
30 Oct '09
Merge authors:
Michael Widenius (monty)
------------------------------------------------------------
revno: 2753 [merge]
committer: Michael Widenius <monty(a)askmonty.org>
branch nick: maria-5.1
timestamp: Fri 2009-10-30 22:16:08 +0200
message:
Merge of FederatedX code
added:
storage/federated/README
storage/federatedx/
storage/federatedx/AUTHORS
storage/federatedx/CMakeFiles.txt
storage/federatedx/ChangeLog
storage/federatedx/FAQ
storage/federatedx/Makefile.am
storage/federatedx/README
storage/federatedx/README.windows
storage/federatedx/TODO
storage/federatedx/federatedx_io.cc
storage/federatedx/federatedx_io_mysql.cc
storage/federatedx/federatedx_io_null.cc
storage/federatedx/federatedx_probes.h
storage/federatedx/federatedx_txn.cc
storage/federatedx/ha_federatedx.cc
storage/federatedx/ha_federatedx.h
storage/federatedx/plug.in
renamed:
storage/federated/plug.in => storage/federated/plug.in.disabled
modified:
.bzrignore
client/mysqladmin.cc
extra/yassl/taocrypt/src/twofish.cpp
libmysqld/Makefile.am
mysql-test/mysql-test-run.pl
mysql-test/suite/federated/disabled.def
mysql-test/suite/federated/federated.result
mysql-test/suite/federated/federated.test
mysql-test/suite/federated/federated_archive.result
mysql-test/suite/federated/federated_bug_13118.result
mysql-test/suite/federated/federated_bug_25714.result
mysql-test/suite/federated/federated_cleanup.inc
mysql-test/suite/federated/federated_innodb.result
mysql-test/suite/federated/federated_server.result
mysql-test/suite/federated/federated_server.test
mysql-test/suite/federated/federated_transactions.result
mysql-test/valgrind.supp
storage/pbxt/src/cache_xt.cc
storage/xtradb/include/buf0buf.ic
The size of the diff (6093 lines) is larger than your specified limit of 5000 lines
--
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:2753)
by Michael Widenius 30 Oct '09
by Michael Widenius 30 Oct '09
30 Oct '09
#At lp:maria based on revid:psergey@askmonty.org-20091029175033-4agewzfel760eq7v
2753 Michael Widenius 2009-10-30 [merge]
Merge of FederatedX code
added:
storage/federated/README
storage/federatedx/
storage/federatedx/AUTHORS
storage/federatedx/CMakeFiles.txt
storage/federatedx/ChangeLog
storage/federatedx/FAQ
storage/federatedx/Makefile.am
storage/federatedx/README
storage/federatedx/README.windows
storage/federatedx/TODO
storage/federatedx/federatedx_io.cc
storage/federatedx/federatedx_io_mysql.cc
storage/federatedx/federatedx_io_null.cc
storage/federatedx/federatedx_probes.h
storage/federatedx/federatedx_txn.cc
storage/federatedx/ha_federatedx.cc
storage/federatedx/ha_federatedx.h
storage/federatedx/plug.in
renamed:
storage/federated/plug.in => storage/federated/plug.in.disabled
modified:
.bzrignore
client/mysqladmin.cc
extra/yassl/taocrypt/src/twofish.cpp
libmysqld/Makefile.am
mysql-test/mysql-test-run.pl
mysql-test/suite/federated/disabled.def
mysql-test/suite/federated/federated.result
mysql-test/suite/federated/federated.test
mysql-test/suite/federated/federated_archive.result
mysql-test/suite/federated/federated_bug_13118.result
mysql-test/suite/federated/federated_bug_25714.result
mysql-test/suite/federated/federated_cleanup.inc
mysql-test/suite/federated/federated_innodb.result
mysql-test/suite/federated/federated_server.result
mysql-test/suite/federated/federated_server.test
mysql-test/suite/federated/federated_transactions.result
mysql-test/valgrind.supp
storage/pbxt/src/cache_xt.cc
storage/xtradb/include/buf0buf.ic
=== modified file '.bzrignore'
--- a/.bzrignore 2009-09-15 12:12:51 +0000
+++ b/.bzrignore 2009-10-30 18:51:46 +0000
@@ -1921,3 +1921,4 @@ sql/share/ukrainian
libmysqld/examples/mysqltest.cc
extra/libevent/event-config.h
libmysqld/opt_table_elimination.cc
+libmysqld/ha_federatedx.cc
=== modified file 'client/mysqladmin.cc'
--- a/client/mysqladmin.cc 2009-10-26 11:35:42 +0000
+++ b/client/mysqladmin.cc 2009-10-30 18:50:56 +0000
@@ -1043,7 +1043,7 @@ static int drop_db(MYSQL *mysql, const c
printf("Do you really want to drop the '%s' database [y/N] ",db);
fflush(stdout);
if (fgets(buf,sizeof(buf)-1,stdin) == 0 ||
- (*buf != 'y') && (*buf != 'Y'))
+ ((*buf != 'y') && (*buf != 'Y')))
{
puts("\nOK, aborting database drop!");
return -1;
=== modified file 'extra/yassl/taocrypt/src/twofish.cpp'
--- a/extra/yassl/taocrypt/src/twofish.cpp 2007-01-29 15:54:40 +0000
+++ b/extra/yassl/taocrypt/src/twofish.cpp 2009-10-30 18:50:56 +0000
@@ -55,6 +55,7 @@ void Twofish::Process(byte* out, const b
in += BLOCK_SIZE;
}
else if (mode_ == CBC)
+ {
if (dir_ == ENCRYPTION)
while (blocks--) {
r_[0] ^= *(word32*)in;
@@ -82,6 +83,7 @@ void Twofish::Process(byte* out, const b
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
+ }
}
#endif // DO_TWOFISH_ASM
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-09-15 10:46:35 +0000
+++ b/libmysqld/Makefile.am 2009-10-30 18:50:56 +0000
@@ -124,7 +124,7 @@ handler.o: handler.cc
# found to append fileslists that collected by configure
# to the sources list
-ha_federated.o:ha_federated.cc
+ha_federatedx.o:ha_federatedx.cc
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
ha_heap.o:ha_heap.cc
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2009-10-26 11:35:42 +0000
+++ b/mysql-test/mysql-test-run.pl 2009-10-30 18:50:56 +0000
@@ -127,7 +127,6 @@ my $path_config_file; # The ge
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts";
-my $opt_suites;
our $opt_usage;
our $opt_list_options;
=== modified file 'mysql-test/suite/federated/disabled.def'
--- a/mysql-test/suite/federated/disabled.def 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/federated/disabled.def 2009-10-30 18:50:56 +0000
@@ -9,4 +9,5 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-federated_transactions : Bug#29523 Transactions do not work
+federated_server : needs fixup
+
=== modified file 'mysql-test/suite/federated/federated.result'
--- a/mysql-test/suite/federated/federated.result 2009-03-19 08:49:51 +0000
+++ b/mysql-test/suite/federated/federated.result 2009-10-30 18:50:56 +0000
@@ -47,9 +47,10 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
-SELECT * FROM federated.t1;
-ERROR HY000: The foreign data source you are trying to reference does not exist. Data source error: error: 1146 'Table 'federated.t3' doesn't exist'
-DROP TABLE federated.t1;
+ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'root' hostname: '127.0.0.1'
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -59,9 +60,10 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
-SELECT * FROM federated.t1;
-ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES)
-DROP TABLE federated.t1;
+ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'user' hostname: '127.0.0.1'
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -1944,15 +1946,7 @@ Bug#18287 create federated table always
Test that self-references work
-create table federated.t1 (a int primary key);
-create table federated.t2 (a int primary key)
-ENGINE=FEDERATED
-connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
-insert into federated.t1 (a) values (1);
-select * from federated.t2;
-a
-1
-drop table federated.t1, federated.t2;
+fix LOCK_open before reenabling test for Bug#18287
CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8;
CREATE TABLE federated.t1 (a INT PRIMARY KEY)
ENGINE=FEDERATED
@@ -1960,13 +1954,11 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE
DEFAULT CHARSET=utf8;
SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED";
transactions
-NO
+YES
INSERT INTO federated.t1 VALUES (1);
SET autocommit=0;
INSERT INTO federated.t1 VALUES (2);
ROLLBACK;
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
SET autocommit=1;
SELECT * FROM federated.t1;
a
@@ -2157,6 +2149,6 @@ End of 5.1 tests
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated.test'
--- a/mysql-test/suite/federated/federated.test 2009-03-19 08:49:51 +0000
+++ b/mysql-test/suite/federated/federated.test 2009-10-30 18:50:56 +0000
@@ -57,6 +57,7 @@ CREATE TABLE federated.t1 (
# test non-existant table
--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_CANT_CREATE_FEDERATED_TABLE
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -66,12 +67,11 @@ eval CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3';
---error ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
-SELECT * FROM federated.t1;
-DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
# test bad user/password
--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_CANT_CREATE_FEDERATED_TABLE
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -81,9 +81,7 @@ eval CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1';
---error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
-SELECT * FROM federated.t1;
-DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
# # correct connection, same named tables
--replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -1806,6 +1804,8 @@ drop table federated.t1;
--echo
--echo Test that self-references work
--echo
+--echo fix LOCK_open before reenabling test for Bug#18287
+--disable_parsing
connection slave;
create table federated.t1 (a int primary key);
--replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -1815,7 +1815,7 @@ eval create table federated.t2 (a int pr
insert into federated.t1 (a) values (1);
select * from federated.t2;
drop table federated.t1, federated.t2;
-
+--enable_parsing
#
# BUG#29875 Disable support for transactions
#
=== modified file 'mysql-test/suite/federated/federated_archive.result'
--- a/mysql-test/suite/federated/federated_archive.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_archive.result 2009-10-30 18:50:56 +0000
@@ -34,6 +34,6 @@ id name
DROP TABLE federated.t1;
DROP TABLE federated.archive_table;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_bug_13118.result'
--- a/mysql-test/suite/federated/federated_bug_13118.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_bug_13118.result 2009-10-30 18:50:56 +0000
@@ -25,6 +25,6 @@ foo bar
DROP TABLE federated.t1;
DROP TABLE federated.bug_13118_table;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_bug_25714.result'
--- a/mysql-test/suite/federated/federated_bug_25714.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_bug_25714.result 2009-10-30 18:50:56 +0000
@@ -48,6 +48,6 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MAS
DROP TABLE federated.t1;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_cleanup.inc'
--- a/mysql-test/suite/federated/federated_cleanup.inc 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_cleanup.inc 2009-10-30 18:50:56 +0000
@@ -1,9 +1,9 @@
connection master;
--disable_warnings
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
connection slave;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
--enable_warnings
=== modified file 'mysql-test/suite/federated/federated_innodb.result'
--- a/mysql-test/suite/federated/federated_innodb.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_innodb.result 2009-10-30 18:50:56 +0000
@@ -20,6 +20,6 @@ a b
drop table federated.t1;
drop table federated.t1;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_server.result'
--- a/mysql-test/suite/federated/federated_server.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_server.result 2009-10-30 18:50:56 +0000
@@ -178,8 +178,8 @@ INSERT INTO db_bogus.t1 VALUES ('2','thi
create server 's1' foreign data wrapper 'mysql' options
(HOST '127.0.0.1',
DATABASE 'db_legitimate',
-USER 'root',
-PASSWORD '',
+USER 'test_fed',
+PASSWORD 'foo',
PORT SLAVE_PORT,
SOCKET '',
OWNER 'root');
=== modified file 'mysql-test/suite/federated/federated_server.test'
--- a/mysql-test/suite/federated/federated_server.test 2009-06-05 15:35:22 +0000
+++ b/mysql-test/suite/federated/federated_server.test 2009-10-30 18:50:56 +0000
@@ -3,6 +3,7 @@
# Slow test, don't run during staging part
-- source include/not_staging.inc
+-- source include/big_test.inc
-- source federated.inc
connection slave;
@@ -182,13 +183,17 @@ CREATE TABLE db_bogus.t1 (
;
INSERT INTO db_bogus.t1 VALUES ('2','this is bogus');
+connection slave;
+create user test_fed@localhost identified by 'foo';
+grant all on db_legitimate.* to test_fed@localhost;
+
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create server 's1' foreign data wrapper 'mysql' options
(HOST '127.0.0.1',
DATABASE 'db_legitimate',
- USER 'root',
- PASSWORD '',
+ USER 'test_fed',
+ PASSWORD 'foo',
PORT $SLAVE_MYPORT,
SOCKET '',
OWNER 'root');
=== modified file 'mysql-test/suite/federated/federated_transactions.result'
--- a/mysql-test/suite/federated/federated_transactions.result 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/federated/federated_transactions.result 2009-10-30 18:50:56 +0000
@@ -1,13 +1,4 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-stop slave;
-DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
-DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
DROP TABLE IF EXISTS federated.t1;
Warnings:
=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp 2009-09-15 10:46:35 +0000
+++ b/mysql-test/valgrind.supp 2009-10-30 18:50:56 +0000
@@ -880,3 +880,17 @@
fun:nptl_pthread_exit_hack_handler
fun:start_thread
}
+
+#
+# Problem with glibc and gethostbyaddr_r
+#
+
+{
+ libc_res_nsend: Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ fun: __libc_res_nsend
+ fun: __libc_res_nquery
+ obj: /lib64/libnss_dns-*so)
+ obj: /lib64/libnss_dns-*so)
+ fun: gethostbyaddr_r
+}
=== added file 'storage/federated/README'
--- a/storage/federated/README 1970-01-01 00:00:00 +0000
+++ b/storage/federated/README 2009-10-30 18:50:56 +0000
@@ -0,0 +1,7 @@
+The files in this directory are not used by MariaDB
+
+MariaDB uses the new federated storage engine that can be found in the
+federatedx directory.
+
+This directory is only kept around to make it easy to merge code from the
+MySQL source repositories that uses the old and disabled federated code.
=== renamed file 'storage/federated/plug.in' => 'storage/federated/plug.in.disabled'
=== added directory 'storage/federatedx'
=== added file 'storage/federatedx/AUTHORS'
--- a/storage/federatedx/AUTHORS 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/AUTHORS 2009-10-30 18:50:56 +0000
@@ -0,0 +1,11 @@
+FederatedX
+
+Patrick Galbraith <patg(a)patg.net> - Federated
+
+Pluggable Storage Engine Skeleton setup
+
+Brian Aker <brian(a)mysql.com> | <brian(a)tangent.org> - Original Design
+Calvin Sun - Windows Support
+Brian Miezejewski - Bug fixes
+Antony T Curtis - Help in inital development, transactions and various help
+Michael Widenius - Bug fixes and some simple early optimizations
=== added file 'storage/federatedx/CMakeFiles.txt'
--- a/storage/federatedx/CMakeFiles.txt 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/CMakeFiles.txt 2009-10-30 18:50:56 +0000
@@ -0,0 +1,3 @@
+INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
+SET(FEDERATED_SOURCES ha_federatedx.cc)
+MYSQL_STORAGE_ENGINE(FEDERATED)
=== added file 'storage/federatedx/ChangeLog'
--- a/storage/federatedx/ChangeLog 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ChangeLog 2009-10-30 18:50:56 +0000
@@ -0,0 +1,18 @@
+0.2 - Thu March 8 00:00:00 EST 2008
+
+ - Fixed bug #30051 "CREATE TABLE does not connect and check existence of remote table"
+ Modified "real_connect" to take a share and create flag to in order to not rely
+ on any settings that are later instantiated and/or set by get_share
+ Also, put logic in the code to not attempt this if a localhost. There's an annoying
+ functionality that if federated tries to connect to itself during creater table, you
+ get 1159 error (timeout) - only when local. This prevents having this functionality
+ and is probably part of the reason it was removed.
+
+0.1 - Thu Feb 1 00:00:00 EST 2008
+
+ - This is the FederatedX Storage Engine,
+ first release.
+ - Added documentation
+ - Added simple test and README file to explain
+ how to run the test
+ - Added FAQ
=== added file 'storage/federatedx/FAQ'
--- a/storage/federatedx/FAQ 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/FAQ 2009-10-30 18:50:56 +0000
@@ -0,0 +1,40 @@
+Q. What is the FederatedX pluggable storage engine?
+
+A. It is a fork of the Federated Storage Engine that Brian Aker and I
+(Patrick Galbraith) developed originally . It is a storage engine that
+uses a client connection to a remote MySQL data source as its data
+source instead of a local file on disk.
+
+Q. Why did you fork from Federated?
+
+A. To enhance the storage engine independently of the
+MySQL Server release schedule. Many people have been
+mentioning their dissatisfaction with the limitations
+of Federated. I think the engine is a great concept and
+have a sense of obligation to continue to improve it.
+There are some patches already that are in dire need
+of being applied and tested.
+
+Q. What do you plan to do with FederatedX?
+
+A. Many things need addressing:
+
+- Outstanding bugs
+- How do deal with huge result sets
+- Pushdown conditions (being able to pass things like LIMIT
+ to the remote connection to keep from returning huge
+ result sets).
+- Better transactional support
+- Other connection mechanisms (ODBC, JDBC, native drivers
+ of other RDBMSs)
+
+Q. What FederatedX is and is not?
+
+A. FederatedX is not yet a complete "federated" solution in
+ the sense that other venders have developed (IBM, etc). It
+ is essentially a networked storage engine. It is my hope
+ to make it a real federated solution.
+
+Q. In which MySQL distributions/forks/branches can I find FederateX
+
+A. MariaDB (http://www.mariadb.com)
=== added file 'storage/federatedx/Makefile.am'
--- a/storage/federatedx/Makefile.am 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/Makefile.am 2009-10-30 18:50:56 +0000
@@ -0,0 +1,64 @@
+# Used to build Makefile.in
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+pkgplugindir = $(pkglibdir)/plugin
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir)
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_federatedx.h federatedx_probes.h
+
+EXTRA_LTLIBRARIES = ha_federatedx.la
+pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@
+ha_federatedx_la_LDFLAGS = -module -rpath $(pkgplugindir)
+ha_federatedx_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_federatedx_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_federatedx_la_SOURCES = ha_federatedx.cc
+
+
+EXTRA_LIBRARIES = libfederatedx.a
+noinst_LIBRARIES = @plugin_federated_static_target@
+libfederatedx_a_CXXFLAGS = $(AM_CFLAGS)
+libfederatedx_a_CFLAGS = $(AM_CFLAGS)
+libfederatedx_a_SOURCES= ha_federatedx.cc federatedx_txn.cc \
+ federatedx_io.cc federatedx_io_null.cc \
+ federatedx_io_mysql.cc
+
+EXTRA_DIST = CMakeLists.txt plug.in ha_federatedx.h \
+ federatedx_probes.d
+
+ha_federatedx_la_SOURCES = ha_federatedx.cc federatedx_txn.cc \
+ federatedx_io.cc federatedx_io_null.cc \
+ federatedx_io_mysql.cc $(top_srcdir)/mysys/string.c
+ha_federatedx_la_LIBADD =
+
+#DTRACE = @DTRACE@
+#DTRACEFLAGS = @DTRACEFLAGS@
+#DTRACEFILES = .libs/libfederatedx_engine_la-ha_federatedx.o
+
+# #if HAVE_DTRACE
+# # libfederatedx_engine_la_LIBADD += federatedx_probes.o
+# #endif
+
+# federatedx_probes.h: federatedx_probes.d
+# $(DTRACE) $(DTRACEFLAGS) -h -s federatedx_probes.d
+# mv federatedx_probes.h federatedx_probes.h.bak
+# sed "s/#include <unistd.h>//g" federatedx_probes.h.bak > federatedx_probes.h
+# rm federatedx_probes.h.bak
+
+#federatedx_probes.o:
+# $(DTRACE) $(DTRACEFLAGS) -G -s federatedx_probes.d $(DTRACEFILES)
+
+# End
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
=== added file 'storage/federatedx/README'
--- a/storage/federatedx/README 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/README 2009-10-30 18:50:56 +0000
@@ -0,0 +1,33 @@
+This is the FederatedX Storage Engine, developed as an external storage engine.
+
+NOTE:
+
+The following is only relevant if you use it for MySQL. MariaDB already comes
+with the latest version of FederatedX.
+
+To install, grab a copy of the mysql source code and run this:
+
+./configure --with-mysql=/path/to/src/mysql-5.x --libdir=/usr/local/lib/mysql/
+
+make install
+
+And then inside of MySQL:
+
+mysql> INSTALL PLUGIN federatedx SONAME 'libfederatedx_engine.so';
+
+mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="mysql://root@host/schema/table"
+
+or
+
+mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="server" CHARSET=latin1;
+
+You will probably need to edit the Makefile.am in the src/ tree if you want
+to build on anything other then Linux (and the Makefile assumes that the
+server was not compiled for debug). The reason for the two possible
+configure lines is that libdir is dependent on where MySQL was installed. If
+you run the "INSTALL PLUGIN ..." and you get a file not found, check that
+your configured this directory correctly.
+
+For Solaris you can enable DTrace probes by adding to configure
+--enable-dtrace
+
=== added file 'storage/federatedx/README.windows'
--- a/storage/federatedx/README.windows 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/README.windows 2009-10-30 18:50:56 +0000
@@ -0,0 +1,23 @@
+The following files are changed in order to build a new engine on Windows:
+
+- Update win\configure.js with
+case "WITH_FEDERATEDX_STORAGE_ENGINE":
+to make sure it will pass WITH_FEDERATEDX_STORAGE_ENGINE in.
+
+- Update CMakeFiles.txt under mysql root:
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ ADD_DEFINITIONS(-D WITH_FEDERATEDX_STORAGE_ENGINE)
+ SET (mysql_plugin_defs
+ "${mysql_plugin_defs},builtin_skeleton_plugin")
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
+
+ and,
+
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/skeleton/src)
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
+
+ - Update CMakeFiles.txt under sql:
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld skeleton)
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
=== added file 'storage/federatedx/TODO'
--- a/storage/federatedx/TODO 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/TODO 2009-10-30 18:50:56 +0000
@@ -0,0 +1,30 @@
+Features
+
+* Add Pushdown conditions
+* Add other network driver interfaces
+* Handle large result sets
+* Auto-discovery of tables on foreign data sources
+
+Bugs (http://bugs.mysql.com)
+
+20026 2006-05-23 FEDERATED lacks support for auto_increment_increment and auto_increment_offset
+20724 2006-06-27 FEDERATED does not honour SET INSERT_ID
+28269 2007-05-06 Any FEDERATED engine fails to quote reserved words for field names
+25509 2007-01-10 Federated: Failure with non-ASCII characters
+26697 2007-02-27 Every query to a federated table results in a full scan of MyISAM table.
+21360 2006-07-31 Microsoft Windows (Windows/Linux) mysqldump error on federated tables
+34189 2008-01-31 Any ALTER TABLE t1 ENGINE=FEDERATED CONNECTION='connectionString' on MyISAM fails
+31757 2007-10-22 Any Federated tables break replication Antony Curtis
+33953 2008-01-21 Any mysqld dies on search federated table using nullable index with < or <= operator
+34015 2008-01-23 Linux Problems with float fields using federated tables
+21583 2006-08-11 Linux (Linux) Federated table returns broken strings.
+33702 2008-01-05 Accessing a federated table with a non existing server returns random error code
+25512 2007-01-10 Federated: CREATE failures
+32426 2007-11-16 Any FEDERATED query returns corrupt results for ORDER BY on a TEXT field
+25510 2007-01-10 Federated: double trigger activation
+33250 2007-12-14 SELECT * FROM really_big_federated_table eats lots of virtual memory (OOM)
+14874 2005-11-11 Error 2013: Lost connection to MySQL server with Federated table
+25508 2007-01-10 Federated: Failure to Remove Partitioning
+27180 2007-03-15 #1030 - Got error 1 from storage engine with big tables
+33947 2008-01-20 Any Join on Federated tables with Unique index and IS NOT NULL crashes server
+30051 (fixed) CREATE TABLE does not connect and check existence of remote table
=== added file 'storage/federatedx/federatedx_io.cc'
--- a/storage/federatedx/federatedx_io.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+typedef federatedx_io *(*instantiate_io_type)(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+struct io_schemes_st
+{
+ const char *scheme;
+ instantiate_io_type instantiate;
+};
+
+
+static const io_schemes_st federated_io_schemes[] =
+{
+ { "mysql", &instantiate_io_mysql },
+ { "null", instantiate_io_null } /* must be last element */
+};
+
+const uint federated_io_schemes_count= array_elements(federated_io_schemes);
+
+federatedx_io::federatedx_io(FEDERATEDX_SERVER *aserver)
+ : server(aserver), owner_ptr(0), txn_next(0), idle_next(0),
+ active(FALSE), busy(FALSE), readonly(TRUE)
+{
+ DBUG_ENTER("federatedx_io::federatedx_io");
+ DBUG_ASSERT(server);
+
+ safe_mutex_assert_owner(&server->mutex);
+ server->io_count++;
+
+ DBUG_VOID_RETURN;
+}
+
+
+federatedx_io::~federatedx_io()
+{
+ DBUG_ENTER("federatedx_io::~federatedx_io");
+
+ server->io_count--;
+
+ DBUG_VOID_RETURN;
+}
+
+
+bool federatedx_io::handles_scheme(const char *scheme)
+{
+ const io_schemes_st *ptr = federated_io_schemes;
+ const io_schemes_st *end = ptr + array_elements(federated_io_schemes);
+ while (ptr != end && strcasecmp(scheme, ptr->scheme))
+ ++ptr;
+ return ptr != end;
+}
+
+
+federatedx_io *federatedx_io::construct(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ const io_schemes_st *ptr = federated_io_schemes;
+ const io_schemes_st *end = ptr + (array_elements(federated_io_schemes) - 1);
+ while (ptr != end && strcasecmp(server->scheme, ptr->scheme))
+ ++ptr;
+ return ptr->instantiate(server_root, server);
+}
+
+
=== added file 'storage/federatedx/federatedx_io_mysql.cc'
--- a/storage/federatedx/federatedx_io_mysql.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io_mysql.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,592 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+#define SAVEPOINT_REALIZED 1
+#define SAVEPOINT_RESTRICT 2
+#define SAVEPOINT_EMITTED 4
+
+
+typedef struct federatedx_savepoint
+{
+ ulong level;
+ uint flags;
+} SAVEPT;
+
+
+class federatedx_io_mysql :public federatedx_io
+{
+ MYSQL mysql; /* MySQL connection */
+ DYNAMIC_ARRAY savepoints;
+ bool requested_autocommit;
+ bool actual_autocommit;
+
+ int actual_query(const char *buffer, uint length);
+ bool test_all_restrict() const;
+public:
+ federatedx_io_mysql(FEDERATEDX_SERVER *);
+ ~federatedx_io_mysql();
+
+ int simple_query(const char *fmt, ...);
+ int query(const char *buffer, uint length);
+ virtual FEDERATEDX_IO_RESULT *store_result();
+
+ virtual size_t max_query_size() const;
+
+ virtual my_ulonglong affected_rows() const;
+ virtual my_ulonglong last_insert_id() const;
+
+ virtual int error_code();
+ virtual const char *error_str();
+
+ void reset();
+ int commit();
+ int rollback();
+
+ int savepoint_set(ulong sp);
+ ulong savepoint_release(ulong sp);
+ ulong savepoint_rollback(ulong sp);
+ void savepoint_restrict(ulong sp);
+
+ ulong last_savepoint() const;
+ ulong actual_savepoint() const;
+ bool is_autocommit() const;
+
+ bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag);
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column);
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const;
+};
+
+
+federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ return new (server_root) federatedx_io_mysql(server);
+}
+
+
+federatedx_io_mysql::federatedx_io_mysql(FEDERATEDX_SERVER *aserver)
+ : federatedx_io(aserver),
+ requested_autocommit(TRUE), actual_autocommit(TRUE)
+{
+ DBUG_ENTER("federatedx_io_mysql::federatedx_io_mysql");
+
+ bzero(&mysql, sizeof(MYSQL));
+ bzero(&savepoints, sizeof(DYNAMIC_ARRAY));
+
+ my_init_dynamic_array(&savepoints, sizeof(SAVEPT), 16, 16);
+
+ DBUG_VOID_RETURN;
+}
+
+
+federatedx_io_mysql::~federatedx_io_mysql()
+{
+ DBUG_ENTER("federatedx_io_mysql::~federatedx_io_mysql");
+
+ mysql_close(&mysql);
+ delete_dynamic(&savepoints);
+
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_io_mysql::reset()
+{
+ reset_dynamic(&savepoints);
+ set_active(FALSE);
+
+ requested_autocommit= TRUE;
+ mysql.reconnect= 1;
+}
+
+
+int federatedx_io_mysql::commit()
+{
+ int error= 0;
+ DBUG_ENTER("federatedx_io_mysql::commit");
+
+ if (!actual_autocommit && (error= actual_query("COMMIT", 6)))
+ rollback();
+
+ reset();
+
+ DBUG_RETURN(error);
+}
+
+int federatedx_io_mysql::rollback()
+{
+ int error= 0;
+ DBUG_ENTER("federatedx_io_mysql::rollback");
+
+ if (!actual_autocommit)
+ error= actual_query("ROLLBACK", 8);
+ else
+ error= ER_WARNING_NOT_COMPLETE_ROLLBACK;
+
+ reset();
+
+ DBUG_RETURN(error);
+}
+
+
+ulong federatedx_io_mysql::last_savepoint() const
+{
+ SAVEPT *savept= NULL;
+ DBUG_ENTER("federatedx_io_mysql::last_savepoint");
+
+ if (savepoints.elements)
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+
+ DBUG_RETURN(savept ? savept->level : 0);
+}
+
+
+ulong federatedx_io_mysql::actual_savepoint() const
+{
+ SAVEPT *savept= NULL;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::last_savepoint");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->flags & SAVEPOINT_REALIZED)
+ break;
+ savept= NULL;
+ }
+
+ DBUG_RETURN(savept ? savept->level : 0);
+}
+
+bool federatedx_io_mysql::is_autocommit() const
+{
+ return actual_autocommit;
+}
+
+
+int federatedx_io_mysql::savepoint_set(ulong sp)
+{
+ int error;
+ SAVEPT savept;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_set");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+ DBUG_ASSERT(sp > last_savepoint());
+
+ savept.level= sp;
+ savept.flags= 0;
+
+ if ((error= insert_dynamic(&savepoints, (uchar*) &savept) ? -1 : 0))
+ goto err;
+
+ set_active(TRUE);
+ mysql.reconnect= 0;
+ requested_autocommit= FALSE;
+
+err:
+ DBUG_RETURN(error);
+}
+
+
+ulong federatedx_io_mysql::savepoint_release(ulong sp)
+{
+ SAVEPT *savept, *last= NULL;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_release");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+
+ while (savepoints.elements)
+ {
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+ if (savept->level < sp)
+ break;
+ if ((savept->flags & (SAVEPOINT_REALIZED |
+ SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED)
+ last= savept;
+ savepoints.elements--;
+ }
+
+ if (last)
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length= my_snprintf(buffer, sizeof(buffer),
+ "RELEASE SAVEPOINT save%lu", last->level);
+ actual_query(buffer, length);
+ }
+
+ DBUG_RETURN(last_savepoint());
+}
+
+
+ulong federatedx_io_mysql::savepoint_rollback(ulong sp)
+{
+ SAVEPT *savept;
+ uint index;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_release");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+
+ while (savepoints.elements)
+ {
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+ if (savept->level <= sp)
+ break;
+ savepoints.elements--;
+ }
+
+ for (index= savepoints.elements, savept= NULL; index;)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->flags & SAVEPOINT_REALIZED)
+ break;
+ savept= NULL;
+ }
+
+ if (savept && !(savept->flags & SAVEPOINT_RESTRICT))
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length= my_snprintf(buffer, sizeof(buffer),
+ "ROLLBACK TO SAVEPOINT save%lu", savept->level);
+ actual_query(buffer, length);
+ }
+
+ DBUG_RETURN(last_savepoint());
+}
+
+
+void federatedx_io_mysql::savepoint_restrict(ulong sp)
+{
+ SAVEPT *savept;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_restrict");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->level > sp)
+ continue;
+ if (savept->level < sp)
+ break;
+ savept->flags|= SAVEPOINT_RESTRICT;
+ break;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+int federatedx_io_mysql::simple_query(const char *fmt, ...)
+{
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length, error;
+ va_list arg;
+ DBUG_ENTER("federatedx_io_mysql::simple_query");
+
+ va_start(arg, fmt);
+ length= my_vsnprintf(buffer, sizeof(buffer), fmt, arg);
+ va_end(arg);
+
+ error= query(buffer, length);
+
+ DBUG_RETURN(error);
+}
+
+
+bool federatedx_io_mysql::test_all_restrict() const
+{
+ bool result= FALSE;
+ SAVEPT *savept;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::test_all_restrict");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if ((savept->flags & (SAVEPOINT_REALIZED |
+ SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED ||
+ (savept->flags & SAVEPOINT_EMITTED))
+ DBUG_RETURN(FALSE);
+ if (savept->flags & SAVEPOINT_RESTRICT)
+ result= TRUE;
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_io_mysql::query(const char *buffer, uint length)
+{
+ int error;
+ bool wants_autocommit= requested_autocommit | is_readonly();
+ DBUG_ENTER("federatedx_io_mysql::query");
+
+ if (!wants_autocommit && test_all_restrict())
+ wants_autocommit= TRUE;
+
+ if (wants_autocommit != actual_autocommit)
+ {
+ if ((error= actual_query(wants_autocommit ? "SET AUTOCOMMIT=1"
+ : "SET AUTOCOMMIT=0", 16)))
+ DBUG_RETURN(error);
+ mysql.reconnect= wants_autocommit ? 1 : 0;
+ actual_autocommit= wants_autocommit;
+ }
+
+ if (!actual_autocommit && last_savepoint() != actual_savepoint())
+ {
+ SAVEPT *savept= dynamic_element(&savepoints, savepoints.elements - 1,
+ SAVEPT *);
+ if (!(savept->flags & SAVEPOINT_RESTRICT))
+ {
+ char buf[STRING_BUFFER_USUAL_SIZE];
+ int len= my_snprintf(buf, sizeof(buf),
+ "SAVEPOINT save%lu", savept->level);
+ if ((error= actual_query(buf, len)))
+ DBUG_RETURN(error);
+ set_active(TRUE);
+ savept->flags|= SAVEPOINT_EMITTED;
+ }
+ savept->flags|= SAVEPOINT_REALIZED;
+ }
+
+ if (!(error= actual_query(buffer, length)))
+ set_active(is_active() || !actual_autocommit);
+
+ DBUG_RETURN(error);
+}
+
+
+int federatedx_io_mysql::actual_query(const char *buffer, uint length)
+{
+ int error;
+ DBUG_ENTER("federatedx_io_mysql::actual_query");
+
+ if (!mysql.master)
+ {
+ if (!(mysql_init(&mysql)))
+ DBUG_RETURN(-1);
+
+ /*
+ BUG# 17044 Federated Storage Engine is not UTF8 clean
+ Add set names to whatever charset the table is at open
+ of table
+ */
+ /* this sets the csname like 'set names utf8' */
+ mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, get_charsetname());
+
+ if (!mysql_real_connect(&mysql,
+ get_hostname(),
+ get_username(),
+ get_password(),
+ get_database(),
+ get_port(),
+ get_socket(), 0))
+ DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
+ mysql.reconnect= 1;
+ }
+
+ error= mysql_real_query(&mysql, buffer, length);
+
+ DBUG_RETURN(error);
+}
+
+size_t federatedx_io_mysql::max_query_size() const
+{
+ return mysql.net.max_packet_size;
+}
+
+
+my_ulonglong federatedx_io_mysql::affected_rows() const
+{
+ return mysql.affected_rows;
+}
+
+
+my_ulonglong federatedx_io_mysql::last_insert_id() const
+{
+ return mysql.last_used_con->insert_id;
+}
+
+
+int federatedx_io_mysql::error_code()
+{
+ return mysql_errno(&mysql);
+}
+
+
+const char *federatedx_io_mysql::error_str()
+{
+ return mysql_error(&mysql);
+}
+
+
+FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result()
+{
+ FEDERATEDX_IO_RESULT *result;
+ DBUG_ENTER("federatedx_io_mysql::store_result");
+
+ result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql);
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_io_mysql::free_result(FEDERATEDX_IO_RESULT *io_result)
+{
+ mysql_free_result((MYSQL_RES *) io_result);
+}
+
+
+unsigned int federatedx_io_mysql::get_num_fields(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_num_fields((MYSQL_RES *) io_result);
+}
+
+
+my_ulonglong federatedx_io_mysql::get_num_rows(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_num_rows((MYSQL_RES *) io_result);
+}
+
+
+FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result)
+{
+ return (FEDERATEDX_IO_ROW *) mysql_fetch_row((MYSQL_RES *) io_result);
+}
+
+
+ulong *federatedx_io_mysql::fetch_lengths(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_fetch_lengths((MYSQL_RES *) io_result);
+}
+
+
+const char *federatedx_io_mysql::get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column)
+{
+ return ((MYSQL_ROW)row)[column];
+}
+
+
+bool federatedx_io_mysql::is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const
+{
+ return !((MYSQL_ROW)row)[column];
+}
+
+bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
+ const char *table_name,
+ uint table_name_length, uint flag)
+{
+ char status_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ FEDERATEDX_IO_RESULT *result= 0;
+ FEDERATEDX_IO_ROW *row;
+ String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin);
+ int error;
+
+ status_query_string.length(0);
+ status_query_string.append(STRING_WITH_LEN("SHOW TABLE STATUS LIKE "));
+ append_ident(&status_query_string, table_name,
+ table_name_length, value_quote_char);
+
+ if (query(status_query_string.ptr(), status_query_string.length()))
+ goto error;
+
+ status_query_string.length(0);
+
+ result= store_result();
+
+ /*
+ We're going to use fields num. 4, 12 and 13 of the resultset,
+ so make sure we have these fields.
+ */
+ if (!result || (get_num_fields(result) < 14))
+ goto error;
+
+ if (!get_num_rows(result))
+ goto error;
+
+ if (!(row= fetch_row(result)))
+ goto error;
+
+ /*
+ deleted is set in ha_federatedx::info
+ */
+ /*
+ need to figure out what this means as far as federatedx is concerned,
+ since we don't have a "file"
+
+ data_file_length = ?
+ index_file_length = ?
+ delete_length = ?
+ */
+ if (!is_column_null(row, 4))
+ stats->records= (ha_rows) my_strtoll10(get_column_data(row, 4),
+ (char**) 0, &error);
+ if (!is_column_null(row, 5))
+ stats->mean_rec_length= (ulong) my_strtoll10(get_column_data(row, 5),
+ (char**) 0, &error);
+
+ stats->data_file_length= stats->records * stats->mean_rec_length;
+
+ if (!is_column_null(row, 12))
+ stats->update_time= (time_t) my_strtoll10(get_column_data(row, 12),
+ (char**) 0, &error);
+ if (!is_column_null(row, 13))
+ stats->check_time= (time_t) my_strtoll10(get_column_data(row, 13),
+ (char**) 0, &error);
+
+ free_result(result);
+ return 0;
+
+error:
+ free_result(result);
+ return 1;
+}
=== added file 'storage/federatedx/federatedx_io_null.cc'
--- a/storage/federatedx/federatedx_io_null.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io_null.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,277 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+#define SAVEPOINT_REALIZED 1
+#define SAVEPOINT_RESTRICT 2
+#define SAVEPOINT_EMITTED 4
+
+
+typedef struct federatedx_savepoint
+{
+ ulong level;
+ uint flags;
+} SAVEPT;
+
+
+class federatedx_io_null :public federatedx_io
+{
+public:
+ federatedx_io_null(FEDERATEDX_SERVER *);
+ ~federatedx_io_null();
+
+ int query(const char *buffer, uint length);
+ virtual FEDERATEDX_IO_RESULT *store_result();
+
+ virtual size_t max_query_size() const;
+
+ virtual my_ulonglong affected_rows() const;
+ virtual my_ulonglong last_insert_id() const;
+
+ virtual int error_code();
+ virtual const char *error_str();
+
+ void reset();
+ int commit();
+ int rollback();
+
+ int savepoint_set(ulong sp);
+ ulong savepoint_release(ulong sp);
+ ulong savepoint_rollback(ulong sp);
+ void savepoint_restrict(ulong sp);
+
+ ulong last_savepoint() const;
+ ulong actual_savepoint() const;
+ bool is_autocommit() const;
+
+ bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag);
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column);
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const;
+};
+
+
+federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ return new (server_root) federatedx_io_null(server);
+}
+
+
+federatedx_io_null::federatedx_io_null(FEDERATEDX_SERVER *aserver)
+ : federatedx_io(aserver)
+{
+}
+
+
+federatedx_io_null::~federatedx_io_null()
+{
+}
+
+
+void federatedx_io_null::reset()
+{
+}
+
+
+int federatedx_io_null::commit()
+{
+ return 0;
+}
+
+int federatedx_io_null::rollback()
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::last_savepoint() const
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::actual_savepoint() const
+{
+ return 0;
+}
+
+bool federatedx_io_null::is_autocommit() const
+{
+ return 0;
+}
+
+
+int federatedx_io_null::savepoint_set(ulong sp)
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::savepoint_release(ulong sp)
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::savepoint_rollback(ulong sp)
+{
+ return 0;
+}
+
+
+void federatedx_io_null::savepoint_restrict(ulong sp)
+{
+}
+
+
+int federatedx_io_null::query(const char *buffer, uint length)
+{
+ return 0;
+}
+
+
+size_t federatedx_io_null::max_query_size() const
+{
+ return INT_MAX;
+}
+
+
+my_ulonglong federatedx_io_null::affected_rows() const
+{
+ return 0;
+}
+
+
+my_ulonglong federatedx_io_null::last_insert_id() const
+{
+ return 0;
+}
+
+
+int federatedx_io_null::error_code()
+{
+ return 0;
+}
+
+
+const char *federatedx_io_null::error_str()
+{
+ return "";
+}
+
+
+FEDERATEDX_IO_RESULT *federatedx_io_null::store_result()
+{
+ FEDERATEDX_IO_RESULT *result;
+ DBUG_ENTER("federatedx_io_null::store_result");
+
+ result= NULL;
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_io_null::free_result(FEDERATEDX_IO_RESULT *)
+{
+}
+
+
+unsigned int federatedx_io_null::get_num_fields(FEDERATEDX_IO_RESULT *)
+{
+ return 0;
+}
+
+
+my_ulonglong federatedx_io_null::get_num_rows(FEDERATEDX_IO_RESULT *)
+{
+ return 0;
+}
+
+
+FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *)
+{
+ return NULL;
+}
+
+
+ulong *federatedx_io_null::fetch_lengths(FEDERATEDX_IO_RESULT *)
+{
+ return NULL;
+}
+
+
+const char *federatedx_io_null::get_column_data(FEDERATEDX_IO_ROW *,
+ unsigned int)
+{
+ return "";
+}
+
+
+bool federatedx_io_null::is_column_null(const FEDERATEDX_IO_ROW *,
+ unsigned int) const
+{
+ return true;
+}
+
+bool federatedx_io_null::table_metadata(ha_statistics *stats,
+ const char *table_name,
+ uint table_name_length, uint flag)
+{
+ stats->records= (ha_rows) 0;
+ stats->mean_rec_length= (ulong) 0;
+ stats->data_file_length= 0;
+
+ stats->update_time= (time_t) 0;
+ stats->check_time= (time_t) 0;
+
+ return 0;
+}
=== added file 'storage/federatedx/federatedx_probes.h'
--- a/storage/federatedx/federatedx_probes.h 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_probes.h 2009-10-30 18:50:56 +0000
@@ -0,0 +1,45 @@
+/*
+ * Generated by dtrace(1M).
+ */
+
+#ifndef _FEDERATED_PROBES_H
+#define _FEDERATED_PROBES_H
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if _DTRACE_VERSION
+
+#define FEDERATED_CLOSE() \
+ __dtrace_federated___close()
+#define FEDERATED_CLOSE_ENABLED() \
+ __dtraceenabled_federated___close()
+#define FEDERATED_OPEN() \
+ __dtrace_federated___open()
+#define FEDERATED_OPEN_ENABLED() \
+ __dtraceenabled_federated___open()
+
+
+extern void __dtrace_federated___close(void);
+extern int __dtraceenabled_federated___close(void);
+extern void __dtrace_federated___open(void);
+extern int __dtraceenabled_federated___open(void);
+
+#else
+
+#define FEDERATED_CLOSE()
+#define FEDERATED_CLOSE_ENABLED() (0)
+#define FEDERATED_OPEN()
+#define FEDERATED_OPEN_ENABLED() (0)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FEDERATED_PROBES_H */
=== added file 'storage/federatedx/federatedx_txn.cc'
--- a/storage/federatedx/federatedx_txn.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_txn.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,424 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+federatedx_txn::federatedx_txn()
+ : txn_list(0), savepoint_level(0), savepoint_stmt(0), savepoint_next(0)
+{
+ DBUG_ENTER("federatedx_txn::federatedx_txn");
+ DBUG_VOID_RETURN;
+}
+
+federatedx_txn::~federatedx_txn()
+{
+ DBUG_ENTER("federatedx_txn::~federatedx_txn");
+ DBUG_ASSERT(!txn_list);
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_txn::close(FEDERATEDX_SERVER *server)
+{
+ uint count= 0;
+ federatedx_io *io, **iop;
+ DBUG_ENTER("federatedx_txn::close");
+
+ DBUG_ASSERT(!server->use_count);
+ DBUG_PRINT("info",("use count: %u connections: %u",
+ server->use_count, server->io_count));
+
+ for (iop= &txn_list; (io= *iop);)
+ {
+ if (io->server != server)
+ iop= &io->txn_next;
+ else
+ {
+ *iop= io->txn_next;
+ io->txn_next= NULL;
+ io->busy= FALSE;
+
+ io->idle_next= server->idle_list;
+ server->idle_list= io;
+ }
+ }
+
+ while ((io= server->idle_list))
+ {
+ server->idle_list= io->idle_next;
+ delete io;
+ count++;
+ }
+
+ DBUG_PRINT("info",("closed %u connections, txn_list: %s", count,
+ txn_list ? "active": "empty"));
+ DBUG_VOID_RETURN;
+}
+
+
+int federatedx_txn::acquire(FEDERATEDX_SHARE *share, bool readonly,
+ federatedx_io **ioptr)
+{
+ federatedx_io *io;
+ FEDERATEDX_SERVER *server= share->s;
+ DBUG_ENTER("federatedx_txn::acquire");
+ DBUG_ASSERT(ioptr && server);
+
+ if (!(io= *ioptr))
+ {
+ /* check to see if we have an available IO connection */
+ for (io= txn_list; io; io= io->txn_next)
+ if (io->server == server)
+ break;
+
+ if (!io)
+ {
+ /* check to see if there are any unowned IO connections */
+ pthread_mutex_lock(&server->mutex);
+ if ((io= server->idle_list))
+ {
+ server->idle_list= io->idle_next;
+ io->idle_next= NULL;
+ }
+ else
+ io= federatedx_io::construct(&server->mem_root, server);
+
+ io->txn_next= txn_list;
+ txn_list= io;
+
+ pthread_mutex_unlock(&server->mutex);
+ }
+
+ if (io->busy)
+ *io->owner_ptr= NULL;
+
+ io->busy= TRUE;
+ io->owner_ptr= ioptr;
+ }
+
+ DBUG_ASSERT(io->busy && io->server == server);
+
+ io->readonly&= readonly;
+
+ DBUG_RETURN((*ioptr= io) ? 0 : -1);
+}
+
+
+void federatedx_txn::release(federatedx_io **ioptr)
+{
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::release");
+ DBUG_ASSERT(ioptr);
+
+ if ((io= *ioptr))
+ {
+ /* mark as available for reuse in this transaction */
+ io->busy= FALSE;
+ *ioptr= NULL;
+
+ DBUG_PRINT("info", ("active: %d autocommit: %d",
+ io->active, io->is_autocommit()));
+
+ if (io->is_autocommit())
+ io->active= FALSE;
+ }
+
+ release_scan();
+
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_txn::release_scan()
+{
+ uint count= 0, returned= 0;
+ federatedx_io *io, **pio;
+ DBUG_ENTER("federatedx_txn::release_scan");
+
+ /* return any inactive and idle connections to the server */
+ for (pio= &txn_list; (io= *pio); count++)
+ {
+ if (io->active || io->busy)
+ pio= &io->txn_next;
+ else
+ {
+ FEDERATEDX_SERVER *server= io->server;
+
+ /* unlink from list of connections bound to the transaction */
+ *pio= io->txn_next;
+ io->txn_next= NULL;
+
+ /* reset some values */
+ io->readonly= TRUE;
+
+ pthread_mutex_lock(&server->mutex);
+ io->idle_next= server->idle_list;
+ server->idle_list= io;
+ pthread_mutex_unlock(&server->mutex);
+ returned++;
+ }
+ }
+ DBUG_PRINT("info",("returned %u of %u connections(s)", returned, count));
+
+ DBUG_VOID_RETURN;
+}
+
+
+bool federatedx_txn::txn_begin()
+{
+ ulong level= 0;
+ DBUG_ENTER("federatedx_txn::txn_begin");
+
+ if (savepoint_next == 0)
+ {
+ savepoint_next++;
+ savepoint_level= savepoint_stmt= 0;
+ sp_acquire(&level);
+ }
+
+ DBUG_RETURN(level == 1);
+}
+
+
+int federatedx_txn::txn_commit()
+{
+ int error= 0;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::txn_commit");
+
+ if (savepoint_next)
+ {
+ DBUG_ASSERT(savepoint_stmt != 1);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ int rc= 0;
+
+ if (io->active)
+ rc= io->commit();
+ else
+ io->rollback();
+
+ if (io->active && rc)
+ error= -1;
+
+ io->reset();
+ }
+
+ release_scan();
+
+ savepoint_next= savepoint_stmt= savepoint_level= 0;
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int federatedx_txn::txn_rollback()
+{
+ int error= 0;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::txn_commit");
+
+ if (savepoint_next)
+ {
+ DBUG_ASSERT(savepoint_stmt != 1);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ int rc= io->rollback();
+
+ if (io->active && rc)
+ error= -1;
+
+ io->reset();
+ }
+
+ release_scan();
+
+ savepoint_next= savepoint_stmt= savepoint_level= 0;
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+bool federatedx_txn::sp_acquire(ulong *sp)
+{
+ bool rc= FALSE;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_acquire");
+ DBUG_ASSERT(sp && savepoint_next);
+
+ *sp= savepoint_level= savepoint_next++;
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ io->savepoint_set(savepoint_level);
+ rc= TRUE;
+ }
+
+ DBUG_RETURN(rc);
+}
+
+
+int federatedx_txn::sp_rollback(ulong *sp)
+{
+ ulong level, new_level= savepoint_level;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_rollback");
+ DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ if ((level= io->savepoint_rollback(*sp)) < new_level)
+ new_level= level;
+ }
+
+ savepoint_level= new_level;
+
+ DBUG_RETURN(0);
+}
+
+
+int federatedx_txn::sp_release(ulong *sp)
+{
+ ulong level, new_level= savepoint_level;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_release");
+ DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ if ((level= io->savepoint_release(*sp)) < new_level)
+ new_level= level;
+ }
+
+ savepoint_level= new_level;
+ *sp= 0;
+
+ DBUG_RETURN(0);
+}
+
+
+bool federatedx_txn::stmt_begin()
+{
+ bool result= FALSE;
+ DBUG_ENTER("federatedx_txn::stmt_begin");
+
+ if (!savepoint_stmt)
+ {
+ if (!savepoint_next)
+ {
+ savepoint_next++;
+ savepoint_level= savepoint_stmt= 0;
+ }
+ result= sp_acquire(&savepoint_stmt);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_txn::stmt_commit()
+{
+ int result= 0;
+ DBUG_ENTER("federatedx_txn::stmt_commit");
+
+ if (savepoint_stmt == 1)
+ {
+ savepoint_stmt= 0;
+ result= txn_commit();
+ }
+ else
+ if (savepoint_stmt)
+ result= sp_release(&savepoint_stmt);
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_txn::stmt_rollback()
+{
+ int result= 0;
+ DBUG_ENTER("federated:txn::stmt_rollback");
+
+ if (savepoint_stmt == 1)
+ {
+ savepoint_stmt= 0;
+ result= txn_rollback();
+ }
+ else
+ if (savepoint_stmt)
+ {
+ result= sp_rollback(&savepoint_stmt);
+ sp_release(&savepoint_stmt);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_txn::stmt_autocommit()
+{
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::stmt_autocommit");
+
+ for (io= txn_list; savepoint_stmt && io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ io->savepoint_restrict(savepoint_stmt);
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
=== added file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,3487 @@
+/*
+Copyright (c) 2008, Patrick Galbraith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of Patrick Galbraith nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*
+
+ FederatedX Pluggable Storage Engine
+
+ ha_federatedx.cc - FederatedX Pluggable Storage Engine
+ Patrick Galbraith, 2008
+
+ This is a handler which uses a foreign database as the data file, as
+ opposed to a handler like MyISAM, which uses .MYD files locally.
+
+ How this handler works
+ ----------------------------------
+ Normal database files are local and as such: You create a table called
+ 'users', a file such as 'users.MYD' is created. A handler reads, inserts,
+ deletes, updates data in this file. The data is stored in particular format,
+ so to read, that data has to be parsed into fields, to write, fields have to
+ be stored in this format to write to this data file.
+
+ With FederatedX storage engine, there will be no local files
+ for each table's data (such as .MYD). A foreign database will store
+ the data that would normally be in this file. This will necessitate
+ the use of MySQL client API to read, delete, update, insert this
+ data. The data will have to be retrieve via an SQL call "SELECT *
+ FROM users". Then, to read this data, it will have to be retrieved
+ via mysql_fetch_row one row at a time, then converted from the
+ column in this select into the format that the handler expects.
+
+ The create table will simply create the .frm file, and within the
+ "CREATE TABLE" SQL, there SHALL be any of the following :
+
+ connection=scheme://username:password@hostname:port/database/tablename
+ connection=scheme://username@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+
+ - OR -
+
+ As of 5.1 federatedx now allows you to use a non-url
+ format, taking advantage of mysql.servers:
+
+ connection="connection_one"
+ connection="connection_one/table_foo"
+
+ An example would be:
+
+ connection=mysql://username:password@hostname:port/database/tablename
+
+ or, if we had:
+
+ create server 'server_one' foreign data wrapper 'mysql' options
+ (HOST '127.0.0.1',
+ DATABASE 'db1',
+ USER 'root',
+ PASSWORD '',
+ PORT 3306,
+ SOCKET '',
+ OWNER 'root');
+
+ CREATE TABLE federatedx.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(64) NOT NULL default ''
+ )
+ ENGINE="FEDERATEDX" DEFAULT CHARSET=latin1
+ CONNECTION='server_one';
+
+ So, this will have been the equivalent of
+
+ CONNECTION="mysql://root@127.0.0.1:3306/db1/t1"
+
+ Then, we can also change the server to point to a new schema:
+
+ ALTER SERVER 'server_one' options(DATABASE 'db2');
+
+ All subsequent calls will now be against db2.t1! Guess what? You don't
+ have to perform an alter table!
+
+ This connecton="connection string" is necessary for the handler to be
+ able to connect to the foreign server, either by URL, or by server
+ name.
+
+
+ The basic flow is this:
+
+ SQL calls issues locally ->
+ mysql handler API (data in handler format) ->
+ mysql client API (data converted to SQL calls) ->
+ foreign database -> mysql client API ->
+ convert result sets (if any) to handler format ->
+ handler API -> results or rows affected to local
+
+ What this handler does and doesn't support
+ ------------------------------------------
+ * Tables MUST be created on the foreign server prior to any action on those
+ tables via the handler, first version. IMPORTANT: IF you MUST use the
+ federatedx storage engine type on the REMOTE end, MAKE SURE [ :) ] That
+ the table you connect to IS NOT a table pointing BACK to your ORIGNAL
+ table! You know and have heard the screaching of audio feedback? You
+ know putting two mirror in front of each other how the reflection
+ continues for eternity? Well, need I say more?!
+ * There will not be support for transactions.
+ * There is no way for the handler to know if the foreign database or table
+ has changed. The reason for this is that this database has to work like a
+ data file that would never be written to by anything other than the
+ database. The integrity of the data in the local table could be breached
+ if there was any change to the foreign database.
+ * Support for SELECT, INSERT, UPDATE , DELETE, indexes.
+ * No ALTER TABLE, DROP TABLE or any other Data Definition Language calls.
+ * Prepared statements will not be used in the first implementation, it
+ remains to to be seen whether the limited subset of the client API for the
+ server supports this.
+ * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its
+ implementation.
+ * This will not work with the query cache.
+
+ Method calls
+
+ A two column table, with one record:
+
+ (SELECT)
+
+ "SELECT * FROM foo"
+ ha_federatedx::info
+ ha_federatedx::scan_time:
+ ha_federatedx::rnd_init: share->select_query SELECT * FROM foo
+ ha_federatedx::extra
+
+ <for every row of data retrieved>
+ ha_federatedx::rnd_next
+ ha_federatedx::convert_row_to_internal_format
+ ha_federatedx::rnd_next
+ </for every row of data retrieved>
+
+ ha_federatedx::rnd_end
+ ha_federatedx::extra
+ ha_federatedx::reset
+
+ (INSERT)
+
+ "INSERT INTO foo (id, ts) VALUES (2, now());"
+
+ ha_federatedx::write_row
+
+ ha_federatedx::reset
+
+ (UPDATE)
+
+ "UPDATE foo SET ts = now() WHERE id = 1;"
+
+ ha_federatedx::index_init
+ ha_federatedx::index_read
+ ha_federatedx::index_read_idx
+ ha_federatedx::rnd_next
+ ha_federatedx::convert_row_to_internal_format
+ ha_federatedx::update_row
+
+ ha_federatedx::extra
+ ha_federatedx::extra
+ ha_federatedx::extra
+ ha_federatedx::external_lock
+ ha_federatedx::reset
+
+
+ How do I use this handler?
+ --------------------------
+
+ <insert text about plugin storage engine>
+
+ Next, to use this handler, it's very simple. You must
+ have two databases running, either both on the same host, or
+ on different hosts.
+
+ One the server that will be connecting to the foreign
+ host (client), you create your table as such:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="FEDERATEDX"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:9306/federatedx/test_federatedx';
+
+ Notice the "COMMENT" and "ENGINE" field? This is where you
+ respectively set the engine type, "FEDERATEDX" and foreign
+ host information, this being the database your 'client' database
+ will connect to and use as the "data file". Obviously, the foreign
+ database is running on port 9306, so you want to start up your other
+ database so that it is indeed on port 9306, and your federatedx
+ database on a port other than that. In my setup, I use port 5554
+ for federatedx, and port 5555 for the foreign database.
+
+ Then, on the foreign database:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="<NAME>" <-- whatever you want, or not specify
+ DEFAULT CHARSET=latin1 ;
+
+ This table is exactly the same (and must be exactly the same),
+ except that it is not using the federatedx handler and does
+ not need the URL.
+
+
+ How to see the handler in action
+ --------------------------------
+
+ When developing this handler, I compiled the federatedx database with
+ debugging:
+
+ ./configure --with-federatedx-storage-engine
+ --prefix=/home/mysql/mysql-build/federatedx/ --with-debug
+
+ Once compiled, I did a 'make install' (not for the purpose of installing
+ the binary, but to install all the files the binary expects to see in the
+ diretory I specified in the build with --prefix,
+ "/home/mysql/mysql-build/federatedx".
+
+ Then, I started the foreign server:
+
+ /usr/local/mysql/bin/mysqld_safe
+ --user=mysql --log=/tmp/mysqld.5555.log -P 5555
+
+ Then, I went back to the directory containing the newly compiled mysqld,
+ <builddir>/sql/, started up gdb:
+
+ gdb ./mysqld
+
+ Then, withn the (gdb) prompt:
+ (gdb) run --gdb --port=5554 --socket=/tmp/mysqld.5554 --skip-innodb --debug
+
+ Next, I open several windows for each:
+
+ 1. Tail the debug trace: tail -f /tmp/mysqld.trace|grep ha_fed
+ 2. Tail the SQL calls to the foreign database: tail -f /tmp/mysqld.5555.log
+ 3. A window with a client open to the federatedx server on port 5554
+ 4. A window with a client open to the federatedx server on port 5555
+
+ I would create a table on the client to the foreign server on port
+ 5555, and then to the federatedx server on port 5554. At this point,
+ I would run whatever queries I wanted to on the federatedx server,
+ just always remembering that whatever changes I wanted to make on
+ the table, or if I created new tables, that I would have to do that
+ on the foreign server.
+
+ Another thing to look for is 'show variables' to show you that you have
+ support for federatedx handler support:
+
+ show variables like '%federat%'
+
+ and:
+
+ show storage engines;
+
+ Both should display the federatedx storage handler.
+
+
+ Testing
+ -------
+
+ Testing for FederatedX as a pluggable storage engine for
+ now is a manual process that I intend to build a test
+ suite that works for all pluggable storage engines.
+
+ How to test
+
+ 1. cp fed.dat /tmp
+ (make sure you have access to "test". Use a user that has
+ super privileges for now)
+ 2. mysql -f -u root test < federated.test > federated.myresult 2>&1
+ 3. diff federated.result federated.myresult (there _should_ be no differences)
+
+
+*/
+
+
+#define MYSQL_SERVER 1q
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#include <mysql/plugin.h>
+
+/* Variables for federatedx share methods */
+static HASH federatedx_open_tables; // To track open tables
+static HASH federatedx_open_servers; // To track open servers
+pthread_mutex_t federatedx_mutex; // To init the hash
+const char ident_quote_char= '`'; // Character for quoting
+ // identifiers
+const char value_quote_char= '\''; // Character for quoting
+ // literals
+static const int bulk_padding= 64; // bytes "overhead" in packet
+
+/* Variables used when chopping off trailing characters */
+static const uint sizeof_trailing_comma= sizeof(", ") - 1;
+static const uint sizeof_trailing_closeparen= sizeof(") ") - 1;
+static const uint sizeof_trailing_and= sizeof(" AND ") - 1;
+static const uint sizeof_trailing_where= sizeof(" WHERE ") - 1;
+
+/* Static declaration for handerton */
+static handler *federatedx_create_handler(handlerton *hton,
+ TABLE_SHARE *table,
+ MEM_ROOT *mem_root);
+
+/* FederatedX storage engine handlerton */
+
+static handler *federatedx_create_handler(handlerton *hton,
+ TABLE_SHARE *table,
+ MEM_ROOT *mem_root)
+{
+ return new (mem_root) ha_federatedx(hton, table);
+}
+
+
+/* Function we use in the creation of our hash to get key */
+
+static uchar *
+federatedx_share_get_key(FEDERATEDX_SHARE *share, size_t *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= share->share_key_length;
+ return (uchar*) share->share_key;
+}
+
+
+static uchar *
+federatedx_server_get_key(FEDERATEDX_SERVER *server, size_t *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= server->key_length;
+ return server->key;
+}
+
+
+/*
+ Initialize the federatedx handler.
+
+ SYNOPSIS
+ federatedx_db_init()
+ p Handlerton
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+int federatedx_db_init(void *p)
+{
+ DBUG_ENTER("federatedx_db_init");
+ handlerton *federatedx_hton= (handlerton *)p;
+ federatedx_hton->state= SHOW_OPTION_YES;
+ /* This is no longer needed for plugin storage engines */
+ federatedx_hton->db_type= DB_TYPE_DEFAULT;
+ federatedx_hton->savepoint_offset= sizeof(ulong);
+ federatedx_hton->close_connection= ha_federatedx::disconnect;
+ federatedx_hton->savepoint_set= ha_federatedx::savepoint_set;
+ federatedx_hton->savepoint_rollback= ha_federatedx::savepoint_rollback;
+ federatedx_hton->savepoint_release= ha_federatedx::savepoint_release;
+ federatedx_hton->commit= ha_federatedx::commit;
+ federatedx_hton->rollback= ha_federatedx::rollback;
+ federatedx_hton->create= federatedx_create_handler;
+ federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION;
+
+ if (pthread_mutex_init(&federatedx_mutex, MY_MUTEX_INIT_FAST))
+ goto error;
+ if (!hash_init(&federatedx_open_tables, &my_charset_bin, 32, 0, 0,
+ (hash_get_key) federatedx_share_get_key, 0, 0) &&
+ !hash_init(&federatedx_open_servers, &my_charset_bin, 32, 0, 0,
+ (hash_get_key) federatedx_server_get_key, 0, 0))
+ {
+ DBUG_RETURN(FALSE);
+ }
+
+ VOID(pthread_mutex_destroy(&federatedx_mutex));
+error:
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Release the federatedx handler.
+
+ SYNOPSIS
+ federatedx_db_end()
+
+ RETURN
+ FALSE OK
+*/
+
+int federatedx_done(void *p)
+{
+ hash_free(&federatedx_open_tables);
+ hash_free(&federatedx_open_servers);
+ VOID(pthread_mutex_destroy(&federatedx_mutex));
+
+ return 0;
+}
+
+/**
+ @brief Append identifiers to the string.
+
+ @param[in,out] string The target string.
+ @param[in] name Identifier name
+ @param[in] length Length of identifier name in bytes
+ @param[in] quote_char Quote char to use for quoting identifier.
+
+ @return Operation Status
+ @retval FALSE OK
+ @retval TRUE There was an error appending to the string.
+
+ @note This function is based upon the append_identifier() function
+ in sql_show.cc except that quoting always occurs.
+*/
+
+bool append_ident(String *string, const char *name, uint length,
+ const char quote_char)
+{
+ bool result;
+ uint clen;
+ const char *name_end;
+ DBUG_ENTER("append_ident");
+
+ if (quote_char)
+ {
+ string->reserve(length * 2 + 2);
+ if ((result= string->append("e_char, 1, system_charset_info)))
+ goto err;
+
+ for (name_end= name+length; name < name_end; name+= clen)
+ {
+ uchar c= *(uchar *) name;
+ if (!(clen= my_mbcharlen(system_charset_info, c)))
+ clen= 1;
+ if (clen == 1 && c == (uchar) quote_char &&
+ (result= string->append("e_char, 1, system_charset_info)))
+ goto err;
+ if ((result= string->append(name, clen, string->charset())))
+ goto err;
+ }
+ result= string->append("e_char, 1, system_charset_info);
+ }
+ else
+ result= string->append(name, length, system_charset_info);
+
+err:
+ DBUG_RETURN(result);
+}
+
+
+static int parse_url_error(FEDERATEDX_SHARE *share, TABLE *table, int error_num)
+{
+ char buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ int buf_len;
+ DBUG_ENTER("ha_federatedx parse_url_error");
+
+ buf_len= min(table->s->connect_string.length,
+ FEDERATEDX_QUERY_BUFFER_SIZE-1);
+ strmake(buf, table->s->connect_string.str, buf_len);
+ my_error(error_num, MYF(0), buf);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ retrieve server object which contains server meta-data
+ from the system table given a server's name, set share
+ connection parameter members
+*/
+int get_connection(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share)
+{
+ int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ FOREIGN_SERVER *server, server_buffer;
+ DBUG_ENTER("ha_federatedx::get_connection");
+
+ /*
+ get_server_by_name() clones the server if exists and allocates
+ copies of strings in the supplied mem_root
+ */
+ if (!(server=
+ get_server_by_name(mem_root, share->connection_string, &server_buffer)))
+ {
+ DBUG_PRINT("info", ("get_server_by_name returned > 0 error condition!"));
+ /* need to come up with error handling */
+ error_num=1;
+ goto error;
+ }
+ DBUG_PRINT("info", ("get_server_by_name returned server at %lx",
+ (long unsigned int) server));
+
+ /*
+ Most of these should never be empty strings, error handling will
+ need to be implemented. Also, is this the best way to set the share
+ members? Is there some allocation needed? In running this code, it works
+ except there are errors in the trace file of the share being overrun
+ at the address of the share.
+ */
+ share->server_name_length= server->server_name_length;
+ share->server_name= server->server_name;
+ share->username= server->username;
+ share->password= server->password;
+ share->database= server->db;
+#ifndef I_AM_PARANOID
+ share->port= server->port > 0 && server->port < 65536 ?
+#else
+ share->port= server->port > 1023 && server->port < 65536 ?
+#endif
+ (ushort) server->port : MYSQL_PORT;
+ share->hostname= server->host;
+ if (!(share->socket= server->socket) &&
+ !strcmp(share->hostname, my_localhost))
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ share->scheme= server->scheme;
+
+ DBUG_PRINT("info", ("share->username: %s", share->username));
+ DBUG_PRINT("info", ("share->password: %s", share->password));
+ DBUG_PRINT("info", ("share->hostname: %s", share->hostname));
+ DBUG_PRINT("info", ("share->database: %s", share->database));
+ DBUG_PRINT("info", ("share->port: %d", share->port));
+ DBUG_PRINT("info", ("share->socket: %s", share->socket));
+ DBUG_RETURN(0);
+
+error:
+ my_sprintf(error_buffer,
+ (error_buffer, "server name: '%s' doesn't exist!",
+ share->connection_string));
+ my_error(error_num, MYF(0), error_buffer);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ Parse connection info from table->s->connect_string
+
+ SYNOPSIS
+ parse_url()
+ mem_root MEM_ROOT pointer for memory allocation
+ share pointer to FEDERATEDX share
+ table pointer to current TABLE class
+ table_create_flag determines what error to throw
+
+ DESCRIPTION
+ Populates the share with information about the connection
+ to the foreign database that will serve as the data source.
+ This string must be specified (currently) in the "CONNECTION" field,
+ listed in the CREATE TABLE statement.
+
+ This string MUST be in the format of any of these:
+
+ CONNECTION="scheme://username:password@hostname:port/database/table"
+ CONNECTION="scheme://username@hostname/database/table"
+ CONNECTION="scheme://username@hostname:port/database/table"
+ CONNECTION="scheme://username:password@hostname/database/table"
+
+ _OR_
+
+ CONNECTION="connection name"
+
+
+
+ An Example:
+
+ CREATE TABLE t1 (id int(32))
+ ENGINE="FEDERATEDX"
+ CONNECTION="mysql://joe:joespass@192.168.1.111:9308/federatedx/testtable";
+
+ CREATE TABLE t2 (
+ id int(4) NOT NULL auto_increment,
+ name varchar(32) NOT NULL,
+ PRIMARY KEY(id)
+ ) ENGINE="FEDERATEDX" CONNECTION="my_conn";
+
+ ***IMPORTANT***
+ Currently, the FederatedX Storage Engine only supports connecting to another
+ Database ("scheme" of "mysql"). Connections using JDBC as well as
+ other connectors are in the planning stage.
+
+
+ 'password' and 'port' are both optional.
+
+ RETURN VALUE
+ 0 success
+ error_num particular error code
+
+*/
+
+static int parse_url(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share, TABLE *table,
+ uint table_create_flag)
+{
+ uint error_num= (table_create_flag ?
+ ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE :
+ ER_FOREIGN_DATA_STRING_INVALID);
+ DBUG_ENTER("ha_federatedx::parse_url");
+
+ share->port= 0;
+ share->socket= 0;
+ DBUG_PRINT("info", ("share at %lx", (long unsigned int) share));
+ DBUG_PRINT("info", ("Length: %u", (uint) table->s->connect_string.length));
+ DBUG_PRINT("info", ("String: '%.*s'", (int) table->s->connect_string.length,
+ table->s->connect_string.str));
+ share->connection_string= strmake_root(mem_root, table->s->connect_string.str,
+ table->s->connect_string.length);
+
+ DBUG_PRINT("info",("parse_url alloced share->connection_string %lx",
+ (long unsigned int) share->connection_string));
+
+ DBUG_PRINT("info",("share->connection_string: %s",share->connection_string));
+ /*
+ No :// or @ in connection string. Must be a straight connection name of
+ either "servername" or "servername/tablename"
+ */
+ if ((!strstr(share->connection_string, "://") &&
+ (!strchr(share->connection_string, '@'))))
+ {
+
+ DBUG_PRINT("info",
+ ("share->connection_string: %s internal format "
+ "share->connection_string: %lx",
+ share->connection_string,
+ (ulong) share->connection_string));
+
+ /* ok, so we do a little parsing, but not completely! */
+ share->parsed= FALSE;
+ /*
+ If there is a single '/' in the connection string, this means the user is
+ specifying a table name
+ */
+
+ if ((share->table_name= strchr(share->connection_string, '/')))
+ {
+ *share->table_name++= '\0';
+ share->table_name_length= strlen(share->table_name);
+
+ DBUG_PRINT("info",
+ ("internal format, parsed table_name "
+ "share->connection_string: %s share->table_name: %s",
+ share->connection_string, share->table_name));
+
+ /*
+ there better not be any more '/'s !
+ */
+ if (strchr(share->table_name, '/'))
+ goto error;
+ }
+ /*
+ Otherwise, straight server name, use tablename of federatedx table
+ as remote table name
+ */
+ else
+ {
+ /*
+ Connection specifies everything but, resort to
+ expecting remote and foreign table names to match
+ */
+ share->table_name= strmake_root(mem_root, table->s->table_name.str,
+ (share->table_name_length=
+ table->s->table_name.length));
+ DBUG_PRINT("info",
+ ("internal format, default table_name "
+ "share->connection_string: %s share->table_name: %s",
+ share->connection_string, share->table_name));
+ }
+
+ if ((error_num= get_connection(mem_root, share)))
+ goto error;
+ }
+ else
+ {
+ share->parsed= TRUE;
+ // Add a null for later termination of table name
+ share->connection_string[table->s->connect_string.length]= 0;
+ share->scheme= share->connection_string;
+ DBUG_PRINT("info",("parse_url alloced share->scheme: %lx",
+ (ulong) share->scheme));
+
+ /*
+ Remove addition of null terminator and store length
+ for each string in share
+ */
+ if (!(share->username= strstr(share->scheme, "://")))
+ goto error;
+ share->scheme[share->username - share->scheme]= '\0';
+
+ if (!federatedx_io::handles_scheme(share->scheme))
+ goto error;
+
+ share->username+= 3;
+
+ if (!(share->hostname= strchr(share->username, '@')))
+ goto error;
+ *share->hostname++= '\0'; // End username
+
+ if ((share->password= strchr(share->username, ':')))
+ {
+ *share->password++= '\0'; // End username
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
+ goto error;
+ /*
+ Found that if the string is:
+ user:@hostname:port/db/table
+ Then password is a null string, so set to NULL
+ */
+ if ((share->password[0] == '\0'))
+ share->password= NULL;
+ }
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
+ goto error;
+
+ if (!(share->database= strchr(share->hostname, '/')))
+ goto error;
+ *share->database++= '\0';
+
+ if ((share->sport= strchr(share->hostname, ':')))
+ {
+ *share->sport++= '\0';
+ if (share->sport[0] == '\0')
+ share->sport= NULL;
+ else
+ share->port= atoi(share->sport);
+ }
+
+ if (!(share->table_name= strchr(share->database, '/')))
+ goto error;
+ *share->table_name++= '\0';
+
+ share->table_name_length= strlen(share->table_name);
+
+ /* make sure there's not an extra / */
+ if ((strchr(share->table_name, '/')))
+ goto error;
+
+ if (share->hostname[0] == '\0')
+ share->hostname= NULL;
+
+ }
+ if (!share->port)
+ {
+ if (!share->hostname || strcmp(share->hostname, my_localhost) == 0)
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ else
+ share->port= MYSQL_PORT;
+ }
+
+ DBUG_PRINT("info",
+ ("scheme: %s username: %s password: %s hostname: %s "
+ "port: %d db: %s tablename: %s",
+ share->scheme, share->username, share->password,
+ share->hostname, share->port, share->database,
+ share->table_name));
+
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(parse_url_error(share, table, error_num));
+}
+
+/*****************************************************************************
+** FEDERATEDX tables
+*****************************************************************************/
+
+ha_federatedx::ha_federatedx(handlerton *hton,
+ TABLE_SHARE *table_arg)
+ :handler(hton, table_arg),
+ txn(0), io(0), stored_result(0)
+{
+ bzero(&bulk_insert, sizeof(bulk_insert));
+}
+
+
+/*
+ Convert MySQL result set row to handler internal format
+
+ SYNOPSIS
+ convert_row_to_internal_format()
+ record Byte pointer to record
+ row MySQL result set row from fetchrow()
+ result Result set to use
+
+ DESCRIPTION
+ This method simply iterates through a row returned via fetchrow with
+ values from a successful SELECT , and then stores each column's value
+ in the field object via the field object pointer (pointing to the table's
+ array of field object pointers). This is how the handler needs the data
+ to be stored to then return results back to the user
+
+ RETURN VALUE
+ 0 After fields have had field values stored from record
+*/
+
+uint ha_federatedx::convert_row_to_internal_format(uchar *record,
+ FEDERATEDX_IO_ROW *row,
+ FEDERATEDX_IO_RESULT *result)
+{
+ ulong *lengths;
+ Field **field;
+ int column= 0;
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
+ DBUG_ENTER("ha_federatedx::convert_row_to_internal_format");
+
+ lengths= io->fetch_lengths(result);
+
+ for (field= table->field; *field; field++, column++)
+ {
+ /*
+ index variable to move us through the row at the
+ same iterative step as the field
+ */
+ my_ptrdiff_t old_ptr;
+ old_ptr= (my_ptrdiff_t) (record - table->record[0]);
+ (*field)->move_field_offset(old_ptr);
+ if (io->is_column_null(row, column))
+ (*field)->set_null();
+ else
+ {
+ if (bitmap_is_set(table->read_set, (*field)->field_index))
+ {
+ (*field)->set_notnull();
+ (*field)->store(io->get_column_data(row, column), lengths[column], &my_charset_bin);
+ }
+ }
+ (*field)->move_field_offset(-old_ptr);
+ }
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_name(String *to, KEY_PART_INFO *part)
+{
+ DBUG_ENTER("emit_key_part_name");
+ if (append_ident(to, part->field->field_name,
+ strlen(part->field->field_name), ident_quote_char))
+ DBUG_RETURN(1); // Out of memory
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_element(String *to, KEY_PART_INFO *part,
+ bool needs_quotes, bool is_like,
+ const uchar *ptr, uint len)
+{
+ Field *field= part->field;
+ DBUG_ENTER("emit_key_part_element");
+
+ if (needs_quotes && to->append(STRING_WITH_LEN("'")))
+ DBUG_RETURN(1);
+
+ if (part->type == HA_KEYTYPE_BIT)
+ {
+ char buff[STRING_BUFFER_USUAL_SIZE], *buf= buff;
+
+ *buf++= '0';
+ *buf++= 'x';
+ buf= octet2hex(buf, (char*) ptr, len);
+ if (to->append((char*) buff, (uint)(buf - buff)))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_BLOB_PART)
+ {
+ String blob;
+ uint blob_length= uint2korr(ptr);
+ blob.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ blob_length, &my_charset_bin);
+ if (append_escaped(to, &blob))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ String varchar;
+ uint var_length= uint2korr(ptr);
+ varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ var_length, &my_charset_bin);
+ if (append_escaped(to, &varchar))
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ char strbuff[MAX_FIELD_WIDTH];
+ String str(strbuff, sizeof(strbuff), part->field->charset()), *res;
+
+ res= field->val_str(&str, ptr);
+
+ if (field->result_type() == STRING_RESULT)
+ {
+ if (append_escaped(to, res))
+ DBUG_RETURN(1);
+ }
+ else if (to->append(res->ptr(), res->length()))
+ DBUG_RETURN(1);
+ }
+
+ if (is_like && to->append(STRING_WITH_LEN("%")))
+ DBUG_RETURN(1);
+
+ if (needs_quotes && to->append(STRING_WITH_LEN("'")))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Create a WHERE clause based off of values in keys
+ Note: This code was inspired by key_copy from key.cc
+
+ SYNOPSIS
+ create_where_from_key ()
+ to String object to store WHERE clause
+ key_info KEY struct pointer
+ key byte pointer containing key
+ key_length length of key
+ range_type 0 - no range, 1 - min range, 2 - max range
+ (see enum range_operation)
+
+ DESCRIPTION
+ Using iteration through all the keys via a KEY_PART_INFO pointer,
+ This method 'extracts' the value of each key in the byte pointer
+ *key, and for each key found, constructs an appropriate WHERE clause
+
+ RETURN VALUE
+ 0 After all keys have been accounted for to create the WHERE clause
+ 1 No keys found
+
+ Range flags Table per Timour:
+
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_OR_NEXT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+
+ records_in_range:
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_EXACT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+ * "=" -> HA_READ_AFTER_KEY
+
+0 HA_READ_KEY_EXACT, Find first record else error
+1 HA_READ_KEY_OR_NEXT, Record or next record
+2 HA_READ_KEY_OR_PREV, Record or previous
+3 HA_READ_AFTER_KEY, Find next rec. after key-record
+4 HA_READ_BEFORE_KEY, Find next rec. before key-record
+5 HA_READ_PREFIX, Key which as same prefix
+6 HA_READ_PREFIX_LAST, Last key with the same prefix
+7 HA_READ_PREFIX_LAST_OR_PREV, Last or prev key with the same prefix
+
+Flags that I've found:
+
+id, primary key, varchar
+
+id = 'ccccc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 'ccccc'
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id < 'ccccc'
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 'ccccc'
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id >= 'ccccc'
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id like 'cc%cc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id < 'ccccc'
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 'aaaaa' and id < 'ccccc';
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+numeric keys:
+
+id = 4
+index_read_idx: start_key 0 end_key NULL
+
+id > 4
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4
+full table scan, select * from
+
+id > 2 and id < 8
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 8
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 8
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 8
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+multi keys (id int, name varchar, other varchar)
+
+id = 1;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 4;
+id > 2 and name = '333'; remote: id > 2
+id > 2 and name > '333'; remote: id > 2
+id > 2 and name > '333' and other < 'ddd'; remote: id > 2 no results
+id > 2 and name >= '333' and other < 'ddd'; remote: id > 2 1 result
+id >= 4 and name = 'eric was here' and other > 'eeee';
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4;
+id >= 2 and name = '333' and other < 'ddd';
+remote: `id` >= 2 AND `name` >= '333';
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4;
+id < 3 and name = '222' and other <= 'ccc'; remote: id < 3
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4;
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4;
+full table scan
+
+id > 2 and id < 4;
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 4;
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 4;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 4;
+id = 6 and name = 'eric was here' and other > 'eeee';
+remote: (`id` > 6 AND `name` > 'eric was here' AND `other` > 'eeee')
+AND (`id` <= 6) AND ( AND `name` <= 'eric was here')
+no results
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+Summary:
+
+* If the start key flag is 0 the max key flag shouldn't even be set,
+ and if it is, the query produced would be invalid.
+* Multipart keys, even if containing some or all numeric columns,
+ are treated the same as non-numeric keys
+
+ If the query is " = " (quotes or not):
+ - records in range start key flag HA_READ_KEY_EXACT,
+ end key flag HA_READ_AFTER_KEY (incorrect)
+ - any other: start key flag HA_READ_KEY_OR_NEXT,
+ end key flag HA_READ_AFTER_KEY (correct)
+
+* 'like' queries (of key)
+ - Numeric, full table scan
+ - Non-numeric
+ records_in_range: start_key 0 end_key 3
+ other : start_key 1 end_key 3
+
+* If the key flag is HA_READ_AFTER_KEY:
+ if start_key, append >
+ if end_key, append <=
+
+* If create_where_key was called by records_in_range:
+
+ - if the key is numeric:
+ start key flag is 0 when end key is NULL, end key flag is 3 or 4
+ - if create_where_key was called by any other function:
+ start key flag is 1 when end key is NULL, end key flag is 3 or 4
+ - if the key is non-numeric, or multipart
+ When the query is an exact match, the start key flag is 0,
+ end key flag is 3 for what should be a no-range condition where
+ you should have 0 and max key NULL, which it is if called by
+ read_range_first
+
+Conclusion:
+
+1. Need logic to determin if a key is min or max when the flag is
+HA_READ_AFTER_KEY, and handle appending correct operator accordingly
+
+2. Need a boolean flag to pass to create_where_from_key, used in the
+switch statement. Add 1 to the flag if:
+ - start key flag is HA_READ_KEY_EXACT and the end key is NULL
+
+*/
+
+bool ha_federatedx::create_where_from_key(String *to,
+ KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool from_records_in_range,
+ bool eq_range)
+{
+ bool both_not_null=
+ (start_key != NULL && end_key != NULL) ? TRUE : FALSE;
+ const uchar *ptr;
+ uint remainder, length;
+ char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info);
+ const key_range *ranges[2]= { start_key, end_key };
+ my_bitmap_map *old_map;
+ DBUG_ENTER("ha_federatedx::create_where_from_key");
+
+ tmp.length(0);
+ if (start_key == NULL && end_key == NULL)
+ DBUG_RETURN(1);
+
+ old_map= dbug_tmp_use_all_columns(table, table->write_set);
+ for (uint i= 0; i <= 1; i++)
+ {
+ bool needs_quotes;
+ KEY_PART_INFO *key_part;
+ if (ranges[i] == NULL)
+ continue;
+
+ if (both_not_null)
+ {
+ if (i > 0)
+ tmp.append(STRING_WITH_LEN(") AND ("));
+ else
+ tmp.append(STRING_WITH_LEN(" ("));
+ }
+
+ for (key_part= key_info->key_part,
+ remainder= key_info->key_parts,
+ length= ranges[i]->length,
+ ptr= ranges[i]->key; ;
+ remainder--,
+ key_part++)
+ {
+ Field *field= key_part->field;
+ uint store_length= key_part->store_length;
+ uint part_length= min(store_length, length);
+ needs_quotes= field->str_needs_quotes();
+ DBUG_DUMP("key, start of loop", ptr, length);
+
+ if (key_part->null_bit)
+ {
+ if (*ptr++)
+ {
+ /*
+ We got "IS [NOT] NULL" condition against nullable column. We
+ distinguish between "IS NOT NULL" and "IS NULL" by flag. For
+ "IS NULL", flag is set to HA_READ_KEY_EXACT.
+ */
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(ranges[i]->flag == HA_READ_KEY_EXACT ?
+ " IS NULL " : " IS NOT NULL "))
+ goto err;
+ /*
+ We need to adjust pointer and length to be prepared for next
+ key part. As well as check if this was last key part.
+ */
+ goto prepare_for_next_key_part;
+ }
+ }
+
+ if (tmp.append(STRING_WITH_LEN(" (")))
+ goto err;
+
+ switch (ranges[i]->flag) {
+ case HA_READ_KEY_EXACT:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_EXACT %d", i));
+ if (store_length >= length ||
+ !needs_quotes ||
+ key_part->type == HA_KEYTYPE_BIT ||
+ field->result_type() != STRING_RESULT)
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ goto err;
+
+ if (from_records_in_range)
+ {
+ if (tmp.append(STRING_WITH_LEN(" >= ")))
+ goto err;
+ }
+ else
+ {
+ if (tmp.append(STRING_WITH_LEN(" = ")))
+ goto err;
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ }
+ else
+ {
+ /* LIKE */
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" LIKE ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 1, ptr,
+ part_length))
+ goto err;
+ }
+ break;
+ case HA_READ_AFTER_KEY:
+ if (eq_range)
+ {
+ if (tmp.append("1=1")) // Dummy
+ goto err;
+ break;
+ }
+ DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i));
+ if (store_length >= length) /* end key */
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ goto err;
+
+ if (i > 0) /* end key */
+ {
+ if (tmp.append(STRING_WITH_LEN(" <= ")))
+ goto err;
+ }
+ else /* start key */
+ {
+ if (tmp.append(STRING_WITH_LEN(" > ")))
+ goto err;
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ {
+ goto err;
+ }
+ break;
+ }
+ case HA_READ_KEY_OR_NEXT:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_NEXT %d", i));
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" >= ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ case HA_READ_BEFORE_KEY:
+ DBUG_PRINT("info", ("federatedx HA_READ_BEFORE_KEY %d", i));
+ if (store_length >= length)
+ {
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" < ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ }
+ case HA_READ_KEY_OR_PREV:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_PREV %d", i));
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" <= ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ default:
+ DBUG_PRINT("info",("cannot handle flag %d", ranges[i]->flag));
+ goto err;
+ }
+ if (tmp.append(STRING_WITH_LEN(") ")))
+ goto err;
+
+prepare_for_next_key_part:
+ if (store_length >= length)
+ break;
+ DBUG_PRINT("info", ("remainder %d", remainder));
+ DBUG_ASSERT(remainder > 1);
+ length-= store_length;
+ /*
+ For nullable columns, null-byte is already skipped before, that is
+ ptr was incremented by 1. Since store_length still counts null-byte,
+ we need to subtract 1 from store_length.
+ */
+ ptr+= store_length - test(key_part->null_bit);
+ if (tmp.append(STRING_WITH_LEN(" AND ")))
+ goto err;
+
+ DBUG_PRINT("info",
+ ("create_where_from_key WHERE clause: %s",
+ tmp.c_ptr_quick()));
+ }
+ }
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+
+ if (both_not_null)
+ if (tmp.append(STRING_WITH_LEN(") ")))
+ DBUG_RETURN(1);
+
+ if (to->append(STRING_WITH_LEN(" WHERE ")))
+ DBUG_RETURN(1);
+
+ if (to->append(tmp))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+
+err:
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ DBUG_RETURN(1);
+}
+
+static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server,
+ FEDERATEDX_SHARE *share, CHARSET_INFO *table_charset)
+{
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String key(buffer, sizeof(buffer), &my_charset_bin);
+ String scheme(share->scheme, &my_charset_latin1);
+ String hostname(share->hostname, &my_charset_latin1);
+ String database(share->database, system_charset_info);
+ String username(share->username, system_charset_info);
+ String socket(share->socket ? share->socket : "", files_charset_info);
+ String password(share->password ? share->password : "", &my_charset_bin);
+ DBUG_ENTER("fill_server");
+
+ /* Do some case conversions */
+ scheme.reserve(scheme.length());
+ scheme.length(my_casedn_str(&my_charset_latin1, scheme.c_ptr_safe()));
+
+ hostname.reserve(hostname.length());
+ hostname.length(my_casedn_str(&my_charset_latin1, hostname.c_ptr_safe()));
+
+ if (lower_case_table_names)
+ {
+ database.reserve(database.length());
+ database.length(my_casedn_str(system_charset_info, database.c_ptr_safe()));
+ }
+
+ if (lower_case_file_system && socket.length())
+ {
+ socket.reserve(socket.length());
+ socket.length(my_casedn_str(files_charset_info, socket.c_ptr_safe()));
+ }
+
+ /* start with all bytes zeroed */
+ bzero(server, sizeof(*server));
+
+ key.length(0);
+ key.reserve(scheme.length() + hostname.length() + database.length() +
+ socket.length() + username.length() + password.length() +
+ sizeof(int) + 8);
+ key.append(scheme);
+ key.q_append('\0');
+ server->hostname= (const char *) (intptr) key.length();
+ key.append(hostname);
+ key.q_append('\0');
+ server->database= (const char *) (intptr) key.length();
+ key.append(database);
+ key.q_append('\0');
+ key.q_append((uint32) share->port);
+ server->socket= (const char *) (intptr) key.length();
+ key.append(socket);
+ key.q_append('\0');
+ server->username= (const char *) (intptr) key.length();
+ key.append(username);
+ key.q_append('\0');
+ server->password= (const char *) (intptr) key.length();
+ key.append(password);
+
+ server->key_length= key.length();
+ server->key= (uchar *) memdup_root(mem_root, key.ptr(), key.length()+1);
+
+ /* pointer magic */
+ server->scheme+= (intptr) server->key;
+ server->hostname+= (intptr) server->key;
+ server->database+= (intptr) server->key;
+ server->username+= (intptr) server->key;
+ server->password+= (intptr) server->key;
+ server->socket+= (intptr) server->key;
+ server->port= share->port;
+
+ if (!share->socket)
+ server->socket= NULL;
+ if (!share->password)
+ server->password= NULL;
+
+ if (table_charset)
+ server->csname= strdup_root(mem_root, table_charset->csname);
+
+ DBUG_VOID_RETURN;
+}
+
+
+static FEDERATEDX_SERVER *get_server(FEDERATEDX_SHARE *share, TABLE *table)
+{
+ FEDERATEDX_SERVER *server= NULL, tmp_server;
+ MEM_ROOT mem_root;
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String key(buffer, sizeof(buffer), &my_charset_bin);
+ String scheme(share->scheme, &my_charset_latin1);
+ String hostname(share->hostname, &my_charset_latin1);
+ String database(share->database, system_charset_info);
+ String username(share->username, system_charset_info);
+ String socket(share->socket ? share->socket : "", files_charset_info);
+ String password(share->password ? share->password : "", &my_charset_bin);
+ DBUG_ENTER("ha_federated.cc::get_server");
+
+ safe_mutex_assert_owner(&federatedx_mutex);
+
+ init_alloc_root(&mem_root, 4096, 4096);
+
+ fill_server(&mem_root, &tmp_server, share, table ? table->s->table_charset : 0);
+
+ if (!(server= (FEDERATEDX_SERVER *) hash_search(&federatedx_open_servers,
+ tmp_server.key,
+ tmp_server.key_length)))
+ {
+ if (!table || !tmp_server.csname)
+ goto error;
+
+ if (!(server= (FEDERATEDX_SERVER *) memdup_root(&mem_root,
+ (char *) &tmp_server,
+ sizeof(*server))))
+ goto error;
+
+ server->mem_root= mem_root;
+
+ if (my_hash_insert(&federatedx_open_servers, (uchar*) server))
+ goto error;
+
+ pthread_mutex_init(&server->mutex, MY_MUTEX_INIT_FAST);
+ }
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
+ server->use_count++;
+
+ DBUG_RETURN(server);
+error:
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
+}
+
+
+/*
+ Example of simple lock controls. The "share" it creates is structure we will
+ pass to each federatedx handler. Do you have to have one of these? Well, you
+ have pieces that are used for locking, and they are needed to function.
+*/
+
+static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
+{
+ char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ Field **field;
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ FEDERATEDX_SHARE *share= NULL, tmp_share;
+ MEM_ROOT mem_root;
+ DBUG_ENTER("ha_federatedx.cc::get_share");
+
+ /*
+ In order to use this string, we must first zero it's length,
+ or it will contain garbage
+ */
+ query.length(0);
+
+ bzero(&tmp_share, sizeof(tmp_share));
+ init_alloc_root(&mem_root, 256, 0);
+
+ pthread_mutex_lock(&federatedx_mutex);
+
+ tmp_share.share_key= table_name;
+ tmp_share.share_key_length= strlen(table_name);
+ if (parse_url(&mem_root, &tmp_share, table, 0))
+ goto error;
+
+ /* TODO: change tmp_share.scheme to LEX_STRING object */
+ if (!(share= (FEDERATEDX_SHARE *) hash_search(&federatedx_open_tables,
+ (uchar*) tmp_share.share_key,
+ tmp_share.
+ share_key_length)))
+ {
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("SELECT "));
+ for (field= table->field; *field; field++)
+ {
+ append_ident(&query, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+ query.append(STRING_WITH_LEN(", "));
+ }
+ /* chops off trailing comma */
+ query.length(query.length() - sizeof_trailing_comma);
+
+ query.append(STRING_WITH_LEN(" FROM "));
+
+ append_ident(&query, tmp_share.table_name,
+ tmp_share.table_name_length, ident_quote_char);
+
+ if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
+ !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length() + 1)))
+ goto error;
+
+ share->mem_root= mem_root;
+
+ DBUG_PRINT("info",
+ ("share->select_query %s", share->select_query));
+
+ if (!(share->s= get_server(share, table)))
+ goto error;
+
+ if (my_hash_insert(&federatedx_open_tables, (uchar*) share))
+ goto error;
+ thr_lock_init(&share->lock);
+ }
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
+ share->use_count++;
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ DBUG_RETURN(share);
+
+error:
+ pthread_mutex_unlock(&federatedx_mutex);
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
+}
+
+
+static int free_server(federatedx_txn *txn, FEDERATEDX_SERVER *server)
+{
+ bool destroy;
+ DBUG_ENTER("free_server");
+
+ pthread_mutex_lock(&federatedx_mutex);
+ if ((destroy= !--server->use_count))
+ hash_delete(&federatedx_open_servers, (uchar*) server);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (destroy)
+ {
+ MEM_ROOT mem_root;
+
+ txn->close(server);
+
+ DBUG_ASSERT(server->io_count == 0);
+
+ pthread_mutex_destroy(&server->mutex);
+ mem_root= server->mem_root;
+ free_root(&mem_root, MYF(0));
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Free lock controls. We call this whenever we close a table.
+ If the table had the last reference to the share then we
+ free memory associated with it.
+*/
+
+static int free_share(federatedx_txn *txn, FEDERATEDX_SHARE *share)
+{
+ bool destroy;
+ DBUG_ENTER("free_share");
+
+ pthread_mutex_lock(&federatedx_mutex);
+ if ((destroy= !--share->use_count))
+ hash_delete(&federatedx_open_tables, (uchar*) share);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (destroy)
+ {
+ MEM_ROOT mem_root;
+ FEDERATEDX_SERVER *server= share->s;
+
+ thr_lock_delete(&share->lock);
+
+ mem_root= share->mem_root;
+ free_root(&mem_root, MYF(0));
+
+ free_server(txn, server);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+ha_rows ha_federatedx::records_in_range(uint inx, key_range *start_key,
+ key_range *end_key)
+{
+ /*
+
+ We really want indexes to be used as often as possible, therefore
+ we just need to hard-code the return value to a very low number to
+ force the issue
+
+*/
+ DBUG_ENTER("ha_federatedx::records_in_range");
+ DBUG_RETURN(FEDERATEDX_RECORDS_IN_RANGE);
+}
+/*
+ If frm_error() is called then we will use this to to find out
+ what file extentions exist for the storage engine. This is
+ also used by the default rename_table and delete_table method
+ in handler.cc.
+*/
+
+const char **ha_federatedx::bas_ext() const
+{
+ static const char *ext[]=
+ {
+ NullS
+ };
+ return ext;
+}
+
+
+federatedx_txn *ha_federatedx::get_txn(THD *thd, bool no_create)
+{
+ federatedx_txn **txnp= (federatedx_txn **) ha_data(thd);
+ if (!*txnp && !no_create)
+ *txnp= new federatedx_txn();
+ return *txnp;
+}
+
+
+int ha_federatedx::disconnect(handlerton *hton, MYSQL_THD thd)
+{
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ delete txn;
+ return 0;
+}
+
+
+/*
+ Used for opening tables. The name will be the name of the file.
+ A table is opened when it needs to be opened. For instance
+ when a request comes in for a select on the table (tables are not
+ open and closed for each request, they are cached).
+
+ Called from handler.cc by handler::ha_open(). The server opens
+ all tables by calling ha_open() which then calls the handler
+ specific open().
+*/
+
+int ha_federatedx::open(const char *name, int mode, uint test_if_locked)
+{
+ int error;
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::open");
+
+ if (!(share= get_share(name, table)))
+ DBUG_RETURN(1);
+ thr_lock_data_init(&share->lock, &lock, NULL);
+
+ DBUG_ASSERT(io == NULL);
+
+ txn= get_txn(thd);
+
+ if ((error= txn->acquire(share, TRUE, &io)))
+ {
+ free_share(txn, share);
+ DBUG_RETURN(error);
+ }
+
+ txn->release(&io);
+
+ ref_length= (table->s->primary_key != MAX_KEY ?
+ table->key_info[table->s->primary_key].key_length :
+ table->s->reclength);
+ DBUG_PRINT("info", ("ref_length: %u", ref_length));
+
+ reset();
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Closes a table. We call the free_share() function to free any resources
+ that we have allocated in the "shared" structure.
+
+ Called from sql_base.cc, sql_select.cc, and table.cc.
+ In sql_select.cc it is only used to close up temporary tables or during
+ the process where a temporary table is converted over to being a
+ myisam table.
+ For sql_base.cc look at close_data_tables().
+*/
+
+int ha_federatedx::close(void)
+{
+ int retval, error;
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::close");
+
+ /* free the result set */
+ if (stored_result)
+ retval= free_result();
+
+ /* Disconnect from mysql */
+ if ((txn= get_txn(thd, true)))
+ txn->release(&io);
+
+ DBUG_ASSERT(io == NULL);
+
+ if ((error= free_share(txn, share)))
+ retval= error;
+ DBUG_RETURN(retval);
+}
+
+/*
+
+ Checks if a field in a record is SQL NULL.
+
+ SYNOPSIS
+ field_in_record_is_null()
+ table TABLE pointer, MySQL table object
+ field Field pointer, MySQL field object
+ record char pointer, contains record
+
+ DESCRIPTION
+ This method uses the record format information in table to track
+ the null bit in record.
+
+ RETURN VALUE
+ 1 if NULL
+ 0 otherwise
+*/
+
+static inline uint field_in_record_is_null(TABLE *table,
+ Field *field,
+ char *record)
+{
+ int null_offset;
+ DBUG_ENTER("ha_federatedx::field_in_record_is_null");
+
+ if (!field->null_ptr)
+ DBUG_RETURN(0);
+
+ null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]);
+
+ if (record[null_offset] & field->null_bit)
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Construct the INSERT statement.
+
+ @details This method will construct the INSERT statement and appends it to
+ the supplied query string buffer.
+
+ @return
+ @retval FALSE No error
+ @retval TRUE Failure
+*/
+
+bool ha_federatedx::append_stmt_insert(String *query)
+{
+ char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ Field **field;
+ uint tmp_length;
+ bool added_field= FALSE;
+
+ /* The main insert query string */
+ String insert_string(insert_buffer, sizeof(insert_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::append_stmt_insert");
+
+ insert_string.length(0);
+
+ if (replace_duplicates)
+ insert_string.append(STRING_WITH_LEN("REPLACE INTO "));
+ else if (ignore_duplicates && !insert_dup_update)
+ insert_string.append(STRING_WITH_LEN("INSERT IGNORE INTO "));
+ else
+ insert_string.append(STRING_WITH_LEN("INSERT INTO "));
+ append_ident(&insert_string, share->table_name, share->table_name_length,
+ ident_quote_char);
+ tmp_length= insert_string.length();
+ insert_string.append(STRING_WITH_LEN(" ("));
+
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that match the current query id
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ /* append the field name */
+ append_ident(&insert_string, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic if *(fields + 1) to
+ make the following appends conditional as we don't know if the
+ next field is in the write set
+ */
+ insert_string.append(STRING_WITH_LEN(", "));
+ added_field= TRUE;
+ }
+ }
+
+ if (added_field)
+ {
+ /* Remove trailing comma. */
+ insert_string.length(insert_string.length() - sizeof_trailing_comma);
+ insert_string.append(STRING_WITH_LEN(") "));
+ }
+ else
+ {
+ /* If there were no fields, we don't want to add a closing paren. */
+ insert_string.length(tmp_length);
+ }
+
+ insert_string.append(STRING_WITH_LEN(" VALUES "));
+
+ DBUG_RETURN(query->append(insert_string));
+}
+
+
+/*
+ write_row() inserts a row. No extra() hint is given currently if a bulk load
+ is happeneding. buf() is a byte array of data. You can use the field
+ information to extract the data from the native byte array type.
+ Example of this would be:
+ for (Field **field=table->field ; *field ; field++)
+ {
+ ...
+ }
+
+ Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
+ sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::write_row(uchar *buf)
+{
+ char values_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ Field **field;
+ uint tmp_length;
+ int error= 0;
+ bool use_bulk_insert;
+ bool auto_increment_update_required= (table->next_number_field != NULL);
+
+ /* The string containing the values to be added to the insert */
+ String values_string(values_buffer, sizeof(values_buffer), &my_charset_bin);
+ /* The actual value of the field, to be added to the values_string */
+ String insert_field_value_string(insert_field_value_buffer,
+ sizeof(insert_field_value_buffer),
+ &my_charset_bin);
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+ DBUG_ENTER("ha_federatedx::write_row");
+
+ values_string.length(0);
+ insert_field_value_string.length(0);
+ ha_statistic_increment(&SSV::ha_write_count);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
+
+ /*
+ start both our field and field values strings
+ We must disable multi-row insert for "INSERT...ON DUPLICATE KEY UPDATE"
+ Ignore duplicates is always true when insert_dup_update is true.
+ When replace_duplicates == TRUE, we can safely enable multi-row insert.
+ When performing multi-row insert, we only collect the columns values for
+ the row. The start of the statement is only created when the first
+ row is copied in to the bulk_insert string.
+ */
+ if (!(use_bulk_insert= bulk_insert.str &&
+ (!insert_dup_update || replace_duplicates)))
+ append_stmt_insert(&values_string);
+
+ values_string.append(STRING_WITH_LEN(" ("));
+ tmp_length= values_string.length();
+
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that is part of the write set
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ if ((*field)->is_null())
+ values_string.append(STRING_WITH_LEN(" NULL "));
+ else
+ {
+ bool needs_quote= (*field)->str_needs_quotes();
+ (*field)->val_str(&insert_field_value_string);
+ if (needs_quote)
+ values_string.append(value_quote_char);
+ insert_field_value_string.print(&values_string);
+ if (needs_quote)
+ values_string.append(value_quote_char);
+
+ insert_field_value_string.length(0);
+ }
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic if *(fields + 1) to
+ make the following appends conditional as we don't know if the
+ next field is in the write set
+ */
+ values_string.append(STRING_WITH_LEN(", "));
+ }
+ }
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+
+ /*
+ if there were no fields, we don't want to add a closing paren
+ AND, we don't want to chop off the last char '('
+ insert will be "INSERT INTO t1 VALUES ();"
+ */
+ if (values_string.length() > tmp_length)
+ {
+ /* chops off trailing comma */
+ values_string.length(values_string.length() - sizeof_trailing_comma);
+ }
+ /* we always want to append this, even if there aren't any fields */
+ values_string.append(STRING_WITH_LEN(") "));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (use_bulk_insert)
+ {
+ /*
+ Send the current bulk insert out if appending the current row would
+ cause the statement to overflow the packet size, otherwise set
+ auto_increment_update_required to FALSE as no query was executed.
+ */
+ if (bulk_insert.length + values_string.length() + bulk_padding >
+ io->max_query_size() && bulk_insert.length)
+ {
+ error= io->query(bulk_insert.str, bulk_insert.length);
+ bulk_insert.length= 0;
+ }
+ else
+ auto_increment_update_required= FALSE;
+
+ if (bulk_insert.length == 0)
+ {
+ char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String insert_string(insert_buffer, sizeof(insert_buffer),
+ &my_charset_bin);
+ insert_string.length(0);
+ append_stmt_insert(&insert_string);
+ dynstr_append_mem(&bulk_insert, insert_string.ptr(),
+ insert_string.length());
+ }
+ else
+ dynstr_append_mem(&bulk_insert, ",", 1);
+
+ dynstr_append_mem(&bulk_insert, values_string.ptr(),
+ values_string.length());
+ }
+ else
+ {
+ error= io->query(values_string.ptr(), values_string.length());
+ }
+
+ if (error)
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ /*
+ If the table we've just written a record to contains an auto_increment
+ field, then store the last_insert_id() value from the foreign server
+ */
+ if (auto_increment_update_required)
+ {
+ update_auto_increment();
+
+ /* mysql_insert() uses this for protocol return value */
+ table->next_number_field->store(stats.auto_increment_value, 1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Prepares the storage engine for bulk inserts.
+
+ @param[in] rows estimated number of rows in bulk insert
+ or 0 if unknown.
+
+ @details Initializes memory structures required for bulk insert.
+*/
+
+void ha_federatedx::start_bulk_insert(ha_rows rows)
+{
+ uint page_size;
+ DBUG_ENTER("ha_federatedx::start_bulk_insert");
+
+ dynstr_free(&bulk_insert);
+
+ /**
+ We don't bother with bulk-insert semantics when the estimated rows == 1
+ The rows value will be 0 if the server does not know how many rows
+ would be inserted. This can occur when performing INSERT...SELECT
+ */
+
+ if (rows == 1)
+ DBUG_VOID_RETURN;
+
+ /*
+ Make sure we have an open connection so that we know the
+ maximum packet size.
+ */
+ if (txn->acquire(share, FALSE, &io))
+ DBUG_VOID_RETURN;
+
+ page_size= (uint) my_getpagesize();
+
+ if (init_dynamic_string(&bulk_insert, NULL, page_size, page_size))
+ DBUG_VOID_RETURN;
+
+ bulk_insert.length= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief End bulk insert.
+
+ @details This method will send any remaining rows to the remote server.
+ Finally, it will deinitialize the bulk insert data structure.
+
+ @return Operation status
+ @retval 0 No error
+ @retval != 0 Error occured at remote server. Also sets my_errno.
+*/
+
+int ha_federatedx::end_bulk_insert(bool abort)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::end_bulk_insert");
+
+ if (bulk_insert.str && bulk_insert.length && !abort)
+ {
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+ if (io->query(bulk_insert.str, bulk_insert.length))
+ error= stash_remote_error();
+ else
+ if (table->next_number_field)
+ update_auto_increment();
+ }
+
+ dynstr_free(&bulk_insert);
+
+ DBUG_RETURN(my_errno= error);
+}
+
+
+/*
+ ha_federatedx::update_auto_increment
+
+ This method ensures that last_insert_id() works properly. What it simply does
+ is calls last_insert_id() on the foreign database immediately after insert
+ (if the table has an auto_increment field) and sets the insert id via
+ thd->insert_id(ID)).
+*/
+void ha_federatedx::update_auto_increment(void)
+{
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::update_auto_increment");
+
+ ha_federatedx::info(HA_STATUS_AUTO);
+ thd->first_successful_insert_id_in_cur_stmt=
+ stats.auto_increment_value;
+ DBUG_PRINT("info",("last_insert_id: %ld", (long) stats.auto_increment_value));
+
+ DBUG_VOID_RETURN;
+}
+
+int ha_federatedx::optimize(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ int error= 0;
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::optimize");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("OPTIMIZE TABLE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ error= stash_remote_error();
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::repair(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ int error= 0;
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::repair");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("REPAIR TABLE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+ if (check_opt->flags & T_QUICK)
+ query.append(STRING_WITH_LEN(" QUICK"));
+ if (check_opt->flags & T_EXTEND)
+ query.append(STRING_WITH_LEN(" EXTENDED"));
+ if (check_opt->sql_flags & TT_USEFRM)
+ query.append(STRING_WITH_LEN(" USE_FRM"));
+
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ error= stash_remote_error();
+
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Yes, update_row() does what you expect, it updates a row. old_data will have
+ the previous row record in it, while new_data will have the newest data in
+ it.
+
+ Keep in mind that the server can do updates based on ordering if an ORDER BY
+ clause was used. Consecutive ordering is not guaranteed.
+ Currently new_data will not have an updated auto_increament record, or
+ and updated timestamp field. You can do these for federatedx by doing these:
+ if (table->timestamp_on_update_now)
+ update_timestamp(new_row+table->timestamp_on_update_now-1);
+ if (table->next_number_field && record == table->record[0])
+ update_auto_increment();
+
+ Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
+*/
+
+int ha_federatedx::update_row(const uchar *old_data, uchar *new_data)
+{
+ /*
+ This used to control how the query was built. If there was a
+ primary key, the query would be built such that there was a where
+ clause with only that column as the condition. This is flawed,
+ because if we have a multi-part primary key, it would only use the
+ first part! We don't need to do this anyway, because
+ read_range_first will retrieve the correct record, which is what
+ is used to build the WHERE clause. We can however use this to
+ append a LIMIT to the end if there is NOT a primary key. Why do
+ this? Because we only are updating one record, and LIMIT enforces
+ this.
+ */
+ bool has_a_primary_key= test(table->s->primary_key != MAX_KEY);
+
+ /*
+ buffers for following strings
+ */
+ char field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char update_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char where_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+
+ /* Work area for field values */
+ String field_value(field_value_buffer, sizeof(field_value_buffer),
+ &my_charset_bin);
+ /* stores the update query */
+ String update_string(update_buffer,
+ sizeof(update_buffer),
+ &my_charset_bin);
+ /* stores the WHERE clause */
+ String where_string(where_buffer,
+ sizeof(where_buffer),
+ &my_charset_bin);
+ uchar *record= table->record[0];
+ int error;
+ DBUG_ENTER("ha_federatedx::update_row");
+ /*
+ set string lengths to 0 to avoid misc chars in string
+ */
+ field_value.length(0);
+ update_string.length(0);
+ where_string.length(0);
+
+ if (ignore_duplicates)
+ update_string.append(STRING_WITH_LEN("UPDATE IGNORE "));
+ else
+ update_string.append(STRING_WITH_LEN("UPDATE "));
+ append_ident(&update_string, share->table_name,
+ share->table_name_length, ident_quote_char);
+ update_string.append(STRING_WITH_LEN(" SET "));
+
+ /*
+ In this loop, we want to match column names to values being inserted
+ (while building INSERT statement).
+
+ Iterate through table->field (new data) and share->old_field (old_data)
+ using the same index to create an SQL UPDATE statement. New data is
+ used to create SET field=value and old data is used to create WHERE
+ field=oldvalue
+ */
+
+ for (Field **field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ uint field_name_length= strlen((*field)->field_name);
+ append_ident(&update_string, (*field)->field_name, field_name_length,
+ ident_quote_char);
+ update_string.append(STRING_WITH_LEN(" = "));
+
+ if ((*field)->is_null())
+ update_string.append(STRING_WITH_LEN(" NULL "));
+ else
+ {
+ /* otherwise = */
+ my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
+ bool needs_quote= (*field)->str_needs_quotes();
+ (*field)->val_str(&field_value);
+ if (needs_quote)
+ update_string.append(value_quote_char);
+ field_value.print(&update_string);
+ if (needs_quote)
+ update_string.append(value_quote_char);
+ field_value.length(0);
+ tmp_restore_column_map(table->read_set, old_map);
+ }
+ update_string.append(STRING_WITH_LEN(", "));
+ }
+
+ if (bitmap_is_set(table->read_set, (*field)->field_index))
+ {
+ uint field_name_length= strlen((*field)->field_name);
+ append_ident(&where_string, (*field)->field_name, field_name_length,
+ ident_quote_char);
+ if (field_in_record_is_null(table, *field, (char*) old_data))
+ where_string.append(STRING_WITH_LEN(" IS NULL "));
+ else
+ {
+ bool needs_quote= (*field)->str_needs_quotes();
+ where_string.append(STRING_WITH_LEN(" = "));
+ (*field)->val_str(&field_value,
+ (old_data + (*field)->offset(record)));
+ if (needs_quote)
+ where_string.append(value_quote_char);
+ field_value.print(&where_string);
+ if (needs_quote)
+ where_string.append(value_quote_char);
+ field_value.length(0);
+ }
+ where_string.append(STRING_WITH_LEN(" AND "));
+ }
+ }
+
+ /* Remove last ', '. This works as there must be at least on updated field */
+ update_string.length(update_string.length() - sizeof_trailing_comma);
+
+ if (where_string.length())
+ {
+ /* chop off trailing AND */
+ where_string.length(where_string.length() - sizeof_trailing_and);
+ update_string.append(STRING_WITH_LEN(" WHERE "));
+ update_string.append(where_string);
+ }
+
+ /*
+ If this table has not a primary key, then we could possibly
+ update multiple rows. We want to make sure to only update one!
+ */
+ if (!has_a_primary_key)
+ update_string.append(STRING_WITH_LEN(" LIMIT 1"));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(update_string.ptr(), update_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ This will delete a row. 'buf' will contain a copy of the row to be =deleted.
+ The server will call this right after the current row has been called (from
+ either a previous rnd_next() or index call).
+ If you keep a pointer to the last row or can access a primary key it will
+ make doing the deletion quite a bit easier.
+ Keep in mind that the server does no guarentee consecutive deletions.
+ ORDER BY clauses can be used.
+
+ Called in sql_acl.cc and sql_udf.cc to manage internal table information.
+ Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select
+ it is used for removing duplicates while in insert it is used for REPLACE
+ calls.
+*/
+
+int ha_federatedx::delete_row(const uchar *buf)
+{
+ char delete_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char data_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String delete_string(delete_buffer, sizeof(delete_buffer), &my_charset_bin);
+ String data_string(data_buffer, sizeof(data_buffer), &my_charset_bin);
+ uint found= 0;
+ int error;
+ DBUG_ENTER("ha_federatedx::delete_row");
+
+ delete_string.length(0);
+ delete_string.append(STRING_WITH_LEN("DELETE FROM "));
+ append_ident(&delete_string, share->table_name,
+ share->table_name_length, ident_quote_char);
+ delete_string.append(STRING_WITH_LEN(" WHERE "));
+
+ for (Field **field= table->field; *field; field++)
+ {
+ Field *cur_field= *field;
+ found++;
+ if (bitmap_is_set(table->read_set, cur_field->field_index))
+ {
+ append_ident(&delete_string, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+ data_string.length(0);
+ if (cur_field->is_null())
+ {
+ delete_string.append(STRING_WITH_LEN(" IS NULL "));
+ }
+ else
+ {
+ bool needs_quote= cur_field->str_needs_quotes();
+ delete_string.append(STRING_WITH_LEN(" = "));
+ cur_field->val_str(&data_string);
+ if (needs_quote)
+ delete_string.append(value_quote_char);
+ data_string.print(&delete_string);
+ if (needs_quote)
+ delete_string.append(value_quote_char);
+ }
+ delete_string.append(STRING_WITH_LEN(" AND "));
+ }
+ }
+
+ // Remove trailing AND
+ delete_string.length(delete_string.length() - sizeof_trailing_and);
+ if (!found)
+ delete_string.length(delete_string.length() - sizeof_trailing_where);
+
+ delete_string.append(STRING_WITH_LEN(" LIMIT 1"));
+ DBUG_PRINT("info",
+ ("Delete sql: %s", delete_string.c_ptr_quick()));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(delete_string.ptr(), delete_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ stats.deleted+= (ha_rows) io->affected_rows();
+ stats.records-= (ha_rows) io->affected_rows();
+ DBUG_PRINT("info",
+ ("rows deleted %ld rows deleted for all time %ld",
+ (long) io->affected_rows(), (long) stats.deleted));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Positions an index cursor to the index specified in the handle. Fetches the
+ row if available. If the key value is null, begin at the first key of the
+ index. This method, which is called in the case of an SQL statement having
+ a WHERE clause on a non-primary key index, simply calls index_read_idx.
+*/
+
+int ha_federatedx::index_read(uchar *buf, const uchar *key,
+ uint key_len, ha_rkey_function find_flag)
+{
+ DBUG_ENTER("ha_federatedx::index_read");
+
+ if (stored_result)
+ (void) free_result();
+ DBUG_RETURN(index_read_idx_with_result_set(buf, active_index, key,
+ key_len, find_flag,
+ &stored_result));
+}
+
+
+/*
+ Positions an index cursor to the index specified in key. Fetches the
+ row if any. This is only used to read whole keys.
+
+ This method is called via index_read in the case of a WHERE clause using
+ a primary key index OR is called DIRECTLY when the WHERE clause
+ uses a PRIMARY KEY index.
+
+ NOTES
+ This uses an internal result set that is deleted before function
+ returns. We need to be able to be callable from ha_rnd_pos()
+*/
+
+int ha_federatedx::index_read_idx(uchar *buf, uint index, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ int retval;
+ FEDERATEDX_IO_RESULT *io_result;
+ DBUG_ENTER("ha_federatedx::index_read_idx");
+
+ if ((retval= index_read_idx_with_result_set(buf, index, key,
+ key_len, find_flag,
+ &io_result)))
+ DBUG_RETURN(retval);
+ /* io is correct, as index_read_idx_with_result_set was ok */
+ io->free_result(io_result);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ Create result set for rows matching query and return first row
+
+ RESULT
+ 0 ok In this case *result will contain the result set
+ table->status == 0
+ # error In this case *result will contain 0
+ table->status == STATUS_NOT_FOUND
+*/
+
+int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index,
+ const uchar *key,
+ uint key_len,
+ ha_rkey_function find_flag,
+ FEDERATEDX_IO_RESULT **result)
+{
+ int retval;
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char index_value[STRING_BUFFER_USUAL_SIZE];
+ char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String index_string(index_value,
+ sizeof(index_value),
+ &my_charset_bin);
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ key_range range;
+ DBUG_ENTER("ha_federatedx::index_read_idx_with_result_set");
+
+ *result= 0; // In case of errors
+ index_string.length(0);
+ sql_query.length(0);
+ ha_statistic_increment(&SSV::ha_read_key_count);
+
+ sql_query.append(share->select_query);
+
+ range.key= key;
+ range.length= key_len;
+ range.flag= find_flag;
+ create_where_from_key(&index_string,
+ &table->key_info[index],
+ &range,
+ NULL, 0, 0);
+ sql_query.append(index_string);
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ if (io->query(sql_query.ptr(), sql_query.length()))
+ {
+ my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
+ io->error_code(), io->error_str()));
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ if (!(*result= io->store_result()))
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+ if (!(retval= read_next(buf, *result)))
+ DBUG_RETURN(retval);
+
+ io->free_result(*result);
+ *result= 0;
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ my_error(retval, MYF(0), error_buffer);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ This method is used exlusevely by filesort() to check if we
+ can create sorting buffers of necessary size.
+ If the handler returns more records that it declares
+ here server can just crash on filesort().
+ We cannot guarantee that's not going to happen with
+ the FEDERATEDX engine, as we have records==0 always if the
+ client is a VIEW, and for the table the number of
+ records can inpredictably change during execution.
+ So we return maximum possible value here.
+*/
+
+ha_rows ha_federatedx::estimate_rows_upper_bound()
+{
+ return HA_POS_ERROR;
+}
+
+
+/* Initialized at each key walk (called multiple times unlike rnd_init()) */
+
+int ha_federatedx::index_init(uint keynr, bool sorted)
+{
+ DBUG_ENTER("ha_federatedx::index_init");
+ DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr));
+ active_index= keynr;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Read first range
+*/
+
+int ha_federatedx::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range_arg, bool sorted)
+{
+ char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ int retval;
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::read_range_first");
+
+ DBUG_ASSERT(!(start_key == NULL && end_key == NULL));
+
+ sql_query.length(0);
+ sql_query.append(share->select_query);
+ create_where_from_key(&sql_query,
+ &table->key_info[active_index],
+ start_key, end_key, 0, eq_range_arg);
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ if (stored_result)
+ {
+ io->free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (io->query(sql_query.ptr(), sql_query.length()))
+ {
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ sql_query.length(0);
+
+ if (!(stored_result= io->store_result()))
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+
+ retval= read_next(table->record[0], stored_result);
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(retval);
+}
+
+
+int ha_federatedx::read_range_next()
+{
+ int retval;
+ DBUG_ENTER("ha_federatedx::read_range_next");
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+}
+
+
+/* Used to read forward through the index. */
+int ha_federatedx::index_next(uchar *buf)
+{
+ DBUG_ENTER("ha_federatedx::index_next");
+ ha_statistic_increment(&SSV::ha_read_next_count);
+ DBUG_RETURN(read_next(buf, stored_result));
+}
+
+
+/*
+ rnd_init() is called when the system wants the storage engine to do a table
+ scan.
+
+ This is the method that gets data for the SELECT calls.
+
+ See the federatedx in the introduction at the top of this file to see when
+ rnd_init() is called.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::rnd_init(bool scan)
+{
+ DBUG_ENTER("ha_federatedx::rnd_init");
+ /*
+ The use of the 'scan' flag is incredibly important for this handler
+ to work properly, especially with updates containing WHERE clauses
+ using indexed columns.
+
+ When the initial query contains a WHERE clause of the query using an
+ indexed column, it's index_read_idx that selects the exact record from
+ the foreign database.
+
+ When there is NO index in the query, either due to not having a WHERE
+ clause, or the WHERE clause is using columns that are not indexed, a
+ 'full table scan' done by rnd_init, which in this situation simply means
+ a 'select * from ...' on the foreign table.
+
+ In other words, this 'scan' flag gives us the means to ensure that if
+ there is an index involved in the query, we want index_read_idx to
+ retrieve the exact record (scan flag is 0), and do not want rnd_init
+ to do a 'full table scan' and wipe out that result set.
+
+ Prior to using this flag, the problem was most apparent with updates.
+
+ An initial query like 'UPDATE tablename SET anything = whatever WHERE
+ indexedcol = someval', index_read_idx would get called, using a query
+ constructed with a WHERE clause built from the values of index ('indexcol'
+ in this case, having a value of 'someval'). mysql_store_result would
+ then get called (this would be the result set we want to use).
+
+ After this rnd_init (from sql_update.cc) would be called, it would then
+ unecessarily call "select * from table" on the foreign table, then call
+ mysql_store_result, which would wipe out the correct previous result set
+ from the previous call of index_read_idx's that had the result set
+ containing the correct record, hence update the wrong row!
+
+ */
+
+ if (scan)
+ {
+ int error;
+
+ if ((error= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(error);
+
+ if (stored_result)
+ {
+ io->free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (io->query(share->select_query,
+ strlen(share->select_query)))
+ goto error;
+
+ stored_result= io->store_result();
+ if (!stored_result)
+ goto error;
+ }
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(stash_remote_error());
+}
+
+
+int ha_federatedx::rnd_end()
+{
+ DBUG_ENTER("ha_federatedx::rnd_end");
+ DBUG_RETURN(index_end());
+}
+
+
+int ha_federatedx::free_result()
+{
+ int error;
+ DBUG_ASSERT(stored_result);
+ if ((error= txn->acquire(share, FALSE, &io)))
+ {
+ DBUG_ASSERT(0); // Fail when testing
+ return error;
+ }
+ io->free_result(stored_result);
+ stored_result= 0;
+ return 0;
+}
+
+int ha_federatedx::index_end(void)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::index_end");
+ if (stored_result)
+ error= free_result();
+ active_index= MAX_KEY;
+ DBUG_RETURN(error);
+}
+
+
+/*
+ This is called for each row of the table scan. When you run out of records
+ you should return HA_ERR_END_OF_FILE. Fill buff up with the row information.
+ The Field structure for the table is the key to getting data into buf
+ in a manner that will allow the server to understand it.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::rnd_next(uchar *buf)
+{
+ DBUG_ENTER("ha_federatedx::rnd_next");
+
+ if (stored_result == 0)
+ {
+ /*
+ Return value of rnd_init is not always checked (see records.cc),
+ so we can get here _even_ if there is _no_ pre-fetched result-set!
+ TODO: fix it. We can delete this in 5.1 when rnd_init() is checked.
+ */
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(read_next(buf, stored_result));
+}
+
+
+/*
+ ha_federatedx::read_next
+
+ reads from a result set and converts to mysql internal
+ format
+
+ SYNOPSIS
+ field_in_record_is_null()
+ buf byte pointer to record
+ result mysql result set
+
+ DESCRIPTION
+ This method is a wrapper method that reads one record from a result
+ set and converts it to the internal table format
+
+ RETURN VALUE
+ 1 error
+ 0 no error
+*/
+
+int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result)
+{
+ int retval;
+ FEDERATEDX_IO_ROW *row;
+ DBUG_ENTER("ha_federatedx::read_next");
+
+ table->status= STATUS_NOT_FOUND; // For easier return
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ /* Fetch a row, insert it back in a row format. */
+ if (!(row= io->fetch_row(result)))
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ if (!(retval= convert_row_to_internal_format(buf, row, result)))
+ table->status= 0;
+
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ store reference to current row so that we can later find it for
+ a re-read, update or delete.
+
+ In case of federatedx, a reference is either a primary key or
+ the whole record.
+
+ Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
+*/
+
+void ha_federatedx::position(const uchar *record)
+{
+ DBUG_ENTER("ha_federatedx::position");
+ if (table->s->primary_key != MAX_KEY)
+ key_copy(ref, (uchar *)record, table->key_info + table->s->primary_key,
+ ref_length);
+ else
+ memcpy(ref, record, ref_length);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This is like rnd_next, but you are given a position to use to determine the
+ row. The position will be of the type that you stored in ref.
+
+ This method is required for an ORDER BY
+
+ Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
+*/
+
+int ha_federatedx::rnd_pos(uchar *buf, uchar *pos)
+{
+ int result;
+ DBUG_ENTER("ha_federatedx::rnd_pos");
+ ha_statistic_increment(&SSV::ha_read_rnd_count);
+ if (table->s->primary_key != MAX_KEY)
+ {
+ /* We have a primary key, so use index_read_idx to find row */
+ result= index_read_idx(buf, table->s->primary_key, pos,
+ ref_length, HA_READ_KEY_EXACT);
+ }
+ else
+ {
+ /* otherwise, get the old record ref as obtained in ::position */
+ memcpy(buf, pos, ref_length);
+ result= 0;
+ }
+ table->status= result ? STATUS_NOT_FOUND : 0;
+ DBUG_RETURN(result);
+}
+
+
+/*
+ ::info() is used to return information to the optimizer.
+ Currently this table handler doesn't implement most of the fields
+ really needed. SHOW also makes use of this data
+ Another note, you will probably want to have the following in your
+ code:
+ if (records < 2)
+ records = 2;
+ The reason is that the server will optimize for cases of only a single
+ record. If in a table scan you don't know the number of records
+ it will probably be better to set records to two so you can return
+ as many records as you need.
+ Along with records a few more variables you may wish to set are:
+ records
+ deleted
+ data_file_length
+ index_file_length
+ delete_length
+ check_time
+ Take a look at the public variables in handler.h for more information.
+
+ Called in:
+ filesort.cc
+ ha_heap.cc
+ item_sum.cc
+ opt_sum.cc
+ sql_delete.cc
+ sql_delete.cc
+ sql_derived.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_table.cc
+ sql_union.cc
+ sql_update.cc
+
+*/
+
+int ha_federatedx::info(uint flag)
+{
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ uint error_code;
+ federatedx_io *tmp_io= 0;
+ DBUG_ENTER("ha_federatedx::info");
+
+ error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+
+ /* we want not to show table status if not needed to do so */
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO))
+ {
+ if ((error_code= txn->acquire(share, TRUE, &tmp_io)))
+ goto fail;
+ }
+
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST))
+ {
+ /*
+ size of IO operations (This is based on a good guess, no high science
+ involved)
+ */
+ if (flag & HA_STATUS_CONST)
+ stats.block_size= 4096;
+
+ if (tmp_io->table_metadata(&stats, share->table_name,
+ share->table_name_length, flag))
+ goto error;
+ }
+
+ if (flag & HA_STATUS_AUTO)
+ stats.auto_increment_value= tmp_io->last_insert_id();
+
+ /*
+ If ::info created it's own transaction, close it. This happens in case
+ of show table status;
+ */
+ txn->release(&tmp_io);
+
+ DBUG_RETURN(0);
+
+error:
+ if (tmp_io)
+ {
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ tmp_io->error_code(), tmp_io->error_str()));
+ my_error(error_code, MYF(0), error_buffer);
+ }
+ else
+ if (remote_error_number != -1 /* error already reported */)
+ {
+ error_code= remote_error_number;
+ my_error(error_code, MYF(0), ER(error_code));
+ }
+fail:
+ txn->release(&tmp_io);
+ DBUG_RETURN(error_code);
+}
+
+
+/**
+ @brief Handles extra signals from MySQL server
+
+ @param[in] operation Hint for storage engine
+
+ @return Operation Status
+ @retval 0 OK
+ */
+int ha_federatedx::extra(ha_extra_function operation)
+{
+ DBUG_ENTER("ha_federatedx::extra");
+ switch (operation) {
+ case HA_EXTRA_IGNORE_DUP_KEY:
+ ignore_duplicates= TRUE;
+ break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ insert_dup_update= FALSE;
+ ignore_duplicates= FALSE;
+ break;
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ replace_duplicates= TRUE;
+ break;
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ /*
+ We use this flag to ensure that we do not create an "INSERT IGNORE"
+ statement when inserting new rows into the remote table.
+ */
+ replace_duplicates= FALSE;
+ break;
+ case HA_EXTRA_INSERT_WITH_UPDATE:
+ insert_dup_update= TRUE;
+ break;
+ default:
+ /* do nothing */
+ DBUG_PRINT("info",("unhandled operation: %d", (uint) operation));
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Reset state of file to after 'open'.
+
+ @detail This function is called after every statement for all tables
+ used by that statement.
+
+ @return Operation status
+ @retval 0 OK
+*/
+
+int ha_federatedx::reset(void)
+{
+ insert_dup_update= FALSE;
+ ignore_duplicates= FALSE;
+ replace_duplicates= FALSE;
+ return 0;
+}
+
+
+/*
+ Used to delete all rows in a table. Both for cases of truncate and
+ for cases where the optimizer realizes that all rows will be
+ removed as a result of a SQL statement.
+
+ Called from item_sum.cc by Item_func_group_concat::clear(),
+ Item_sum_count_distinct::clear(), and Item_func_group_concat::clear().
+ Called from sql_delete.cc by mysql_delete().
+ Called from sql_select.cc by JOIN::reinit().
+ Called from sql_union.cc by st_select_lex_unit::exec().
+*/
+
+int ha_federatedx::delete_all_rows()
+{
+ char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ int error;
+ DBUG_ENTER("ha_federatedx::delete_all_rows");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("TRUNCATE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+
+ /* no need for savepoint in autocommit mode */
+ if (!(ha_thd()->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ txn->stmt_autocommit();
+
+ /*
+ TRUNCATE won't return anything in mysql_affected_rows
+ */
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ stats.deleted+= stats.records;
+ stats.records= 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ The idea with handler::store_lock() is the following:
+
+ The statement decided which locks we should need for the table
+ for updates/deletes/inserts we get WRITE locks, for SELECT... we get
+ read locks.
+
+ Before adding the lock into the table lock handler (see thr_lock.c)
+ mysqld calls store lock with the requested locks. Store lock can now
+ modify a write lock to a read lock (or some other lock), ignore the
+ lock (if we don't want to use MySQL table locks at all) or add locks
+ for many tables (like we do when we are using a MERGE handler).
+
+ Berkeley DB for federatedx changes all WRITE locks to TL_WRITE_ALLOW_WRITE
+ (which signals that we are doing WRITES, but we are still allowing other
+ reader's and writer's.
+
+ When releasing locks, store_lock() are also called. In this case one
+ usually doesn't have to do anything.
+
+ In some exceptional cases MySQL may send a request for a TL_IGNORE;
+ This means that we are requesting the same lock as last time and this
+ should also be ignored. (This may happen when someone does a flush
+ table when we have opened a part of the tables, in which case mysqld
+ closes and reopens the tables and tries to get the same locks at last
+ time). In the future we will probably try to remove this.
+
+ Called from lock.cc by get_lock_data().
+*/
+
+THR_LOCK_DATA **ha_federatedx::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ DBUG_ENTER("ha_federatedx::store_lock");
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ {
+ /*
+ Here is where we get into the guts of a row level lock.
+ If TL_UNLOCK is set
+ If we are not doing a LOCK TABLE or DISCARD/IMPORT
+ TABLESPACE, then allow multiple writers
+ */
+
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
+ lock_type <= TL_WRITE) && !thd->in_lock_tables)
+ lock_type= TL_WRITE_ALLOW_WRITE;
+
+ /*
+ In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+ MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+ would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+ to t2. Convert the lock to a normal read lock to allow
+ concurrent inserts to t2.
+ */
+
+ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
+ lock_type= TL_READ;
+
+ lock.type= lock_type;
+ }
+
+ *to++= &lock;
+
+ DBUG_RETURN(to);
+}
+
+
+static int test_connection(MYSQL_THD thd, federatedx_io *io,
+ FEDERATEDX_SHARE *share)
+{
+ char buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String str(buffer, sizeof(buffer), &my_charset_bin);
+ FEDERATEDX_IO_RESULT *resultset= NULL;
+ int retval;
+
+ str.length(0);
+ str.append(STRING_WITH_LEN("SELECT * FROM "));
+ append_identifier(thd, &str, share->table_name,
+ share->table_name_length);
+ str.append(STRING_WITH_LEN(" WHERE 1=0"));
+
+ if ((retval= io->query(str.ptr(), str.length())))
+ {
+ my_sprintf(buffer, (buffer,
+ "database: '%s' username: '%s' hostname: '%s'",
+ share->database, share->username, share->hostname));
+ DBUG_PRINT("info", ("error-code: %d", io->error_code()));
+ my_error(ER_CANT_CREATE_FEDERATED_TABLE, MYF(0), buffer);
+ }
+ else
+ resultset= io->store_result();
+
+ io->free_result(resultset);
+
+ return retval;
+}
+
+/*
+ create() does nothing, since we have no local setup of our own.
+ FUTURE: We should potentially connect to the foreign database and
+*/
+
+int ha_federatedx::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int retval;
+ THD *thd= current_thd;
+ FEDERATEDX_SHARE tmp_share; // Only a temporary share, to test the url
+ federatedx_txn *tmp_txn;
+ federatedx_io *tmp_io= NULL;
+ DBUG_ENTER("ha_federatedx::create");
+
+ if ((retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1)))
+ goto error;
+
+ /* loopback socket connections hang due to LOCK_open mutex */
+ if ((!tmp_share.hostname || !strcmp(tmp_share.hostname,my_localhost)) &&
+ !tmp_share.port)
+ goto error;
+
+ /*
+ If possible, we try to use an existing network connection to
+ the remote server. To ensure that no new FEDERATEDX_SERVER
+ instance is created, we pass NULL in get_server() TABLE arg.
+ */
+ pthread_mutex_lock(&federatedx_mutex);
+ tmp_share.s= get_server(&tmp_share, NULL);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (tmp_share.s)
+ {
+ tmp_txn= get_txn(thd);
+ if (!(retval= tmp_txn->acquire(&tmp_share, TRUE, &tmp_io)))
+ {
+ retval= test_connection(thd, tmp_io, &tmp_share);
+ tmp_txn->release(&tmp_io);
+ }
+ free_server(tmp_txn, tmp_share.s);
+ }
+ else
+ {
+ FEDERATEDX_SERVER server;
+
+#ifdef NOT_YET
+ /*
+ Bug#25679
+ Ensure that we do not hold the LOCK_open mutex while attempting
+ to establish FederatedX connection to guard against a trivial
+ Denial of Service scenerio.
+ */
+ safe_mutex_assert_not_owner(&LOCK_open);
+#endif
+
+ fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset);
+
+#ifndef DBUG_OFF
+ pthread_mutex_init(&server.mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_lock(&server.mutex);
+#endif
+
+ tmp_io= federatedx_io::construct(thd->mem_root, &server);
+
+ retval= test_connection(thd, tmp_io, &tmp_share);
+
+#ifndef DBUG_OFF
+ pthread_mutex_unlock(&server.mutex);
+ pthread_mutex_destroy(&server.mutex);
+#endif
+
+ delete tmp_io;
+ }
+
+error:
+ DBUG_RETURN(retval);
+
+}
+
+
+int ha_federatedx::stash_remote_error()
+{
+ DBUG_ENTER("ha_federatedx::stash_remote_error()");
+ if (!io)
+ DBUG_RETURN(remote_error_number);
+ remote_error_number= io->error_code();
+ strmake(remote_error_buf, io->error_str(), sizeof(remote_error_buf)-1);
+ if (remote_error_number == ER_DUP_ENTRY ||
+ remote_error_number == ER_DUP_KEY)
+ DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
+ DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM);
+}
+
+
+bool ha_federatedx::get_error_message(int error, String* buf)
+{
+ DBUG_ENTER("ha_federatedx::get_error_message");
+ DBUG_PRINT("enter", ("error: %d", error));
+ if (error == HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM)
+ {
+ buf->append(STRING_WITH_LEN("Error on remote system: "));
+ buf->qs_append(remote_error_number);
+ buf->append(STRING_WITH_LEN(": "));
+ buf->append(remote_error_buf);
+
+ remote_error_number= 0;
+ remote_error_buf[0]= '\0';
+ }
+ DBUG_PRINT("exit", ("message: %s", buf->ptr()));
+ DBUG_RETURN(FALSE);
+}
+
+
+int ha_federatedx::start_stmt(MYSQL_THD thd, thr_lock_type lock_type)
+{
+ DBUG_ENTER("ha_federatedx::start_stmt");
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if (!txn->in_transaction())
+ {
+ txn->stmt_begin();
+ trans_register_ha(thd, FALSE, ht);
+ }
+ DBUG_RETURN(0);
+}
+
+
+int ha_federatedx::external_lock(MYSQL_THD thd, int lock_type)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::external_lock");
+
+ if (lock_type == F_UNLCK)
+ txn->release(&io);
+ else
+ {
+ txn= get_txn(thd);
+ if (!(error= txn->acquire(share, lock_type == F_RDLCK, &io)) &&
+ (lock_type == F_WRLCK || !io->is_autocommit()))
+ {
+ if (!thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ {
+ txn->stmt_begin();
+ trans_register_ha(thd, FALSE, ht);
+ }
+ else
+ {
+ txn->txn_begin();
+ trans_register_ha(thd, TRUE, ht);
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv)
+{
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_set");
+
+ if (txn && txn->has_connections())
+ {
+ if (txn->txn_begin())
+ trans_register_ha(thd, TRUE, hton);
+
+ txn->sp_acquire((ulong *) sv);
+
+ DBUG_ASSERT(1 < *(ulong *) sv);
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv)
+ {
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_rollback");
+
+ if (txn)
+ error= txn->sp_rollback((ulong *) sv);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv)
+{
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_release");
+
+ if (txn)
+ error= txn->sp_release((ulong *) sv);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::commit(handlerton *hton, MYSQL_THD thd, bool all)
+{
+ int return_val;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::commit");
+
+ if (all)
+ return_val= txn->txn_commit();
+ else
+ return_val= txn->stmt_commit();
+
+ DBUG_PRINT("info", ("error val: %d", return_val));
+ DBUG_RETURN(return_val);
+}
+
+
+int ha_federatedx::rollback(handlerton *hton, MYSQL_THD thd, bool all)
+{
+ int return_val;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::rollback");
+
+ if (all)
+ return_val= txn->txn_rollback();
+ else
+ return_val= txn->stmt_rollback();
+
+ DBUG_PRINT("info", ("error val: %d", return_val));
+ DBUG_RETURN(return_val);
+}
+
+struct st_mysql_storage_engine federatedx_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federatedx_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith",
+ "FederatedX pluggable storage engine",
+ PLUGIN_LICENSE_GPL,
+ federatedx_db_init, /* Plugin Init */
+ federatedx_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
=== added file 'storage/federatedx/ha_federatedx.h'
--- a/storage/federatedx/ha_federatedx.h 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ha_federatedx.h 2009-10-30 18:50:56 +0000
@@ -0,0 +1,446 @@
+/*
+Copyright (c) 2008, Patrick Galbraith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the name of Patrick Galbraith nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+class federatedx_io;
+
+/*
+ FEDERATEDX_SERVER will eventually be a structure that will be shared among
+ all FEDERATEDX_SHARE instances so that the federated server can minimise
+ the number of open connections. This will eventually lead to the support
+ of reliable XA federated tables.
+*/
+typedef struct st_fedrated_server {
+ MEM_ROOT mem_root;
+ uint use_count, io_count;
+
+ uchar *key;
+ uint key_length;
+
+ const char *scheme;
+ const char *hostname;
+ const char *username;
+ const char *password;
+ const char *database;
+ const char *socket;
+ ushort port;
+
+ const char *csname;
+
+ pthread_mutex_t mutex;
+ federatedx_io *idle_list;
+} FEDERATEDX_SERVER;
+
+/*
+ Please read ha_exmple.cc before reading this file.
+ Please keep in mind that the federatedx storage engine implements all methods
+ that are required to be implemented. handler.h has a full list of methods
+ that you can implement.
+*/
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+#include <mysql.h>
+
+/*
+ handler::print_error has a case statement for error numbers.
+ This value is (10000) is far out of range and will envoke the
+ default: case.
+ (Current error range is 120-159 from include/my_base.h)
+*/
+#define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000
+
+#define FEDERATEDX_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5
+#define FEDERATEDX_RECORDS_IN_RANGE 2
+#define FEDERATEDX_MAX_KEY_LENGTH 3500 // Same as innodb
+
+/*
+ FEDERATEDX_SHARE is a structure that will be shared amoung all open handlers
+ The example implements the minimum of what you will probably need.
+*/
+typedef struct st_federatedx_share {
+ MEM_ROOT mem_root;
+
+ bool parsed;
+ /* this key is unique db/tablename */
+ const char *share_key;
+ /*
+ the primary select query to be used in rnd_init
+ */
+ char *select_query;
+ /*
+ remote host info, parse_url supplies
+ */
+ char *server_name;
+ char *connection_string;
+ char *scheme;
+ char *hostname;
+ char *username;
+ char *password;
+ char *database;
+ char *table_name;
+ char *table;
+ char *socket;
+ char *sport;
+ int share_key_length;
+ ushort port;
+
+ uint table_name_length, server_name_length, connect_string_length;
+ uint use_count;
+ THR_LOCK lock;
+ FEDERATEDX_SERVER *s;
+} FEDERATEDX_SHARE;
+
+
+typedef struct st_federatedx_result FEDERATEDX_IO_RESULT;
+typedef struct st_federatedx_row FEDERATEDX_IO_ROW;
+typedef ptrdiff_t FEDERATEDX_IO_OFFSET;
+
+class federatedx_io
+{
+ friend class federatedx_txn;
+ FEDERATEDX_SERVER * const server;
+ federatedx_io **owner_ptr;
+ federatedx_io *txn_next;
+ federatedx_io *idle_next;
+ bool active; /* currently participating in a transaction */
+ bool busy; /* in use by a ha_federated instance */
+ bool readonly;/* indicates that no updates have occurred */
+
+protected:
+ void set_active(bool new_active)
+ { active= new_active; }
+public:
+ federatedx_io(FEDERATEDX_SERVER *);
+ virtual ~federatedx_io();
+
+ bool is_readonly() const { return readonly; }
+ bool is_active() const { return active; }
+
+ const char * get_charsetname() const
+ { return server->csname ? server->csname : "latin1"; }
+
+ const char * get_hostname() const { return server->hostname; }
+ const char * get_username() const { return server->username; }
+ const char * get_password() const { return server->password; }
+ const char * get_database() const { return server->database; }
+ ushort get_port() const { return server->port; }
+ const char * get_socket() const { return server->socket; }
+
+ static bool handles_scheme(const char *scheme);
+ static federatedx_io *construct(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+
+ static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
+ { return alloc_root(mem_root, size); }
+ static void operator delete(void *ptr, size_t size)
+ { TRASH(ptr, size); }
+
+ virtual int query(const char *buffer, uint length)=0;
+ virtual FEDERATEDX_IO_RESULT *store_result()=0;
+
+ virtual size_t max_query_size() const=0;
+
+ virtual my_ulonglong affected_rows() const=0;
+ virtual my_ulonglong last_insert_id() const=0;
+
+ virtual int error_code()=0;
+ virtual const char *error_str()=0;
+
+ virtual void reset()=0;
+ virtual int commit()=0;
+ virtual int rollback()=0;
+
+ virtual int savepoint_set(ulong sp)=0;
+ virtual ulong savepoint_release(ulong sp)=0;
+ virtual ulong savepoint_rollback(ulong sp)=0;
+ virtual void savepoint_restrict(ulong sp)=0;
+
+ virtual ulong last_savepoint() const=0;
+ virtual ulong actual_savepoint() const=0;
+ virtual bool is_autocommit() const=0;
+
+ virtual bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag) = 0;
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column)=0;
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const=0;
+};
+
+
+class federatedx_txn
+{
+ federatedx_io *txn_list;
+ ulong savepoint_level;
+ ulong savepoint_stmt;
+ ulong savepoint_next;
+
+ void release_scan();
+public:
+ federatedx_txn();
+ ~federatedx_txn();
+
+ bool has_connections() const { return txn_list != NULL; }
+ bool in_transaction() const { return savepoint_next != 0; }
+ int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io);
+ void release(federatedx_io **io);
+ void close(FEDERATEDX_SERVER *);
+
+ bool txn_begin();
+ int txn_commit();
+ int txn_rollback();
+
+ bool sp_acquire(ulong *save);
+ int sp_rollback(ulong *save);
+ int sp_release(ulong *save);
+
+ bool stmt_begin();
+ int stmt_commit();
+ int stmt_rollback();
+ void stmt_autocommit();
+};
+
+
+/*
+ Class definition for the storage engine
+*/
+class ha_federatedx: public handler
+{
+ friend int federatedx_db_init(void *p);
+
+ THR_LOCK_DATA lock; /* MySQL lock */
+ FEDERATEDX_SHARE *share; /* Shared lock info */
+ federatedx_txn *txn;
+ federatedx_io *io;
+ FEDERATEDX_IO_RESULT *stored_result;
+ uint fetch_num; // stores the fetch num
+ FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position()
+ int remote_error_number;
+ char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ bool ignore_duplicates, replace_duplicates;
+ bool insert_dup_update;
+ DYNAMIC_STRING bulk_insert;
+
+private:
+ /*
+ return 0 on success
+ return errorcode otherwise
+ */
+ uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row,
+ FEDERATEDX_IO_RESULT *result);
+ bool create_where_from_key(String *to, KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool records_in_range, bool eq_range);
+ int stash_remote_error();
+
+ federatedx_txn *get_txn(THD *thd, bool no_create= FALSE);
+
+ static int disconnect(handlerton *hton, MYSQL_THD thd);
+ static int savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int commit(handlerton *hton, MYSQL_THD thd, bool all);
+ static int rollback(handlerton *hton, MYSQL_THD thd, bool all);
+
+ bool append_stmt_insert(String *query);
+
+ int read_next(uchar *buf, FEDERATEDX_IO_RESULT *result);
+ int index_read_idx_with_result_set(uchar *buf, uint index,
+ const uchar *key,
+ uint key_len,
+ ha_rkey_function find_flag,
+ FEDERATEDX_IO_RESULT **result);
+ int real_query(const char *query, uint length);
+ int real_connect(FEDERATEDX_SHARE *my_share, uint create_flag);
+public:
+ ha_federatedx(handlerton *hton, TABLE_SHARE *table_arg);
+ ~ha_federatedx() {}
+ /* The name that will be used for display purposes */
+ const char *table_type() const { return "FEDERATED"; }
+ /*
+ The name of the index type that will be used for display
+ don't implement this method unless you really have indexes
+ */
+ // perhaps get index type
+ const char *index_type(uint inx) { return "REMOTE"; }
+ const char **bas_ext() const;
+ /*
+ This is a list of flags that says what the storage engine
+ implements. The current table flags are documented in
+ handler.h
+ */
+ ulonglong table_flags() const
+ {
+ /* fix server to be able to get remote server table flags */
+ return (HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED
+ | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS |
+ HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+ HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
+ HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
+ }
+ /*
+ This is a bitmap of flags that says how the storage engine
+ implements indexes. The current index flags are documented in
+ handler.h. If you do not implement indexes, just return zero
+ here.
+
+ part is the key part to check. First key part is 0
+ If all_parts it's set, MySQL want to know the flags for the combined
+ index up to and including 'part'.
+ */
+ /* fix server to be able to get remote server index flags */
+ ulong index_flags(uint inx, uint part, bool all_parts) const
+ {
+ return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
+ }
+ uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_parts() const { return MAX_REF_PARTS; }
+ uint max_supported_key_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
+ uint max_supported_key_part_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
+ /*
+ Called in test_quick_select to determine if indexes should be used.
+ Normally, we need to know number of blocks . For federatedx we need to
+ know number of blocks on remote side, and number of packets and blocks
+ on the network side (?)
+ Talk to Kostja about this - how to get the
+ number of rows * ...
+ disk scan time on other side (block size, size of the row) + network time ...
+ The reason for "records * 1000" is that such a large number forces
+ this to use indexes "
+ */
+ double scan_time()
+ {
+ DBUG_PRINT("info", ("records %lu", (ulong) stats.records));
+ return (double)(stats.records*1000);
+ }
+ /*
+ The next method will never be called if you do not implement indexes.
+ */
+ double read_time(uint index, uint ranges, ha_rows rows)
+ {
+ /*
+ Per Brian, this number is bugus, but this method must be implemented,
+ and at a later date, he intends to document this issue for handler code
+ */
+ return (double) rows / 20.0+1;
+ }
+
+ const key_map *keys_to_use_for_scanning() { return &key_map_full; }
+ /*
+ Everything below are methods that we implment in ha_federatedx.cc.
+
+ Most of these methods are not obligatory, skip them and
+ MySQL will treat them as not implemented
+ */
+ int open(const char *name, int mode, uint test_if_locked); // required
+ int close(void); // required
+
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert(bool abort);
+ int write_row(uchar *buf);
+ int update_row(const uchar *old_data, uchar *new_data);
+ int delete_row(const uchar *buf);
+ int index_init(uint keynr, bool sorted);
+ ha_rows estimate_rows_upper_bound();
+ int index_read(uchar *buf, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_idx(uchar *buf, uint idx, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_next(uchar *buf);
+ int index_end();
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
+ /*
+ unlike index_init(), rnd_init() can be called two times
+ without rnd_end() in between (it only makes sense if scan=1).
+ then the second call should prepare for the new table scan
+ (e.g if rnd_init allocates the cursor, second call should
+ position it to the start of the table, no need to deallocate
+ and allocate it again
+ */
+ int rnd_init(bool scan); //required
+ int rnd_end();
+ int rnd_next(uchar *buf); //required
+ int rnd_pos(uchar *buf, uchar *pos); //required
+ void position(const uchar *record); //required
+ int info(uint); //required
+ int extra(ha_extra_function operation);
+
+ void update_auto_increment(void);
+ int repair(THD* thd, HA_CHECK_OPT* check_opt);
+ int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+
+ int delete_all_rows(void);
+ int create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info); //required
+ ha_rows records_in_range(uint inx, key_range *start_key,
+ key_range *end_key);
+ uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type); //required
+ bool get_error_message(int error, String *buf);
+ int start_stmt(THD *thd, thr_lock_type lock_type);
+ int external_lock(THD *thd, int lock_type);
+ int reset(void);
+ int free_result(void);
+};
+
+extern const char ident_quote_char; // Character for quoting
+ // identifiers
+extern const char value_quote_char; // Character for quoting
+ // literals
+
+extern bool append_ident(String *string, const char *name, uint length,
+ const char quote_char);
+
+
+extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
=== added file 'storage/federatedx/plug.in'
--- a/storage/federatedx/plug.in 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/plug.in 2009-10-30 18:50:56 +0000
@@ -0,0 +1,5 @@
+MYSQL_STORAGE_ENGINE(federated,,[FederatedX Storage Engine],
+ [FederatedX Storage Engine], [max,max-no-ndb])
+MYSQL_PLUGIN_DYNAMIC(federated, [ha_federatedx.la])
+MYSQL_PLUGIN_STATIC(federated, [libfederatedx.a])
+MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federatedx.cc])
=== modified file 'storage/pbxt/src/cache_xt.cc'
--- a/storage/pbxt/src/cache_xt.cc 2009-08-17 11:12:36 +0000
+++ b/storage/pbxt/src/cache_xt.cc 2009-10-30 18:50:56 +0000
@@ -374,7 +374,7 @@ xtPublic void xt_ind_release_handle(XTIn
{
DcHandleSlotPtr hs;
XTIndBlockPtr block = NULL;
- u_int hash_idx = NULL;
+ u_int hash_idx = 0;
DcSegmentPtr seg = NULL;
XTIndBlockPtr xblock;
@@ -1379,7 +1379,7 @@ xtPublic xtBool xt_ind_fetch(XTOpenTable
ASSERT_NS(iref->ir_xlock == 2);
#endif
if (!(block = ind_cac_fetch(ot, ind, address, &seg, TRUE)))
- return NULL;
+ return 0;
branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);
if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) {
=== modified file 'storage/xtradb/include/buf0buf.ic'
--- a/storage/xtradb/include/buf0buf.ic 2009-06-25 01:43:25 +0000
+++ b/storage/xtradb/include/buf0buf.ic 2009-10-30 18:50:56 +0000
@@ -1056,7 +1056,7 @@ buf_page_release(
buf_block_t* block, /* in: buffer block */
ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
- mtr_t* mtr) /* in: mtr */
+ mtr_t* mtr __attribute__((unused))) /* in: mtr */
{
ut_ad(block);
1
0
[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2795)
by Michael Widenius 30 Oct '09
by Michael Widenius 30 Oct '09
30 Oct '09
#At lp:maria based on revid:psergey@askmonty.org-20091030105048-64ufz1ku62g882w5
2795 Michael Widenius 2009-10-30 [merge]
Automatic merge of federatedx code
added:
mysql-test/suite/funcs_1/r/is_tables_is_embedded.result
mysql-test/suite/funcs_1/t/is_tables_is_embedded.test
mysql-test/suite/maria/t/maria_showlog_error-master.opt
mysql-test/suite/pbxt/my.cnf
storage/federated/README
storage/federatedx/
storage/federatedx/AUTHORS
storage/federatedx/CMakeFiles.txt
storage/federatedx/ChangeLog
storage/federatedx/FAQ
storage/federatedx/Makefile.am
storage/federatedx/README
storage/federatedx/README.windows
storage/federatedx/TODO
storage/federatedx/federatedx_io.cc
storage/federatedx/federatedx_io_mysql.cc
storage/federatedx/federatedx_io_null.cc
storage/federatedx/federatedx_probes.h
storage/federatedx/federatedx_txn.cc
storage/federatedx/ha_federatedx.cc
storage/federatedx/ha_federatedx.h
storage/federatedx/plug.in
renamed:
storage/federated/plug.in => storage/federated/plug.in.disabled
modified:
.bzrignore
BUILD/SETUP.sh
client/mysql.cc
client/mysql_upgrade.c
client/mysqladmin.cc
client/mysqlslap.c
extra/yassl/src/crypto_wrapper.cpp
extra/yassl/taocrypt/src/aes.cpp
extra/yassl/taocrypt/src/blowfish.cpp
extra/yassl/taocrypt/src/misc.cpp
extra/yassl/taocrypt/src/twofish.cpp
include/mysys_err.h
libmysqld/Makefile.am
mysql-test/include/maria_empty_logs.inc
mysql-test/include/wait_for_status_var.inc
mysql-test/lib/mtr_cases.pm
mysql-test/mysql-test-run.pl
mysql-test/r/alter_table.result
mysql-test/r/func_misc.result
mysql-test/r/gis-rtree.result
mysql-test/r/innodb_xtradb_bug317074.result
mysql-test/r/merge.result
mysql-test/r/myisam_debug.result
mysql-test/suite/federated/disabled.def
mysql-test/suite/federated/federated.result
mysql-test/suite/federated/federated.test
mysql-test/suite/federated/federated_archive.result
mysql-test/suite/federated/federated_bug_13118.result
mysql-test/suite/federated/federated_bug_25714.result
mysql-test/suite/federated/federated_cleanup.inc
mysql-test/suite/federated/federated_innodb.result
mysql-test/suite/federated/federated_server.result
mysql-test/suite/federated/federated_server.test
mysql-test/suite/federated/federated_transactions.result
mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
mysql-test/suite/funcs_1/r/is_tables_myisam_embedded.result
mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result
mysql-test/suite/funcs_1/t/is_tables_is.test
mysql-test/suite/parts/inc/partition.pre
mysql-test/suite/parts/inc/partition_bigint.inc
mysql-test/suite/parts/inc/partition_binary.inc
mysql-test/suite/parts/inc/partition_bit.inc
mysql-test/suite/parts/inc/partition_char.inc
mysql-test/suite/parts/inc/partition_date.inc
mysql-test/suite/parts/inc/partition_datetime.inc
mysql-test/suite/parts/inc/partition_decimal.inc
mysql-test/suite/parts/inc/partition_double.inc
mysql-test/suite/parts/inc/partition_enum.inc
mysql-test/suite/parts/inc/partition_float.inc
mysql-test/suite/parts/inc/partition_int.inc
mysql-test/suite/parts/inc/partition_mediumint.inc
mysql-test/suite/parts/inc/partition_smallint.inc
mysql-test/suite/parts/inc/partition_time.inc
mysql-test/suite/parts/inc/partition_timestamp.inc
mysql-test/suite/parts/inc/partition_tinyint.inc
mysql-test/suite/parts/inc/partition_varbinary.inc
mysql-test/suite/parts/inc/partition_varchar.inc
mysql-test/suite/parts/inc/partition_year.inc
mysql-test/suite/parts/r/partition_char_innodb.result
mysql-test/suite/parts/r/partition_char_myisam.result
mysql-test/suite/parts/r/partition_datetime_innodb.result
mysql-test/suite/parts/r/partition_datetime_myisam.result
mysql-test/suite/parts/t/part_supported_sql_func_innodb.test
mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test
mysql-test/suite/parts/t/partition_alter4_myisam.test
mysql-test/suite/pbxt/t/count_distinct3.test
mysql-test/suite/pbxt/t/subselect.test
mysql-test/t/almost_full.test
mysql-test/t/alter_table.test
mysql-test/t/archive.test
mysql-test/t/bench_count_distinct.test
mysql-test/t/change_user.test
mysql-test/t/check.test
mysql-test/t/count_distinct2.test
mysql-test/t/count_distinct3.test
mysql-test/t/ctype_euckr.test
mysql-test/t/derived.test
mysql-test/t/events_time_zone.test
mysql-test/t/fulltext2.test
mysql-test/t/func_misc.test
mysql-test/t/gis-rtree.test
mysql-test/t/heap.test
mysql-test/t/innodb_xtradb_bug317074.test
mysql-test/t/insert.test
mysql-test/t/kill.test
mysql-test/t/merge.test
mysql-test/t/multi_update.test
mysql-test/t/multi_update2.test
mysql-test/t/myisam.test
mysql-test/t/myisam_debug.test
mysql-test/t/myisampack.test
mysql-test/t/order_by.test
mysql-test/t/order_fill_sortbuf.test
mysql-test/t/partition.test
mysql-test/t/partition_archive.test
mysql-test/t/select_found.test
mysql-test/t/sp-big.test
mysql-test/t/subselect.test
mysql-test/t/warnings.test
mysql-test/valgrind.supp
mysys/errors.c
mysys/my_copy.c
mysys/my_redel.c
mysys/safemalloc.c
scripts/make_binary_distribution.sh
sql/ha_partition.cc
sql/log.cc
sql/mysqld.cc
sql/rpl_rli.cc
sql/set_var.cc
sql/slave.cc
sql/sql_cache.cc
sql/sql_parse.cc
sql/sql_plugin.cc
sql/sql_select.cc
sql/sql_string.cc
sql/udf_example.c
storage/maria/ha_maria.cc
storage/maria/ma_extra.c
storage/maria/ma_locking.c
storage/maria/ma_recovery.c
storage/maria/unittest/ma_test_loghandler-t.c
storage/myisam/mi_extra.c
storage/pbxt/src/cache_xt.cc
storage/pbxt/src/strutil_xt.cc
storage/xtradb/include/buf0buf.ic
tests/mysql_client_test.c
unittest/mysys/base64-t.c
=== modified file '.bzrignore'
--- a/.bzrignore 2009-09-15 12:12:51 +0000
+++ b/.bzrignore 2009-10-30 18:51:46 +0000
@@ -1921,3 +1921,4 @@ sql/share/ukrainian
libmysqld/examples/mysqltest.cc
extra/libevent/event-config.h
libmysqld/opt_table_elimination.cc
+libmysqld/ha_federatedx.cc
=== modified file 'BUILD/SETUP.sh'
--- a/BUILD/SETUP.sh 2009-10-06 14:53:46 +0000
+++ b/BUILD/SETUP.sh 2009-10-29 00:04:56 +0000
@@ -146,6 +146,13 @@ then
debug_cflags="$debug_cflags $debug_extra_cflags"
fi
+static_link="--with-mysqld-ldflags=-all-static "
+static_link="$static_link --with-client-ldflags=-all-static"
+# we need local-infile in all binaries for rpl000001
+# if you need to disable local-infile in the client, write a build script
+# and unset local_infile_configs
+local_infile_configs="--enable-local-infile"
+
#
# Configuration options.
#
@@ -154,6 +161,8 @@ base_configs="$base_configs --with-extra
base_configs="$base_configs --enable-thread-safe-client "
base_configs="$base_configs --with-big-tables"
base_configs="$base_configs --with-plugin-maria --with-maria-tmp-tables --without-plugin-innodb_plugin"
+# Compile our client programs with static libraries to allow them to be moved
+base_configs="$base_configs --with-mysqld-ldflags=-static --with-client-ldflags=-static"
if test -d "$path/../cmd-line-utils/readline"
then
@@ -163,14 +172,6 @@ then
base_configs="$base_configs --with-libedit"
fi
-static_link="--with-mysqld-ldflags=-all-static "
-static_link="$static_link --with-client-ldflags=-all-static"
-# we need local-infile in all binaries for rpl000001
-# if you need to disable local-infile in the client, write a build script
-# and unset local_infile_configs
-local_infile_configs="--enable-local-infile"
-
-
max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache"
max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server --with-libevent"
=== modified file 'client/mysql.cc'
--- a/client/mysql.cc 2009-10-02 11:56:11 +0000
+++ b/client/mysql.cc 2009-10-26 11:35:42 +0000
@@ -3812,8 +3812,9 @@ static int
com_edit(String *buffer,char *line __attribute__((unused)))
{
char filename[FN_REFLEN],buff[160];
- int fd,tmp;
+ int fd,tmp,error;
const char *editor;
+ MY_STAT stat_arg;
if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY,
MYF(MY_WME))) < 0)
@@ -3829,9 +3830,13 @@ com_edit(String *buffer,char *line __att
!(editor = (char *)getenv("VISUAL")))
editor = "vi";
strxmov(buff,editor," ",filename,NullS);
- (void) system(buff);
+ if ((error= system(buff)))
+ {
+ char errmsg[100];
+ sprintf(errmsg, "Command '%.40s' failed", buff);
+ put_info(errmsg, INFO_ERROR, 0, NullS);
+ }
- MY_STAT stat_arg;
if (!my_stat(filename,&stat_arg,MYF(MY_WME)))
goto err;
if ((fd = my_open(filename,O_RDONLY, MYF(MY_WME))) < 0)
=== modified file 'client/mysql_upgrade.c'
--- a/client/mysql_upgrade.c 2009-07-16 12:43:17 +0000
+++ b/client/mysql_upgrade.c 2009-10-26 11:35:42 +0000
@@ -559,12 +559,11 @@ static int upgrade_already_done(void)
if (!(in= my_fopen(upgrade_info_file, O_RDONLY, MYF(0))))
return 0; /* Could not open file => not sure */
- /*
- Read from file, don't care if it fails since it
- will be detected by the strncmp
- */
bzero(buf, sizeof(buf));
- fgets(buf, sizeof(buf), in);
+ if (!fgets(buf, sizeof(buf), in))
+ {
+ /* Ignore, will be detected by strncmp() below */
+ }
my_fclose(in, MYF(0));
=== modified file 'client/mysqladmin.cc'
--- a/client/mysqladmin.cc 2009-09-07 20:50:10 +0000
+++ b/client/mysqladmin.cc 2009-10-30 18:50:56 +0000
@@ -1042,8 +1042,8 @@ static int drop_db(MYSQL *mysql, const c
puts("Any data stored in the database will be destroyed.\n");
printf("Do you really want to drop the '%s' database [y/N] ",db);
fflush(stdout);
- VOID(fgets(buf,sizeof(buf)-1,stdin));
- if ((*buf != 'y') && (*buf != 'Y'))
+ if (fgets(buf,sizeof(buf)-1,stdin) == 0 ||
+ ((*buf != 'y') && (*buf != 'Y')))
{
puts("\nOK, aborting database drop!");
return -1;
=== modified file 'client/mysqlslap.c'
--- a/client/mysqlslap.c 2009-09-25 08:56:53 +0000
+++ b/client/mysqlslap.c 2009-10-26 11:35:42 +0000
@@ -472,7 +472,7 @@ void concurrency_loop(MYSQL *mysql, uint
run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
if (pre_system)
- system(pre_system);
+ if (system(pre_system)) { /* Ignore for now */ }
/*
Pre statements are always run after all other logic so they can
@@ -487,7 +487,7 @@ void concurrency_loop(MYSQL *mysql, uint
run_statements(mysql, post_statements);
if (post_system)
- system(post_system);
+ if (system(post_system)) { /* Ignore for now */ }
/* We are finished with this run */
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
=== modified file 'extra/yassl/src/crypto_wrapper.cpp'
--- a/extra/yassl/src/crypto_wrapper.cpp 2007-03-23 12:43:09 +0000
+++ b/extra/yassl/src/crypto_wrapper.cpp 2009-10-26 11:35:42 +0000
@@ -953,7 +953,11 @@ x509* PemToDer(FILE* file, CertType type
info->set = true;
}
}
- fgets(line,sizeof(line), file); // get blank line
+ // get blank line
+ if (fgets(line,sizeof(line), file) == 0)
+ {
+ /* Impossible case */
+ }
begin = ftell(file);
}
=== modified file 'extra/yassl/taocrypt/src/aes.cpp'
--- a/extra/yassl/taocrypt/src/aes.cpp 2007-03-23 12:43:09 +0000
+++ b/extra/yassl/taocrypt/src/aes.cpp 2009-10-26 11:35:42 +0000
@@ -52,6 +52,7 @@ void AES::Process(byte* out, const byte*
in += BLOCK_SIZE;
}
else if (mode_ == CBC)
+ {
if (dir_ == ENCRYPTION)
while (blocks--) {
r_[0] ^= *(word32*)in;
@@ -78,6 +79,7 @@ void AES::Process(byte* out, const byte*
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
+ }
}
#endif // DO_AES_ASM
=== modified file 'extra/yassl/taocrypt/src/blowfish.cpp'
--- a/extra/yassl/taocrypt/src/blowfish.cpp 2007-01-29 15:54:40 +0000
+++ b/extra/yassl/taocrypt/src/blowfish.cpp 2009-10-26 11:35:42 +0000
@@ -54,6 +54,7 @@ void Blowfish::Process(byte* out, const
in += BLOCK_SIZE;
}
else if (mode_ == CBC)
+ {
if (dir_ == ENCRYPTION)
while (blocks--) {
r_[0] ^= *(word32*)in;
@@ -78,6 +79,7 @@ void Blowfish::Process(byte* out, const
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
+ }
}
#endif // DO_BLOWFISH_ASM
=== modified file 'extra/yassl/taocrypt/src/misc.cpp'
--- a/extra/yassl/taocrypt/src/misc.cpp 2007-04-11 20:07:24 +0000
+++ b/extra/yassl/taocrypt/src/misc.cpp 2009-10-26 11:35:42 +0000
@@ -166,6 +166,7 @@ word Crop(word value, unsigned int size)
#ifdef TAOCRYPT_X86ASM_AVAILABLE
+#ifdef NOT_USED
#ifndef _MSC_VER
static jmp_buf s_env;
static void SigIllHandler(int)
@@ -173,6 +174,7 @@ word Crop(word value, unsigned int size)
longjmp(s_env, 1);
}
#endif
+#endif
bool HaveCpuId()
=== modified file 'extra/yassl/taocrypt/src/twofish.cpp'
--- a/extra/yassl/taocrypt/src/twofish.cpp 2007-01-29 15:54:40 +0000
+++ b/extra/yassl/taocrypt/src/twofish.cpp 2009-10-30 18:50:56 +0000
@@ -55,6 +55,7 @@ void Twofish::Process(byte* out, const b
in += BLOCK_SIZE;
}
else if (mode_ == CBC)
+ {
if (dir_ == ENCRYPTION)
while (blocks--) {
r_[0] ^= *(word32*)in;
@@ -82,6 +83,7 @@ void Twofish::Process(byte* out, const b
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
+ }
}
#endif // DO_TWOFISH_ASM
=== modified file 'include/mysys_err.h'
--- a/include/mysys_err.h 2008-01-03 07:45:46 +0000
+++ b/include/mysys_err.h 2009-10-26 11:35:42 +0000
@@ -63,7 +63,8 @@ extern const char * NEAR globerrs[]; /*
#define EE_FILENOTFOUND 29
#define EE_FILE_NOT_CLOSED 30
#define EE_CANT_CHMOD 31
-#define EE_ERROR_LAST 31 /* Copy last error nr */
+#define EE_CANT_COPY_OWNERSHIP 32
+#define EE_ERROR_LAST 32 /* Copy last error nr */
/* Add error numbers before EE_ERROR_LAST and change it accordingly. */
/* exit codes for all MySQL programs */
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2009-09-15 10:46:35 +0000
+++ b/libmysqld/Makefile.am 2009-10-30 18:50:56 +0000
@@ -124,7 +124,7 @@ handler.o: handler.cc
# found to append fileslists that collected by configure
# to the sources list
-ha_federated.o:ha_federated.cc
+ha_federatedx.o:ha_federatedx.cc
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
ha_heap.o:ha_heap.cc
=== modified file 'mysql-test/include/maria_empty_logs.inc'
--- a/mysql-test/include/maria_empty_logs.inc 2009-02-19 09:01:25 +0000
+++ b/mysql-test/include/maria_empty_logs.inc 2009-10-13 12:47:17 +0000
@@ -1,6 +1,10 @@
# Maria help script.
# Cleans up all logs to give recovery a fresh start.
-
+#
+# Note that this script relies on the number of threads connect at start of
+# this script, so one should run this script with a freshly started server
+# for it to work.
+#
# API: set mel_keep_control_file=1 if want to keep control file;
# uses vardir, port and socket.
=== modified file 'mysql-test/include/wait_for_status_var.inc'
--- a/mysql-test/include/wait_for_status_var.inc 2009-04-03 21:33:13 +0000
+++ b/mysql-test/include/wait_for_status_var.inc 2009-10-13 12:47:17 +0000
@@ -51,11 +51,12 @@ if (`SELECT '$_status_var_comparsion' =
}
let $_show_status_value= query_get_value("SHOW $status_type STATUS LIKE '$status_var'", Value, 1);
+
while (`SELECT NOT('$_show_status_value' $_status_var_comparsion '$status_var_value')`)
{
if (!$_status_timeout_counter)
{
- --echo **** ERROR: failed while waiting for $status_type $status_var $_status_var_comparison $status_var_value ****
+ --echo **** ERROR: failed while waiting for '$status_type' '$status_var' $_status_var_comparsion '$status_var_value' ****
--echo Note: the following output may have changed since the failure was detected
--echo **** Showing STATUS, PROCESSLIST ****
eval SHOW $status_type STATUS LIKE '$status_var';
=== modified file 'mysql-test/lib/mtr_cases.pm'
--- a/mysql-test/lib/mtr_cases.pm 2009-10-07 22:59:07 +0000
+++ b/mysql-test/lib/mtr_cases.pm 2009-10-14 08:09:56 +0000
@@ -562,8 +562,12 @@ sub collect_one_suite($)
sub optimize_cases {
my ($cases)= @_;
+ my @new_cases= ();
+
foreach my $tinfo ( @$cases )
{
+ push @new_cases, $tinfo;
+
# Skip processing if already marked as skipped
next if $tinfo->{skip};
@@ -617,6 +621,13 @@ sub optimize_cases {
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}=
"Doesn't support --binlog-format='$test_binlog_format'";
+ # This test was added as a replication combination, but it is not
+ # actually ever possible to run it, as it is not made for this
+ # combination.
+ # So delete it from the list, rather than confuse the user with a
+ # message that this test is skipped (it is not really, just run
+ # with other combinations).
+ pop(@new_cases);
next;
}
}
@@ -685,6 +696,7 @@ sub optimize_cases {
}
}
}
+ @$cases= @new_cases;
}
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2009-10-07 22:57:43 +0000
+++ b/mysql-test/mysql-test-run.pl 2009-10-30 18:50:56 +0000
@@ -127,7 +127,6 @@ my $path_config_file; # The ge
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts";
-my $opt_suites;
our $opt_usage;
our $opt_list_options;
@@ -2402,7 +2401,7 @@ sub check_ndbcluster_support ($) {
if ( ! $mysqld_variables{'ndb-connectstring'} )
{
- mtr_report(" - skipping ndbcluster, mysqld not compiled with ndbcluster");
+ #mtr_report(" - skipping ndbcluster, mysqld not compiled with ndbcluster");
$opt_skip_ndbcluster= 2;
return;
}
@@ -2831,7 +2830,7 @@ sub mysql_install_db {
mtr_add_arg($args, "--basedir=%s", $install_basedir);
mtr_add_arg($args, "--datadir=%s", $install_datadir);
mtr_add_arg($args, "--loose-skip-innodb");
- mtr_add_arg($args, "--loose-skip-falcon");
+ mtr_add_arg($args, "--loose-skip-pbxt");
mtr_add_arg($args, "--loose-skip-ndbcluster");
mtr_add_arg($args, "--loose-skip-maria");
mtr_add_arg($args, "--disable-sync-frm");
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result 2009-06-07 10:05:19 +0000
+++ b/mysql-test/r/alter_table.result 2009-10-28 07:52:34 +0000
@@ -143,16 +143,6 @@ t1 1 n4 1 n4 A NULL NULL NULL YES BTREE
t1 1 n4 2 n1 A NULL NULL NULL BTREE disabled
t1 1 n4 3 n2 A NULL NULL NULL YES BTREE disabled
t1 1 n4 4 n3 A NULL NULL NULL YES BTREE disabled
-insert into t1 values(10,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(9,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(8,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(7,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(6,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(5,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(4,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(3,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(2,RAND()*1000,RAND()*1000,RAND());
-insert into t1 values(1,RAND()*1000,RAND()*1000,RAND());
alter table t1 enable keys;
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
@@ -183,106 +173,6 @@ i int(10) unsigned NO PRI NULL auto_incr
c char(10) YES NULL
drop table t1;
create table t1 (a int, b int);
-insert into t1 values(1,100), (2,100), (3, 100);
-insert into t1 values(1,99), (2,99), (3, 99);
-insert into t1 values(1,98), (2,98), (3, 98);
-insert into t1 values(1,97), (2,97), (3, 97);
-insert into t1 values(1,96), (2,96), (3, 96);
-insert into t1 values(1,95), (2,95), (3, 95);
-insert into t1 values(1,94), (2,94), (3, 94);
-insert into t1 values(1,93), (2,93), (3, 93);
-insert into t1 values(1,92), (2,92), (3, 92);
-insert into t1 values(1,91), (2,91), (3, 91);
-insert into t1 values(1,90), (2,90), (3, 90);
-insert into t1 values(1,89), (2,89), (3, 89);
-insert into t1 values(1,88), (2,88), (3, 88);
-insert into t1 values(1,87), (2,87), (3, 87);
-insert into t1 values(1,86), (2,86), (3, 86);
-insert into t1 values(1,85), (2,85), (3, 85);
-insert into t1 values(1,84), (2,84), (3, 84);
-insert into t1 values(1,83), (2,83), (3, 83);
-insert into t1 values(1,82), (2,82), (3, 82);
-insert into t1 values(1,81), (2,81), (3, 81);
-insert into t1 values(1,80), (2,80), (3, 80);
-insert into t1 values(1,79), (2,79), (3, 79);
-insert into t1 values(1,78), (2,78), (3, 78);
-insert into t1 values(1,77), (2,77), (3, 77);
-insert into t1 values(1,76), (2,76), (3, 76);
-insert into t1 values(1,75), (2,75), (3, 75);
-insert into t1 values(1,74), (2,74), (3, 74);
-insert into t1 values(1,73), (2,73), (3, 73);
-insert into t1 values(1,72), (2,72), (3, 72);
-insert into t1 values(1,71), (2,71), (3, 71);
-insert into t1 values(1,70), (2,70), (3, 70);
-insert into t1 values(1,69), (2,69), (3, 69);
-insert into t1 values(1,68), (2,68), (3, 68);
-insert into t1 values(1,67), (2,67), (3, 67);
-insert into t1 values(1,66), (2,66), (3, 66);
-insert into t1 values(1,65), (2,65), (3, 65);
-insert into t1 values(1,64), (2,64), (3, 64);
-insert into t1 values(1,63), (2,63), (3, 63);
-insert into t1 values(1,62), (2,62), (3, 62);
-insert into t1 values(1,61), (2,61), (3, 61);
-insert into t1 values(1,60), (2,60), (3, 60);
-insert into t1 values(1,59), (2,59), (3, 59);
-insert into t1 values(1,58), (2,58), (3, 58);
-insert into t1 values(1,57), (2,57), (3, 57);
-insert into t1 values(1,56), (2,56), (3, 56);
-insert into t1 values(1,55), (2,55), (3, 55);
-insert into t1 values(1,54), (2,54), (3, 54);
-insert into t1 values(1,53), (2,53), (3, 53);
-insert into t1 values(1,52), (2,52), (3, 52);
-insert into t1 values(1,51), (2,51), (3, 51);
-insert into t1 values(1,50), (2,50), (3, 50);
-insert into t1 values(1,49), (2,49), (3, 49);
-insert into t1 values(1,48), (2,48), (3, 48);
-insert into t1 values(1,47), (2,47), (3, 47);
-insert into t1 values(1,46), (2,46), (3, 46);
-insert into t1 values(1,45), (2,45), (3, 45);
-insert into t1 values(1,44), (2,44), (3, 44);
-insert into t1 values(1,43), (2,43), (3, 43);
-insert into t1 values(1,42), (2,42), (3, 42);
-insert into t1 values(1,41), (2,41), (3, 41);
-insert into t1 values(1,40), (2,40), (3, 40);
-insert into t1 values(1,39), (2,39), (3, 39);
-insert into t1 values(1,38), (2,38), (3, 38);
-insert into t1 values(1,37), (2,37), (3, 37);
-insert into t1 values(1,36), (2,36), (3, 36);
-insert into t1 values(1,35), (2,35), (3, 35);
-insert into t1 values(1,34), (2,34), (3, 34);
-insert into t1 values(1,33), (2,33), (3, 33);
-insert into t1 values(1,32), (2,32), (3, 32);
-insert into t1 values(1,31), (2,31), (3, 31);
-insert into t1 values(1,30), (2,30), (3, 30);
-insert into t1 values(1,29), (2,29), (3, 29);
-insert into t1 values(1,28), (2,28), (3, 28);
-insert into t1 values(1,27), (2,27), (3, 27);
-insert into t1 values(1,26), (2,26), (3, 26);
-insert into t1 values(1,25), (2,25), (3, 25);
-insert into t1 values(1,24), (2,24), (3, 24);
-insert into t1 values(1,23), (2,23), (3, 23);
-insert into t1 values(1,22), (2,22), (3, 22);
-insert into t1 values(1,21), (2,21), (3, 21);
-insert into t1 values(1,20), (2,20), (3, 20);
-insert into t1 values(1,19), (2,19), (3, 19);
-insert into t1 values(1,18), (2,18), (3, 18);
-insert into t1 values(1,17), (2,17), (3, 17);
-insert into t1 values(1,16), (2,16), (3, 16);
-insert into t1 values(1,15), (2,15), (3, 15);
-insert into t1 values(1,14), (2,14), (3, 14);
-insert into t1 values(1,13), (2,13), (3, 13);
-insert into t1 values(1,12), (2,12), (3, 12);
-insert into t1 values(1,11), (2,11), (3, 11);
-insert into t1 values(1,10), (2,10), (3, 10);
-insert into t1 values(1,9), (2,9), (3, 9);
-insert into t1 values(1,8), (2,8), (3, 8);
-insert into t1 values(1,7), (2,7), (3, 7);
-insert into t1 values(1,6), (2,6), (3, 6);
-insert into t1 values(1,5), (2,5), (3, 5);
-insert into t1 values(1,4), (2,4), (3, 4);
-insert into t1 values(1,3), (2,3), (3, 3);
-insert into t1 values(1,2), (2,2), (3, 2);
-insert into t1 values(1,1), (2,1), (3, 1);
alter table t1 add unique (a,b), add key (b);
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
=== modified file 'mysql-test/r/func_misc.result'
--- a/mysql-test/r/func_misc.result 2009-06-11 16:21:32 +0000
+++ b/mysql-test/r/func_misc.result 2009-10-28 07:52:34 +0000
@@ -116,10 +116,6 @@ CREATE TEMPORARY TABLE t_history (attemp
start_ts DATETIME, end_ts DATETIME,
start_cached INTEGER, end_cached INTEGER);
CREATE TABLE t1 (f1 BIGINT);
-INSERT INTO t1 VALUES (1);
-INSERT INTO t1 VALUES (1);
-INSERT INTO t1 VALUES (1);
-INSERT INTO t1 VALUES (1);
INSERT INTO t_history
SET attempt = 4 - 4 + 1, start_ts = NOW(),
start_cached = 0;
=== modified file 'mysql-test/r/gis-rtree.result'
--- a/mysql-test/r/gis-rtree.result 2009-07-10 23:12:13 +0000
+++ b/mysql-test/r/gis-rtree.result 2009-10-28 07:52:34 +0000
@@ -12,156 +12,6 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(147 147, 153 153)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(146 146, 154 154)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(145 145, 155 155)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(144 144, 156 156)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(143 143, 157 157)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(142 142, 158 158)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(141 141, 159 159)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(140 140, 160 160)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(139 139, 161 161)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(138 138, 162 162)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(137 137, 163 163)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(136 136, 164 164)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(135 135, 165 165)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(134 134, 166 166)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(133 133, 167 167)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(132 132, 168 168)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(131 131, 169 169)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(130 130, 170 170)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(129 129, 171 171)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(128 128, 172 172)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(127 127, 173 173)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(126 126, 174 174)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(125 125, 175 175)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(124 124, 176 176)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(123 123, 177 177)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(122 122, 178 178)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(121 121, 179 179)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(120 120, 180 180)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(119 119, 181 181)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(118 118, 182 182)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(117 117, 183 183)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(116 116, 184 184)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(115 115, 185 185)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(114 114, 186 186)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(113 113, 187 187)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(112 112, 188 188)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(111 111, 189 189)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(110 110, 190 190)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(109 109, 191 191)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(108 108, 192 192)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(107 107, 193 193)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(106 106, 194 194)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(105 105, 195 195)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(104 104, 196 196)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(103 103, 197 197)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(102 102, 198 198)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(101 101, 199 199)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(100 100, 200 200)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(99 99, 201 201)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(98 98, 202 202)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(97 97, 203 203)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(96 96, 204 204)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(95 95, 205 205)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(94 94, 206 206)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(93 93, 207 207)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(92 92, 208 208)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(91 91, 209 209)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(90 90, 210 210)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(89 89, 211 211)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(88 88, 212 212)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(87 87, 213 213)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(86 86, 214 214)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(85 85, 215 215)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(84 84, 216 216)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(83 83, 217 217)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(82 82, 218 218)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(81 81, 219 219)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(80 80, 220 220)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(79 79, 221 221)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(78 78, 222 222)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(77 77, 223 223)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(76 76, 224 224)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(75 75, 225 225)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(74 74, 226 226)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(73 73, 227 227)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(72 72, 228 228)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(71 71, 229 229)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(70 70, 230 230)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(69 69, 231 231)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(68 68, 232 232)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(67 67, 233 233)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(66 66, 234 234)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(65 65, 235 235)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(64 64, 236 236)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(63 63, 237 237)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(62 62, 238 238)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(61 61, 239 239)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(60 60, 240 240)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(59 59, 241 241)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(58 58, 242 242)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(57 57, 243 243)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(56 56, 244 244)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(55 55, 245 245)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(54 54, 246 246)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(53 53, 247 247)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(52 52, 248 248)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(51 51, 249 249)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(50 50, 250 250)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(49 49, 251 251)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(48 48, 252 252)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(47 47, 253 253)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(46 46, 254 254)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(45 45, 255 255)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(44 44, 256 256)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(43 43, 257 257)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(42 42, 258 258)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(41 41, 259 259)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(40 40, 260 260)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(39 39, 261 261)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(38 38, 262 262)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(37 37, 263 263)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(36 36, 264 264)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(35 35, 265 265)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(34 34, 266 266)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(33 33, 267 267)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(32 32, 268 268)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(31 31, 269 269)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(30 30, 270 270)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(29 29, 271 271)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(28 28, 272 272)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(27 27, 273 273)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(26 26, 274 274)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(25 25, 275 275)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(24 24, 276 276)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(23 23, 277 277)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(22 22, 278 278)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(21 21, 279 279)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(20 20, 280 280)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(19 19, 281 281)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(18 18, 282 282)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(17 17, 283 283)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(16 16, 284 284)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(15 15, 285 285)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(14 14, 286 286)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(13 13, 287 287)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(12 12, 288 288)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(11 11, 289 289)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(10 10, 290 290)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(9 9, 291 291)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(8 8, 292 292)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(7 7, 293 293)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(6 6, 294 294)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(5 5, 295 295)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(4 4, 296 296)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(3 3, 297 297)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(2 2, 298 298)'));
-INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 1, 299 299)'));
SELECT count(*) FROM t1;
count(*)
150
@@ -186,106 +36,6 @@ CREATE TABLE t2 (
fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
g GEOMETRY NOT NULL
) ENGINE=MyISAM;
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10)));
-INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10)));
ALTER TABLE t2 ADD SPATIAL KEY(g);
SHOW CREATE TABLE t2;
Table Create Table
@@ -309,404 +59,204 @@ fid AsText(g)
56 LINESTRING(41 41,50 50)
45 LINESTRING(51 51,60 60)
55 LINESTRING(41 51,50 60)
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10))));
-SELECT count(*) FROM t2;
count(*)
100
DROP TABLE t2;
=== modified file 'mysql-test/r/innodb_xtradb_bug317074.result'
--- a/mysql-test/r/innodb_xtradb_bug317074.result 2009-09-08 16:04:58 +0000
+++ b/mysql-test/r/innodb_xtradb_bug317074.result 2009-10-28 07:52:34 +0000
@@ -3,3 +3,30 @@ SET @old_innodb_file_per_table=@@innodb_
SET @old_innodb_file_format_check=@@innodb_file_format_check;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;
+DROP TABLE IF EXISTS `test1`;
+CREATE TABLE IF NOT EXISTS `test1` (
+`a` int primary key auto_increment,
+`b` int default 0,
+`c` char(100) default 'testtest'
+) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
+set autocommit=0;
+CREATE PROCEDURE insert_many(p1 int)
+BEGIN
+SET @x = 0;
+SET @y = 0;
+REPEAT
+insert into test1 set b=1;
+SET @x = @x + 1;
+SET @y = @y + 1;
+IF @y >= 1000 THEN
+commit;
+SET @y = 0;
+END IF;
+UNTIL @x >= p1 END REPEAT;
+END|
+DROP PROCEDURE insert_many;
+ALTER TABLE test1 ENGINE=MyISAM;
+DROP TABLE test1;
+SET GLOBAL innodb_file_format=@old_innodb_file_format;
+SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table;
+SET GLOBAL innodb_file_format_check=@old_innodb_file_format_check;
=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result 2009-09-07 20:50:10 +0000
+++ b/mysql-test/r/merge.result 2009-10-28 07:52:34 +0000
@@ -1846,56 +1846,6 @@ c1
DROP TABLE t1, t2, t3;
CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER);
SET @rnd_max= 2147483647;
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
set @@read_buffer_size=2*1024*1024;
CREATE TABLE t2 SELECT * FROM t1;
INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
=== modified file 'mysql-test/r/myisam_debug.result'
--- a/mysql-test/r/myisam_debug.result 2009-04-30 11:03:44 +0000
+++ b/mysql-test/r/myisam_debug.result 2009-10-28 07:52:34 +0000
@@ -12,16 +12,6 @@ CREATE TABLE `t2` (
KEY (id1), KEY(id)
) ENGINE=MyISAM;
INSERT INTO t2 (id) VALUES (123);
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
-INSERT INTO t2 (id) SELECT id FROM t2;
# Switch to insert Connection
SET SESSION debug='+d,wait_in_enable_indexes';
# Send insert data
=== modified file 'mysql-test/suite/federated/disabled.def'
--- a/mysql-test/suite/federated/disabled.def 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/federated/disabled.def 2009-10-30 18:50:56 +0000
@@ -9,4 +9,5 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-federated_transactions : Bug#29523 Transactions do not work
+federated_server : needs fixup
+
=== modified file 'mysql-test/suite/federated/federated.result'
--- a/mysql-test/suite/federated/federated.result 2009-03-19 08:49:51 +0000
+++ b/mysql-test/suite/federated/federated.result 2009-10-30 18:50:56 +0000
@@ -47,9 +47,10 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
-SELECT * FROM federated.t1;
-ERROR HY000: The foreign data source you are trying to reference does not exist. Data source error: error: 1146 'Table 'federated.t3' doesn't exist'
-DROP TABLE federated.t1;
+ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'root' hostname: '127.0.0.1'
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -59,9 +60,10 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
-SELECT * FROM federated.t1;
-ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES)
-DROP TABLE federated.t1;
+ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'user' hostname: '127.0.0.1'
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -1944,15 +1946,7 @@ Bug#18287 create federated table always
Test that self-references work
-create table federated.t1 (a int primary key);
-create table federated.t2 (a int primary key)
-ENGINE=FEDERATED
-connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
-insert into federated.t1 (a) values (1);
-select * from federated.t2;
-a
-1
-drop table federated.t1, federated.t2;
+fix LOCK_open before reenabling test for Bug#18287
CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8;
CREATE TABLE federated.t1 (a INT PRIMARY KEY)
ENGINE=FEDERATED
@@ -1960,13 +1954,11 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE
DEFAULT CHARSET=utf8;
SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED";
transactions
-NO
+YES
INSERT INTO federated.t1 VALUES (1);
SET autocommit=0;
INSERT INTO federated.t1 VALUES (2);
ROLLBACK;
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
SET autocommit=1;
SELECT * FROM federated.t1;
a
@@ -2157,6 +2149,6 @@ End of 5.1 tests
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated.test'
--- a/mysql-test/suite/federated/federated.test 2009-03-19 08:49:51 +0000
+++ b/mysql-test/suite/federated/federated.test 2009-10-30 18:50:56 +0000
@@ -57,6 +57,7 @@ CREATE TABLE federated.t1 (
# test non-existant table
--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_CANT_CREATE_FEDERATED_TABLE
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -66,12 +67,11 @@ eval CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3';
---error ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
-SELECT * FROM federated.t1;
-DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
# test bad user/password
--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_CANT_CREATE_FEDERATED_TABLE
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`group` int NOT NULL default 0,
@@ -81,9 +81,7 @@ eval CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1';
---error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
-SELECT * FROM federated.t1;
-DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
# # correct connection, same named tables
--replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -1806,6 +1804,8 @@ drop table federated.t1;
--echo
--echo Test that self-references work
--echo
+--echo fix LOCK_open before reenabling test for Bug#18287
+--disable_parsing
connection slave;
create table federated.t1 (a int primary key);
--replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -1815,7 +1815,7 @@ eval create table federated.t2 (a int pr
insert into federated.t1 (a) values (1);
select * from federated.t2;
drop table federated.t1, federated.t2;
-
+--enable_parsing
#
# BUG#29875 Disable support for transactions
#
=== modified file 'mysql-test/suite/federated/federated_archive.result'
--- a/mysql-test/suite/federated/federated_archive.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_archive.result 2009-10-30 18:50:56 +0000
@@ -34,6 +34,6 @@ id name
DROP TABLE federated.t1;
DROP TABLE federated.archive_table;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_bug_13118.result'
--- a/mysql-test/suite/federated/federated_bug_13118.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_bug_13118.result 2009-10-30 18:50:56 +0000
@@ -25,6 +25,6 @@ foo bar
DROP TABLE federated.t1;
DROP TABLE federated.bug_13118_table;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_bug_25714.result'
--- a/mysql-test/suite/federated/federated_bug_25714.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_bug_25714.result 2009-10-30 18:50:56 +0000
@@ -48,6 +48,6 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MAS
DROP TABLE federated.t1;
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_cleanup.inc'
--- a/mysql-test/suite/federated/federated_cleanup.inc 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_cleanup.inc 2009-10-30 18:50:56 +0000
@@ -1,9 +1,9 @@
connection master;
--disable_warnings
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
connection slave;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
--enable_warnings
=== modified file 'mysql-test/suite/federated/federated_innodb.result'
--- a/mysql-test/suite/federated/federated_innodb.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_innodb.result 2009-10-30 18:50:56 +0000
@@ -20,6 +20,6 @@ a b
drop table federated.t1;
drop table federated.t1;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
-DROP DATABASE federated;
+DROP DATABASE IF EXISTS federated;
=== modified file 'mysql-test/suite/federated/federated_server.result'
--- a/mysql-test/suite/federated/federated_server.result 2009-02-02 11:36:03 +0000
+++ b/mysql-test/suite/federated/federated_server.result 2009-10-30 18:50:56 +0000
@@ -178,8 +178,8 @@ INSERT INTO db_bogus.t1 VALUES ('2','thi
create server 's1' foreign data wrapper 'mysql' options
(HOST '127.0.0.1',
DATABASE 'db_legitimate',
-USER 'root',
-PASSWORD '',
+USER 'test_fed',
+PASSWORD 'foo',
PORT SLAVE_PORT,
SOCKET '',
OWNER 'root');
=== modified file 'mysql-test/suite/federated/federated_server.test'
--- a/mysql-test/suite/federated/federated_server.test 2009-06-05 15:35:22 +0000
+++ b/mysql-test/suite/federated/federated_server.test 2009-10-30 18:50:56 +0000
@@ -3,6 +3,7 @@
# Slow test, don't run during staging part
-- source include/not_staging.inc
+-- source include/big_test.inc
-- source federated.inc
connection slave;
@@ -182,13 +183,17 @@ CREATE TABLE db_bogus.t1 (
;
INSERT INTO db_bogus.t1 VALUES ('2','this is bogus');
+connection slave;
+create user test_fed@localhost identified by 'foo';
+grant all on db_legitimate.* to test_fed@localhost;
+
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create server 's1' foreign data wrapper 'mysql' options
(HOST '127.0.0.1',
DATABASE 'db_legitimate',
- USER 'root',
- PASSWORD '',
+ USER 'test_fed',
+ PASSWORD 'foo',
PORT $SLAVE_MYPORT,
SOCKET '',
OWNER 'root');
=== modified file 'mysql-test/suite/federated/federated_transactions.result'
--- a/mysql-test/suite/federated/federated_transactions.result 2007-12-12 17:19:24 +0000
+++ b/mysql-test/suite/federated/federated_transactions.result 2009-10-30 18:50:56 +0000
@@ -1,13 +1,4 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-stop slave;
-DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
-DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
DROP TABLE IF EXISTS federated.t1;
Warnings:
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_is_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result 2009-05-19 16:43:50 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result 2009-10-26 11:35:42 +0000
@@ -113,6 +113,96 @@ NULL information_schema GLOBAL_STATUS VA
NULL information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
NULL information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
+NULL information_schema INNODB_BUFFER_POOL_PAGES fix_count 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES flush_type 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES lru_position 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES page_no 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES page_type 1 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
+NULL information_schema INNODB_BUFFER_POOL_PAGES space_id 2 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB compressed 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB fix_count 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB flush_type 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB lru_position 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB next_page_no 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB page_no 2 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB part_len 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB space_id 1 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX accessed 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX data_size 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX dirty 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX fix_count 14 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX flush_type 15 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX hashed 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX index_name 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX lru_position 13 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX modified 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX n_recs 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX old 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX page_no 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX schema_name 1 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX space_id 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX table_name 2 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
+NULL information_schema INNODB_CMP compress_ops 2 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP compress_ops_ok 3 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP compress_time 4 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP page_size 1 0 NO int NULL NULL 10 0 NULL NULL int(5)
+NULL information_schema INNODB_CMP uncompress_ops 5 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP uncompress_time 6 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM pages_free 3 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM pages_used 2 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM page_size 1 0 NO int NULL NULL 10 0 NULL NULL int(5)
+NULL information_schema INNODB_CMPMEM relocation_ops 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21)
+NULL information_schema INNODB_CMPMEM relocation_time 5 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM_RESET pages_free 3 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM_RESET pages_used 2 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM_RESET page_size 1 0 NO int NULL NULL 10 0 NULL NULL int(5)
+NULL information_schema INNODB_CMPMEM_RESET relocation_ops 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21)
+NULL information_schema INNODB_CMPMEM_RESET relocation_time 5 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET compress_ops 2 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET compress_ops_ok 3 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET compress_time 4 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET page_size 1 0 NO int NULL NULL 10 0 NULL NULL int(5)
+NULL information_schema INNODB_CMP_RESET uncompress_ops 5 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET uncompress_time 6 0 NO int NULL NULL 10 0 NULL NULL int(11)
+NULL information_schema INNODB_INDEX_STATS fields 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_INDEX_STATS index_name 2 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
+NULL information_schema INNODB_INDEX_STATS index_size 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_INDEX_STATS leaf_pages 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_INDEX_STATS row_per_keys 4 NO varchar 256 768 NULL NULL utf8 utf8_general_ci varchar(256)
+NULL information_schema INNODB_INDEX_STATS table_name 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
+NULL information_schema INNODB_LOCKS lock_data 10 NULL YES varchar 8192 24576 NULL NULL utf8 utf8_general_ci varchar(8192)
+NULL information_schema INNODB_LOCKS lock_id 1 NO varchar 81 243 NULL NULL utf8 utf8_general_ci varchar(81)
+NULL information_schema INNODB_LOCKS lock_index 6 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
+NULL information_schema INNODB_LOCKS lock_mode 3 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
+NULL information_schema INNODB_LOCKS lock_page 8 NULL YES bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_LOCKS lock_rec 9 NULL YES bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_LOCKS lock_space 7 NULL YES bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_LOCKS lock_table 5 NO varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
+NULL information_schema INNODB_LOCKS lock_trx_id 2 NO varchar 18 54 NULL NULL utf8 utf8_general_ci varchar(18)
+NULL information_schema INNODB_LOCKS lock_type 4 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
+NULL information_schema INNODB_LOCK_WAITS blocking_lock_id 4 NO varchar 81 243 NULL NULL utf8 utf8_general_ci varchar(81)
+NULL information_schema INNODB_LOCK_WAITS blocking_trx_id 3 NO varchar 18 54 NULL NULL utf8 utf8_general_ci varchar(18)
+NULL information_schema INNODB_LOCK_WAITS requested_lock_id 2 NO varchar 81 243 NULL NULL utf8 utf8_general_ci varchar(81)
+NULL information_schema INNODB_LOCK_WAITS requesting_trx_id 1 NO varchar 18 54 NULL NULL utf8 utf8_general_ci varchar(18)
+NULL information_schema INNODB_RSEG curr_size 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG max_size 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG page_no 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG rseg_id 1 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG space_id 2 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG zip_size 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS clust_size 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS modified 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS other_size 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS rows 2 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS table_name 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
+NULL information_schema INNODB_TRX trx_id 1 NO varchar 18 54 NULL NULL utf8 utf8_general_ci varchar(18)
+NULL information_schema INNODB_TRX trx_mysql_thread_id 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TRX trx_query 8 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
+NULL information_schema INNODB_TRX trx_requested_lock_id 4 NULL YES varchar 81 243 NULL NULL utf8 utf8_general_ci varchar(81)
+NULL information_schema INNODB_TRX trx_started 3 0000-00-00 00:00:00 NO datetime NULL NULL NULL NULL NULL NULL datetime
+NULL information_schema INNODB_TRX trx_state 2 NO varchar 13 39 NULL NULL utf8 utf8_general_ci varchar(13)
+NULL information_schema INNODB_TRX trx_wait_started 5 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime
+NULL information_schema INNODB_TRX trx_weight 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
NULL information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512)
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
@@ -167,6 +257,7 @@ NULL information_schema PROCESSLIST ID 1
NULL information_schema PROCESSLIST INFO 8 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext
NULL information_schema PROCESSLIST STATE 7 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema PROCESSLIST TIME 6 0 NO int NULL NULL 10 0 NULL NULL int(7)
+NULL information_schema PROCESSLIST TIME_MS 9 0.000 NO decimal NULL NULL 22 3 NULL NULL decimal(22,3)
NULL information_schema PROCESSLIST USER 2 NO varchar 16 48 NULL NULL utf8 utf8_general_ci varchar(16)
NULL information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG 1 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512)
NULL information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
@@ -300,6 +391,10 @@ NULL information_schema VIEWS TABLE_CATA
NULL information_schema VIEWS TABLE_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema VIEWS TABLE_SCHEMA 2 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema VIEWS VIEW_DEFINITION 4 NULL NO longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext
+NULL information_schema XTRADB_ENHANCEMENTS comment 3 NO varchar 100 300 NULL NULL utf8 utf8_general_ci varchar(100)
+NULL information_schema XTRADB_ENHANCEMENTS description 2 NO varchar 255 765 NULL NULL utf8 utf8_general_ci varchar(255)
+NULL information_schema XTRADB_ENHANCEMENTS link 4 NO varchar 255 765 NULL NULL utf8 utf8_general_ci varchar(255)
+NULL information_schema XTRADB_ENHANCEMENTS name 1 NO varchar 255 765 NULL NULL utf8 utf8_general_ci varchar(255)
##########################################################################
# Show the quotient of CHARACTER_OCTET_LENGTH and CHARACTER_MAXIMUM_LENGTH
##########################################################################
@@ -340,6 +435,7 @@ ORDER BY CHARACTER_SET_NAME, COLLATION_N
COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME
NULL bigint NULL NULL
NULL datetime NULL NULL
+NULL decimal NULL NULL
NULL int NULL NULL
--> CHAR(0) is allowed (see manual), and here both CHARACHTER_* values
--> are 0, which is intended behavior, and the result of 0 / 0 IS NULL
@@ -468,6 +564,96 @@ NULL information_schema FILES CHECKSUM b
3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema INNODB_BUFFER_POOL_PAGES page_type varchar 64 192 utf8 utf8_general_ci varchar(64)
+NULL information_schema INNODB_BUFFER_POOL_PAGES space_id bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES page_no bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES lru_position bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES fix_count bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES flush_type bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB space_id bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB page_no bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB compressed bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB part_len bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB next_page_no bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB lru_position bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB fix_count bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_BLOB flush_type bigint NULL NULL NULL NULL bigint(21) unsigned
+3.0000 information_schema INNODB_BUFFER_POOL_PAGES_INDEX schema_name varchar 64 192 utf8 utf8_general_ci varchar(64)
+3.0000 information_schema INNODB_BUFFER_POOL_PAGES_INDEX table_name varchar 64 192 utf8 utf8_general_ci varchar(64)
+3.0000 information_schema INNODB_BUFFER_POOL_PAGES_INDEX index_name varchar 64 192 utf8 utf8_general_ci varchar(64)
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX space_id bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX page_no bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX n_recs bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX data_size bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX hashed bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX accessed bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX modified bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX dirty bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX old bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX lru_position bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX fix_count bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_BUFFER_POOL_PAGES_INDEX flush_type bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_CMP page_size int NULL NULL NULL NULL int(5)
+NULL information_schema INNODB_CMP compress_ops int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP compress_ops_ok int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP compress_time int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP uncompress_ops int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP uncompress_time int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM page_size int NULL NULL NULL NULL int(5)
+NULL information_schema INNODB_CMPMEM pages_used int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM pages_free int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM relocation_ops bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema INNODB_CMPMEM relocation_time int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM_RESET page_size int NULL NULL NULL NULL int(5)
+NULL information_schema INNODB_CMPMEM_RESET pages_used int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM_RESET pages_free int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMPMEM_RESET relocation_ops bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema INNODB_CMPMEM_RESET relocation_time int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET page_size int NULL NULL NULL NULL int(5)
+NULL information_schema INNODB_CMP_RESET compress_ops int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET compress_ops_ok int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET compress_time int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET uncompress_ops int NULL NULL NULL NULL int(11)
+NULL information_schema INNODB_CMP_RESET uncompress_time int NULL NULL NULL NULL int(11)
+3.0000 information_schema INNODB_INDEX_STATS table_name varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema INNODB_INDEX_STATS index_name varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema INNODB_INDEX_STATS fields bigint NULL NULL NULL NULL bigint(21) unsigned
+3.0000 information_schema INNODB_INDEX_STATS row_per_keys varchar 256 768 utf8 utf8_general_ci varchar(256)
+NULL information_schema INNODB_INDEX_STATS index_size bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_INDEX_STATS leaf_pages bigint NULL NULL NULL NULL bigint(21) unsigned
+3.0000 information_schema INNODB_LOCKS lock_id varchar 81 243 utf8 utf8_general_ci varchar(81)
+3.0000 information_schema INNODB_LOCKS lock_trx_id varchar 18 54 utf8 utf8_general_ci varchar(18)
+3.0000 information_schema INNODB_LOCKS lock_mode varchar 32 96 utf8 utf8_general_ci varchar(32)
+3.0000 information_schema INNODB_LOCKS lock_type varchar 32 96 utf8 utf8_general_ci varchar(32)
+3.0000 information_schema INNODB_LOCKS lock_table varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema INNODB_LOCKS lock_index varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+NULL information_schema INNODB_LOCKS lock_space bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_LOCKS lock_page bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_LOCKS lock_rec bigint NULL NULL NULL NULL bigint(21) unsigned
+3.0000 information_schema INNODB_LOCKS lock_data varchar 8192 24576 utf8 utf8_general_ci varchar(8192)
+3.0000 information_schema INNODB_LOCK_WAITS requesting_trx_id varchar 18 54 utf8 utf8_general_ci varchar(18)
+3.0000 information_schema INNODB_LOCK_WAITS requested_lock_id varchar 81 243 utf8 utf8_general_ci varchar(81)
+3.0000 information_schema INNODB_LOCK_WAITS blocking_trx_id varchar 18 54 utf8 utf8_general_ci varchar(18)
+3.0000 information_schema INNODB_LOCK_WAITS blocking_lock_id varchar 81 243 utf8 utf8_general_ci varchar(81)
+NULL information_schema INNODB_RSEG rseg_id bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG space_id bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG zip_size bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG page_no bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG max_size bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_RSEG curr_size bigint NULL NULL NULL NULL bigint(21) unsigned
+3.0000 information_schema INNODB_TABLE_STATS table_name varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema INNODB_TABLE_STATS rows bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS clust_size bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS other_size bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema INNODB_TABLE_STATS modified bigint NULL NULL NULL NULL bigint(21) unsigned
+3.0000 information_schema INNODB_TRX trx_id varchar 18 54 utf8 utf8_general_ci varchar(18)
+3.0000 information_schema INNODB_TRX trx_state varchar 13 39 utf8 utf8_general_ci varchar(13)
+NULL information_schema INNODB_TRX trx_started datetime NULL NULL NULL NULL datetime
+3.0000 information_schema INNODB_TRX trx_requested_lock_id varchar 81 243 utf8 utf8_general_ci varchar(81)
+NULL information_schema INNODB_TRX trx_wait_started datetime NULL NULL NULL NULL datetime
+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_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)
@@ -523,6 +709,7 @@ NULL information_schema PROCESSLIST ID b
NULL information_schema PROCESSLIST TIME int NULL NULL NULL NULL int(7)
3.0000 information_schema PROCESSLIST STATE varchar 64 192 utf8 utf8_general_ci varchar(64)
1.0000 information_schema PROCESSLIST INFO longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
+NULL information_schema PROCESSLIST TIME_MS decimal NULL NULL NULL NULL decimal(22,3)
3.0000 information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
@@ -655,3 +842,7 @@ NULL information_schema TRIGGERS CREATED
3.0000 information_schema VIEWS SECURITY_TYPE varchar 7 21 utf8 utf8_general_ci varchar(7)
3.0000 information_schema VIEWS CHARACTER_SET_CLIENT varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema VIEWS COLLATION_CONNECTION varchar 32 96 utf8 utf8_general_ci varchar(32)
+3.0000 information_schema XTRADB_ENHANCEMENTS name varchar 255 765 utf8 utf8_general_ci varchar(255)
+3.0000 information_schema XTRADB_ENHANCEMENTS description varchar 255 765 utf8 utf8_general_ci varchar(255)
+3.0000 information_schema XTRADB_ENHANCEMENTS comment varchar 100 300 utf8 utf8_general_ci varchar(100)
+3.0000 information_schema XTRADB_ENHANCEMENTS link varchar 255 765 utf8 utf8_general_ci varchar(255)
=== added file 'mysql-test/suite/funcs_1/r/is_tables_is_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result 2009-10-26 11:35:42 +0000
@@ -0,0 +1,1921 @@
+DROP DATABASE IF EXISTS test1;
+CREATE DATABASE test1;
+SELECT *,
+LEFT( table_comment,
+IF(INSTR(table_comment,'InnoDB free') = 0
+AND INSTR(table_comment,'number_of_replicas') = 0,
+LENGTH(table_comment),
+INSTR(table_comment,'InnoDB free')
++ INSTR(table_comment,'number_of_replicas') - 1))
+AS "user_comment",
+'-----------------------------------------------------' AS "Separator"
+FROM information_schema.tables
+WHERE table_schema = 'information_schema'
+AND table_name <> 'profiling'
+ORDER BY table_schema,table_name;
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
+TABLE_NAME CHARACTER_SETS
+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 COLLATIONS
+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 COLLATION_CHARACTER_SET_APPLICABILITY
+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 COLUMNS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 COLUMN_PRIVILEGES
+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 ENGINES
+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 EVENTS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 FILES
+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 GLOBAL_STATUS
+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 GLOBAL_VARIABLES
+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 INNODB_BUFFER_POOL_PAGES
+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 INNODB_BUFFER_POOL_PAGES_BLOB
+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 INNODB_BUFFER_POOL_PAGES_INDEX
+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 INNODB_CMP
+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 INNODB_CMPMEM
+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 INNODB_CMPMEM_RESET
+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 INNODB_CMP_RESET
+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 INNODB_INDEX_STATS
+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 INNODB_LOCKS
+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 INNODB_LOCK_WAITS
+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 INNODB_RSEG
+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 INNODB_TABLE_STATS
+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 INNODB_TRX
+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
+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 PARTITIONS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 PLUGINS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 PROCESSLIST
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 REFERENTIAL_CONSTRAINTS
+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 ROUTINES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 SCHEMATA
+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 SCHEMA_PRIVILEGES
+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 SESSION_STATUS
+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 SESSION_VARIABLES
+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 STATISTICS
+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 TABLES
+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 TABLE_CONSTRAINTS
+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 TABLE_PRIVILEGES
+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 TRIGGERS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 USER_PRIVILEGES
+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 VIEWS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 XTRADB_ENHANCEMENTS
+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 -----------------------------------------------------
+DROP USER testuser1@localhost;
+CREATE USER testuser1@localhost;
+GRANT SELECT ON test1.* TO testuser1@localhost;
+# Establish connection testuser1 (user=testuser1)
+SELECT *,
+LEFT( table_comment,
+IF(INSTR(table_comment,'InnoDB free') = 0
+AND INSTR(table_comment,'number_of_replicas') = 0,
+LENGTH(table_comment),
+INSTR(table_comment,'InnoDB free')
++ INSTR(table_comment,'number_of_replicas') - 1))
+AS "user_comment",
+'-----------------------------------------------------' AS "Separator"
+FROM information_schema.tables
+WHERE table_schema = 'information_schema'
+AND table_name <> 'profiling'
+ORDER BY table_schema,table_name;
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
+TABLE_NAME CHARACTER_SETS
+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 COLLATIONS
+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 COLLATION_CHARACTER_SET_APPLICABILITY
+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 COLUMNS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 COLUMN_PRIVILEGES
+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 ENGINES
+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 EVENTS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 FILES
+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 GLOBAL_STATUS
+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 GLOBAL_VARIABLES
+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 INNODB_BUFFER_POOL_PAGES
+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 INNODB_BUFFER_POOL_PAGES_BLOB
+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 INNODB_BUFFER_POOL_PAGES_INDEX
+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 INNODB_CMP
+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 INNODB_CMPMEM
+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 INNODB_CMPMEM_RESET
+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 INNODB_CMP_RESET
+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 INNODB_INDEX_STATS
+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 INNODB_LOCKS
+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 INNODB_LOCK_WAITS
+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 INNODB_RSEG
+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 INNODB_TABLE_STATS
+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 INNODB_TRX
+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
+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 PARTITIONS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 PLUGINS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 PROCESSLIST
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 REFERENTIAL_CONSTRAINTS
+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 ROUTINES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 SCHEMATA
+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 SCHEMA_PRIVILEGES
+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 SESSION_STATUS
+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 SESSION_VARIABLES
+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 STATISTICS
+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 TABLES
+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 TABLE_CONSTRAINTS
+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 TABLE_PRIVILEGES
+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 TRIGGERS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 USER_PRIVILEGES
+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 VIEWS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MYISAM_OR_MARIA
+VERSION 10
+ROW_FORMAT DYNAMIC_OR_PAGE
+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 XTRADB_ENHANCEMENTS
+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 -----------------------------------------------------
+# Switch to connection default and close connection testuser1
+DROP USER testuser1@localhost;
+DROP DATABASE test1;
=== modified file 'mysql-test/suite/funcs_1/r/is_tables_myisam_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_tables_myisam_embedded.result 2008-06-16 18:39:58 +0000
+++ b/mysql-test/suite/funcs_1/r/is_tables_myisam_embedded.result 2009-10-26 11:35:42 +0000
@@ -22,9 +22,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA test1
TABLE_NAME t1
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -45,9 +45,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA test1
TABLE_NAME t2
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -68,9 +68,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA test2
TABLE_NAME t1
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -114,9 +114,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA test1
TABLE_NAME t1
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -137,9 +137,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA test1
TABLE_NAME t2
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -160,9 +160,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA test2
TABLE_NAME t1
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
=== modified file 'mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result 2008-06-18 17:23:55 +0000
+++ b/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result 2009-10-26 11:35:42 +0000
@@ -16,7 +16,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME columns_priv
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -39,7 +39,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME db
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -62,9 +62,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME event
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -85,7 +85,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME func
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -110,7 +110,7 @@ TABLE_NAME general_log
TABLE_TYPE BASE TABLE
ENGINE CSV
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -131,7 +131,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_category
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -154,7 +154,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_keyword
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -177,7 +177,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_relation
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -200,9 +200,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_topic
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -223,7 +223,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME host
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -246,9 +246,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME ndb_binlog_index
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -269,7 +269,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME plugin
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -292,9 +292,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME proc
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -315,7 +315,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME procs_priv
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -338,7 +338,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME servers
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -363,7 +363,7 @@ TABLE_NAME slow_log
TABLE_TYPE BASE TABLE
ENGINE CSV
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -384,7 +384,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME tables_priv
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -407,7 +407,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -430,7 +430,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_leap_second
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -453,7 +453,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_name
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -476,7 +476,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_transition
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -499,7 +499,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_transition_type
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -522,9 +522,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME user
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -561,7 +561,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME columns_priv
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -584,7 +584,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME db
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -607,9 +607,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME event
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -630,7 +630,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME func
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -655,7 +655,7 @@ TABLE_NAME general_log
TABLE_TYPE BASE TABLE
ENGINE CSV
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -676,7 +676,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_category
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -699,7 +699,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_keyword
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -722,7 +722,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_relation
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -745,9 +745,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME help_topic
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -768,7 +768,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME host
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -791,9 +791,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME ndb_binlog_index
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -814,7 +814,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME plugin
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -837,9 +837,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME proc
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -860,7 +860,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME procs_priv
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -883,7 +883,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME servers
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -908,7 +908,7 @@ TABLE_NAME slow_log
TABLE_TYPE BASE TABLE
ENGINE CSV
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
@@ -929,7 +929,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME tables_priv
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -952,7 +952,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -975,7 +975,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_leap_second
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -998,7 +998,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_name
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -1021,7 +1021,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_transition
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -1044,7 +1044,7 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME time_zone_transition_type
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
@@ -1067,9 +1067,9 @@ TABLE_CATALOG NULL
TABLE_SCHEMA mysql
TABLE_NAME user
TABLE_TYPE BASE TABLE
-ENGINE MyISAM
+ENGINE MYISAM_OR_MARIA
VERSION 10
-ROW_FORMAT Dynamic
+ROW_FORMAT DYNAMIC_OR_PAGE
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
=== modified file 'mysql-test/suite/funcs_1/t/is_tables_is.test'
--- a/mysql-test/suite/funcs_1/t/is_tables_is.test 2008-03-07 16:33:07 +0000
+++ b/mysql-test/suite/funcs_1/t/is_tables_is.test 2009-10-26 11:35:42 +0000
@@ -12,6 +12,7 @@
# Create this script based on older scripts and new code.
#
+--source include/not_embedded.inc
let $my_where = WHERE table_schema = 'information_schema'
AND table_name <> 'profiling';
--source suite/funcs_1/datadict/tables1.inc
=== added file 'mysql-test/suite/funcs_1/t/is_tables_is_embedded.test'
--- a/mysql-test/suite/funcs_1/t/is_tables_is_embedded.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/funcs_1/t/is_tables_is_embedded.test 2009-10-26 11:35:42 +0000
@@ -0,0 +1,22 @@
+# suite/funcs_1/t/is_tables_is_embedded.test
+#
+# Check the layout of information_schema.tables and the impact of
+# CREATE/ALTER/DROP TABLE/VIEW/SCHEMA ... on it.
+# Variant for the embedded server
+# The expected results must equal is_tables except that all users
+# have all privileges (affects some result sets).
+#
+# There is detailed information about this test within
+# suite/funcs_1/datadict/is_tables.inc
+#
+# Author:
+# 2008-06-06 mleich Create this this variant for the embedded server.
+#
+
+if (`SELECT VERSION() NOT LIKE '%embedded%'`)
+{
+ --skip Test requires: embedded server
+}
+let $my_where = WHERE table_schema = 'information_schema'
+AND table_name <> 'profiling';
+--source suite/funcs_1/datadict/tables1.inc
=== added file 'mysql-test/suite/maria/t/maria_showlog_error-master.opt'
--- a/mysql-test/suite/maria/t/maria_showlog_error-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/maria/t/maria_showlog_error-master.opt 2009-10-13 12:47:17 +0000
@@ -0,0 +1 @@
+--force-restart
=== modified file 'mysql-test/suite/parts/inc/partition.pre'
--- a/mysql-test/suite/parts/inc/partition.pre 2008-01-10 15:50:37 +0000
+++ b/mysql-test/suite/parts/inc/partition.pre 2009-10-28 07:52:34 +0000
@@ -152,6 +152,7 @@ ENGINE = MEMORY;
--echo # Logging of <max_row> INSERTs into t0_template suppressed
--disable_query_log
let $num= `SELECT @max_row`;
+begin;
while ($num)
{
eval INSERT INTO t0_template
@@ -160,6 +161,7 @@ f_charbig = '===$num===';
dec $num;
}
+commit;
--enable_query_log
# Auxiliary table used for comparisons of table definitions and file lists
=== modified file 'mysql-test/suite/parts/inc/partition_bigint.inc'
--- a/mysql-test/suite/parts/inc/partition_bigint.inc 2008-07-01 18:38:15 +0000
+++ b/mysql-test/suite/parts/inc/partition_bigint.inc 2009-10-28 07:52:34 +0000
@@ -32,11 +32,13 @@ delete from t2;
let $count=$maxrows;
--echo $maxrows inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
=== modified file 'mysql-test/suite/parts/inc/partition_binary.inc'
--- a/mysql-test/suite/parts/inc/partition_binary.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_binary.inc 2009-10-28 07:52:34 +0000
@@ -22,13 +22,16 @@ show create table t2;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t2;
select hex(a) from t2;
drop table t2;
@@ -48,13 +51,16 @@ show create table t3;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t3;
select hex(a) from t3;
drop table t3;
@@ -73,14 +79,16 @@ show create table t4;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
-
+commit;
+--enable_query_log
select count(*) from t4;
select hex(a) from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_bit.inc'
--- a/mysql-test/suite/parts/inc/partition_bit.inc 2008-02-07 15:26:22 +0000
+++ b/mysql-test/suite/parts/inc/partition_bit.inc 2009-10-28 07:52:34 +0000
@@ -74,11 +74,13 @@ show create table t3;
let $count=255;
--echo $count inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values ($count);
dec $count;
}
+commit;
--enable_query_log
select hex(a) from t3 where a=b'01010101';
delete from t3 where a=b'01010101';
@@ -96,11 +98,13 @@ show create table t4;
let $count=32;
--echo $count inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values ($count);
dec $count;
}
+commit;
--enable_query_log
select hex(a) from t4 where a=b'00000001';
delete from t4 where a=b'00000001';
=== modified file 'mysql-test/suite/parts/inc/partition_char.inc'
--- a/mysql-test/suite/parts/inc/partition_char.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_char.inc 2009-10-28 07:52:34 +0000
@@ -21,13 +21,16 @@ show create table t2;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -47,13 +50,16 @@ show create table t3;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t3;
select a from t3;
drop table t3;
@@ -71,13 +77,16 @@ show create table t4;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t4;
select a from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_date.inc'
--- a/mysql-test/suite/parts/inc/partition_date.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_date.inc 2009-10-28 07:52:34 +0000
@@ -23,7 +23,8 @@ select * from t2;
delete from t2;
let $count=28;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (19700101+$count-1);
@@ -31,7 +32,8 @@ eval insert into t2 values (19700201+$co
eval insert into t2 values (19700301+$count-1);
dec $count;
}
-#--enable_query_log
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -47,11 +49,15 @@ partition quarter4 values less than (13)
show create table t3;
let $count=12;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (adddate(19700101,interval $count-1 month));
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -67,11 +73,15 @@ partition quarter4 values in (10,11,12)
show create table t4;
let $count=12;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (adddate(19700101,interval $count-1 month));
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_datetime.inc'
--- a/mysql-test/suite/parts/inc/partition_datetime.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_datetime.inc 2009-10-28 07:52:34 +0000
@@ -23,12 +23,15 @@ select * from t2;
delete from t2;
let $count=59;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (19700101000000+$count);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -44,11 +47,15 @@ partition quarter4 values less than (13)
show create table t3;
let $count=12;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (adddate(19700101000000,interval $count-1 month));
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -64,11 +71,15 @@ partition quarter4 values in (10,11,12)
show create table t4;
let $count=12;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (adddate(19700101000000,interval $count-1 month));
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_decimal.inc'
--- a/mysql-test/suite/parts/inc/partition_decimal.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_decimal.inc 2009-10-28 07:52:34 +0000
@@ -24,6 +24,7 @@ delete from t2;
let $count=$maxrows;
--echo $count*3 inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
@@ -31,6 +32,7 @@ eval insert into t2 values ($count+0.333
eval insert into t2 values ($count+0.755555555);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
@@ -53,6 +55,8 @@ partition pa10 values less than (10)
show create table t3;
let $count=9;
--echo $count*3 inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values ($count);
@@ -60,6 +64,7 @@ eval insert into t3 values ($count+0.333
eval insert into t3 values ($count+0.755555555);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t3;
drop table t3;
@@ -75,6 +80,8 @@ partition pa10 values in (9,10)
show create table t4;
let $count=9;
--echo $count*3 inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values ($count);
@@ -82,6 +89,7 @@ eval insert into t4 values ($count+0.333
eval insert into t4 values ($count+0.755555555);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_double.inc'
--- a/mysql-test/suite/parts/inc/partition_double.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_double.inc 2009-10-28 07:52:34 +0000
@@ -24,6 +24,7 @@ delete from t2;
let $count=$maxrows;
--echo $maxrows*3 inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
@@ -31,6 +32,7 @@ eval insert into t2 values ($count+0.33)
eval insert into t2 values ($count+0.75);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
@@ -52,6 +54,8 @@ partition pa10 values less than (10)
show create table t3;
let $count=9;
--echo $count*3 inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values ($count);
@@ -59,6 +63,8 @@ eval insert into t3 values ($count+0.33)
eval insert into t3 values ($count+0.75);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -72,6 +78,8 @@ partition pa10 values in (7,8,9,10)
show create table t4;
let $count=9;
--echo $count*3 inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values ($count);
@@ -79,6 +87,8 @@ eval insert into t4 values ($count+0.33)
eval insert into t4 values ($count+0.75);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_enum.inc'
--- a/mysql-test/suite/parts/inc/partition_enum.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_enum.inc 2009-10-28 07:52:34 +0000
@@ -26,12 +26,15 @@ partition by key (a) partitions 27;
show create table t2;
let $letter=26;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($letter)
{
eval insert into t2 values (char(ascii('A')+$letter));
dec $letter;
}
+commit;
+--enable_query_log
insert into t2 values ('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('0');
select count(*) from t2;
select * from t2;
@@ -55,12 +58,15 @@ partition pa36 values less than (37)
show create table t3;
let $letter=36;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+ begin;
while ($letter)
{
#eval insert into t3 values ($letter);
dec $letter;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
=== modified file 'mysql-test/suite/parts/inc/partition_float.inc'
--- a/mysql-test/suite/parts/inc/partition_float.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_float.inc 2009-10-28 07:52:34 +0000
@@ -28,6 +28,7 @@ delete from t2;
let $count=$maxrows;
--echo $maxrows*3 inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
@@ -35,6 +36,7 @@ eval insert into t2 values ($count+0.33)
eval insert into t2 values ($count+0.75);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
@@ -55,6 +57,8 @@ partition pa10 values less than (10)
show create table t3;
let $count=9;
--echo $count*3 inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values ($count);
@@ -62,6 +66,8 @@ eval insert into t3 values ($count+0.33)
eval insert into t3 values ($count+0.75);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -75,6 +81,8 @@ partition pa10 values in (7,8,9,10)
show create table t4;
let $count=9;
--echo $count*3 inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values ($count);
@@ -82,6 +90,8 @@ eval insert into t4 values ($count+0.33)
eval insert into t4 values ($count+0.75);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_int.inc'
--- a/mysql-test/suite/parts/inc/partition_int.inc 2008-07-01 18:38:15 +0000
+++ b/mysql-test/suite/parts/inc/partition_int.inc 2009-10-28 07:52:34 +0000
@@ -28,11 +28,13 @@ delete from t2;
let $count=$maxrows;
--echo $count inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
=== modified file 'mysql-test/suite/parts/inc/partition_mediumint.inc'
--- a/mysql-test/suite/parts/inc/partition_mediumint.inc 2008-07-01 18:38:15 +0000
+++ b/mysql-test/suite/parts/inc/partition_mediumint.inc 2009-10-28 07:52:34 +0000
@@ -28,11 +28,13 @@ delete from t2;
let $count=$maxrows;
--echo $maxrows inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
=== modified file 'mysql-test/suite/parts/inc/partition_smallint.inc'
--- a/mysql-test/suite/parts/inc/partition_smallint.inc 2008-07-01 18:38:15 +0000
+++ b/mysql-test/suite/parts/inc/partition_smallint.inc 2009-10-28 07:52:34 +0000
@@ -28,11 +28,13 @@ delete from t2;
let $count=$maxrows;
--echo $count inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
=== modified file 'mysql-test/suite/parts/inc/partition_time.inc'
--- a/mysql-test/suite/parts/inc/partition_time.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_time.inc 2009-10-28 07:52:34 +0000
@@ -23,12 +23,15 @@ select * from t2;
delete from t2;
let $count=59;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (000100+$count);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -44,11 +47,15 @@ partition quarter4 values less than (61)
show create table t3;
let $count=59;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (100000+$count);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -64,11 +71,15 @@ partition quarter4 values in (46,47,48,4
show create table t4;
let $count=59;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (100000+$count);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_timestamp.inc'
--- a/mysql-test/suite/parts/inc/partition_timestamp.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_timestamp.inc 2009-10-28 07:52:34 +0000
@@ -23,12 +23,15 @@ select * from t2;
delete from t2;
let $count=59;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (19710101000000+$count);
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -44,11 +47,15 @@ partition quarter4 values less than (13)
show create table t3;
let $count=12;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month));
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -64,11 +71,15 @@ partition quarter4 values in (10,11,12)
show create table t4;
let $count=12;
--echo $count inserts;
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month));
dec $count;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_tinyint.inc'
--- a/mysql-test/suite/parts/inc/partition_tinyint.inc 2008-07-01 18:38:15 +0000
+++ b/mysql-test/suite/parts/inc/partition_tinyint.inc 2009-10-28 07:52:34 +0000
@@ -28,11 +28,13 @@ delete from t2;
let $count=255;
--echo 255 inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values ($count);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
drop table t2;
=== modified file 'mysql-test/suite/parts/inc/partition_varbinary.inc'
--- a/mysql-test/suite/parts/inc/partition_varbinary.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_varbinary.inc 2009-10-28 07:52:34 +0000
@@ -21,13 +21,16 @@ show create table t2;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (repeat(char(ascii('a')+$letter),$count*$count));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -47,13 +50,16 @@ show create table t3;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t3;
select hex(a) from t3;
drop table t3;
@@ -71,13 +77,16 @@ show create table t4;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t4;
select hex(a) from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_varchar.inc'
--- a/mysql-test/suite/parts/inc/partition_varchar.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_varchar.inc 2009-10-28 07:52:34 +0000
@@ -21,13 +21,16 @@ show create table t2;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (repeat(char(ascii('a')+$letter),$count*$count));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t2;
select * from t2;
drop table t2;
@@ -46,13 +49,16 @@ show create table t3;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t3;
select * from t3;
drop table t3;
@@ -70,13 +76,16 @@ show create table t4;
let $count=26;
let $letter=0;
--echo $count inserts;
-#--disable_query_log
+--disable_query_log
+begin;
while ($count)
{
eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54));
dec $count;
inc $letter;
}
+commit;
+--enable_query_log
select count(*) from t4;
select * from t4;
drop table t4;
=== modified file 'mysql-test/suite/parts/inc/partition_year.inc'
--- a/mysql-test/suite/parts/inc/partition_year.inc 2008-02-06 14:13:56 +0000
+++ b/mysql-test/suite/parts/inc/partition_year.inc 2009-10-28 07:52:34 +0000
@@ -24,11 +24,13 @@ delete from t2;
let $count=255;
--echo $count inserts;
--disable_query_log
+begin;
while ($count)
{
eval insert into t2 values (1901+$count);
dec $count;
}
+commit;
--enable_query_log
select count(*) from t2;
select * from t2;
=== modified file 'mysql-test/suite/parts/r/partition_char_innodb.result'
--- a/mysql-test/suite/parts/r/partition_char_innodb.result 2008-11-04 07:43:21 +0000
+++ b/mysql-test/suite/parts/r/partition_char_innodb.result 2009-10-28 07:52:34 +0000
@@ -45,32 +45,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26+54));
-insert into t2 values (repeat(char(ascii('a')+1),25+54));
-insert into t2 values (repeat(char(ascii('a')+2),24+54));
-insert into t2 values (repeat(char(ascii('a')+3),23+54));
-insert into t2 values (repeat(char(ascii('a')+4),22+54));
-insert into t2 values (repeat(char(ascii('a')+5),21+54));
-insert into t2 values (repeat(char(ascii('a')+6),20+54));
-insert into t2 values (repeat(char(ascii('a')+7),19+54));
-insert into t2 values (repeat(char(ascii('a')+8),18+54));
-insert into t2 values (repeat(char(ascii('a')+9),17+54));
-insert into t2 values (repeat(char(ascii('a')+10),16+54));
-insert into t2 values (repeat(char(ascii('a')+11),15+54));
-insert into t2 values (repeat(char(ascii('a')+12),14+54));
-insert into t2 values (repeat(char(ascii('a')+13),13+54));
-insert into t2 values (repeat(char(ascii('a')+14),12+54));
-insert into t2 values (repeat(char(ascii('a')+15),11+54));
-insert into t2 values (repeat(char(ascii('a')+16),10+54));
-insert into t2 values (repeat(char(ascii('a')+17),9+54));
-insert into t2 values (repeat(char(ascii('a')+18),8+54));
-insert into t2 values (repeat(char(ascii('a')+19),7+54));
-insert into t2 values (repeat(char(ascii('a')+20),6+54));
-insert into t2 values (repeat(char(ascii('a')+21),5+54));
-insert into t2 values (repeat(char(ascii('a')+22),4+54));
-insert into t2 values (repeat(char(ascii('a')+23),3+54));
-insert into t2 values (repeat(char(ascii('a')+24),2+54));
-insert into t2 values (repeat(char(ascii('a')+25),1+54));
select count(*) from t2;
count(*)
26
@@ -153,32 +127,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26+54));
-insert into t2 values (repeat(char(ascii('a')+1),25+54));
-insert into t2 values (repeat(char(ascii('a')+2),24+54));
-insert into t2 values (repeat(char(ascii('a')+3),23+54));
-insert into t2 values (repeat(char(ascii('a')+4),22+54));
-insert into t2 values (repeat(char(ascii('a')+5),21+54));
-insert into t2 values (repeat(char(ascii('a')+6),20+54));
-insert into t2 values (repeat(char(ascii('a')+7),19+54));
-insert into t2 values (repeat(char(ascii('a')+8),18+54));
-insert into t2 values (repeat(char(ascii('a')+9),17+54));
-insert into t2 values (repeat(char(ascii('a')+10),16+54));
-insert into t2 values (repeat(char(ascii('a')+11),15+54));
-insert into t2 values (repeat(char(ascii('a')+12),14+54));
-insert into t2 values (repeat(char(ascii('a')+13),13+54));
-insert into t2 values (repeat(char(ascii('a')+14),12+54));
-insert into t2 values (repeat(char(ascii('a')+15),11+54));
-insert into t2 values (repeat(char(ascii('a')+16),10+54));
-insert into t2 values (repeat(char(ascii('a')+17),9+54));
-insert into t2 values (repeat(char(ascii('a')+18),8+54));
-insert into t2 values (repeat(char(ascii('a')+19),7+54));
-insert into t2 values (repeat(char(ascii('a')+20),6+54));
-insert into t2 values (repeat(char(ascii('a')+21),5+54));
-insert into t2 values (repeat(char(ascii('a')+22),4+54));
-insert into t2 values (repeat(char(ascii('a')+23),3+54));
-insert into t2 values (repeat(char(ascii('a')+24),2+54));
-insert into t2 values (repeat(char(ascii('a')+25),1+54));
select count(*) from t2;
count(*)
26
@@ -258,32 +206,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26*26));
-insert into t2 values (repeat(char(ascii('a')+1),25*25));
-insert into t2 values (repeat(char(ascii('a')+2),24*24));
-insert into t2 values (repeat(char(ascii('a')+3),23*23));
-insert into t2 values (repeat(char(ascii('a')+4),22*22));
-insert into t2 values (repeat(char(ascii('a')+5),21*21));
-insert into t2 values (repeat(char(ascii('a')+6),20*20));
-insert into t2 values (repeat(char(ascii('a')+7),19*19));
-insert into t2 values (repeat(char(ascii('a')+8),18*18));
-insert into t2 values (repeat(char(ascii('a')+9),17*17));
-insert into t2 values (repeat(char(ascii('a')+10),16*16));
-insert into t2 values (repeat(char(ascii('a')+11),15*15));
-insert into t2 values (repeat(char(ascii('a')+12),14*14));
-insert into t2 values (repeat(char(ascii('a')+13),13*13));
-insert into t2 values (repeat(char(ascii('a')+14),12*12));
-insert into t2 values (repeat(char(ascii('a')+15),11*11));
-insert into t2 values (repeat(char(ascii('a')+16),10*10));
-insert into t2 values (repeat(char(ascii('a')+17),9*9));
-insert into t2 values (repeat(char(ascii('a')+18),8*8));
-insert into t2 values (repeat(char(ascii('a')+19),7*7));
-insert into t2 values (repeat(char(ascii('a')+20),6*6));
-insert into t2 values (repeat(char(ascii('a')+21),5*5));
-insert into t2 values (repeat(char(ascii('a')+22),4*4));
-insert into t2 values (repeat(char(ascii('a')+23),3*3));
-insert into t2 values (repeat(char(ascii('a')+24),2*2));
-insert into t2 values (repeat(char(ascii('a')+25),1*1));
select count(*) from t2;
count(*)
26
@@ -363,32 +285,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 30 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26*26));
-insert into t2 values (repeat(char(ascii('a')+1),25*25));
-insert into t2 values (repeat(char(ascii('a')+2),24*24));
-insert into t2 values (repeat(char(ascii('a')+3),23*23));
-insert into t2 values (repeat(char(ascii('a')+4),22*22));
-insert into t2 values (repeat(char(ascii('a')+5),21*21));
-insert into t2 values (repeat(char(ascii('a')+6),20*20));
-insert into t2 values (repeat(char(ascii('a')+7),19*19));
-insert into t2 values (repeat(char(ascii('a')+8),18*18));
-insert into t2 values (repeat(char(ascii('a')+9),17*17));
-insert into t2 values (repeat(char(ascii('a')+10),16*16));
-insert into t2 values (repeat(char(ascii('a')+11),15*15));
-insert into t2 values (repeat(char(ascii('a')+12),14*14));
-insert into t2 values (repeat(char(ascii('a')+13),13*13));
-insert into t2 values (repeat(char(ascii('a')+14),12*12));
-insert into t2 values (repeat(char(ascii('a')+15),11*11));
-insert into t2 values (repeat(char(ascii('a')+16),10*10));
-insert into t2 values (repeat(char(ascii('a')+17),9*9));
-insert into t2 values (repeat(char(ascii('a')+18),8*8));
-insert into t2 values (repeat(char(ascii('a')+19),7*7));
-insert into t2 values (repeat(char(ascii('a')+20),6*6));
-insert into t2 values (repeat(char(ascii('a')+21),5*5));
-insert into t2 values (repeat(char(ascii('a')+22),4*4));
-insert into t2 values (repeat(char(ascii('a')+23),3*3));
-insert into t2 values (repeat(char(ascii('a')+24),2*2));
-insert into t2 values (repeat(char(ascii('a')+25),1*1));
select count(*) from t2;
count(*)
26
@@ -479,34 +375,8 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
0 inserts;
-insert into t2 values (char(ascii('A')+26));
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
-insert into t2 values (char(ascii('A')+25));
-insert into t2 values (char(ascii('A')+24));
-insert into t2 values (char(ascii('A')+23));
-insert into t2 values (char(ascii('A')+22));
-insert into t2 values (char(ascii('A')+21));
-insert into t2 values (char(ascii('A')+20));
-insert into t2 values (char(ascii('A')+19));
-insert into t2 values (char(ascii('A')+18));
-insert into t2 values (char(ascii('A')+17));
-insert into t2 values (char(ascii('A')+16));
-insert into t2 values (char(ascii('A')+15));
-insert into t2 values (char(ascii('A')+14));
-insert into t2 values (char(ascii('A')+13));
-insert into t2 values (char(ascii('A')+12));
-insert into t2 values (char(ascii('A')+11));
-insert into t2 values (char(ascii('A')+10));
-insert into t2 values (char(ascii('A')+9));
-insert into t2 values (char(ascii('A')+8));
-insert into t2 values (char(ascii('A')+7));
-insert into t2 values (char(ascii('A')+6));
-insert into t2 values (char(ascii('A')+5));
-insert into t2 values (char(ascii('A')+4));
-insert into t2 values (char(ascii('A')+3));
-insert into t2 values (char(ascii('A')+2));
-insert into t2 values (char(ascii('A')+1));
insert into t2 values ('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('0');
select count(*) from t2;
count(*)
=== modified file 'mysql-test/suite/parts/r/partition_char_myisam.result'
--- a/mysql-test/suite/parts/r/partition_char_myisam.result 2008-11-04 07:43:21 +0000
+++ b/mysql-test/suite/parts/r/partition_char_myisam.result 2009-10-28 07:52:34 +0000
@@ -45,32 +45,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26+54));
-insert into t2 values (repeat(char(ascii('a')+1),25+54));
-insert into t2 values (repeat(char(ascii('a')+2),24+54));
-insert into t2 values (repeat(char(ascii('a')+3),23+54));
-insert into t2 values (repeat(char(ascii('a')+4),22+54));
-insert into t2 values (repeat(char(ascii('a')+5),21+54));
-insert into t2 values (repeat(char(ascii('a')+6),20+54));
-insert into t2 values (repeat(char(ascii('a')+7),19+54));
-insert into t2 values (repeat(char(ascii('a')+8),18+54));
-insert into t2 values (repeat(char(ascii('a')+9),17+54));
-insert into t2 values (repeat(char(ascii('a')+10),16+54));
-insert into t2 values (repeat(char(ascii('a')+11),15+54));
-insert into t2 values (repeat(char(ascii('a')+12),14+54));
-insert into t2 values (repeat(char(ascii('a')+13),13+54));
-insert into t2 values (repeat(char(ascii('a')+14),12+54));
-insert into t2 values (repeat(char(ascii('a')+15),11+54));
-insert into t2 values (repeat(char(ascii('a')+16),10+54));
-insert into t2 values (repeat(char(ascii('a')+17),9+54));
-insert into t2 values (repeat(char(ascii('a')+18),8+54));
-insert into t2 values (repeat(char(ascii('a')+19),7+54));
-insert into t2 values (repeat(char(ascii('a')+20),6+54));
-insert into t2 values (repeat(char(ascii('a')+21),5+54));
-insert into t2 values (repeat(char(ascii('a')+22),4+54));
-insert into t2 values (repeat(char(ascii('a')+23),3+54));
-insert into t2 values (repeat(char(ascii('a')+24),2+54));
-insert into t2 values (repeat(char(ascii('a')+25),1+54));
select count(*) from t2;
count(*)
26
@@ -153,32 +127,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26+54));
-insert into t2 values (repeat(char(ascii('a')+1),25+54));
-insert into t2 values (repeat(char(ascii('a')+2),24+54));
-insert into t2 values (repeat(char(ascii('a')+3),23+54));
-insert into t2 values (repeat(char(ascii('a')+4),22+54));
-insert into t2 values (repeat(char(ascii('a')+5),21+54));
-insert into t2 values (repeat(char(ascii('a')+6),20+54));
-insert into t2 values (repeat(char(ascii('a')+7),19+54));
-insert into t2 values (repeat(char(ascii('a')+8),18+54));
-insert into t2 values (repeat(char(ascii('a')+9),17+54));
-insert into t2 values (repeat(char(ascii('a')+10),16+54));
-insert into t2 values (repeat(char(ascii('a')+11),15+54));
-insert into t2 values (repeat(char(ascii('a')+12),14+54));
-insert into t2 values (repeat(char(ascii('a')+13),13+54));
-insert into t2 values (repeat(char(ascii('a')+14),12+54));
-insert into t2 values (repeat(char(ascii('a')+15),11+54));
-insert into t2 values (repeat(char(ascii('a')+16),10+54));
-insert into t2 values (repeat(char(ascii('a')+17),9+54));
-insert into t2 values (repeat(char(ascii('a')+18),8+54));
-insert into t2 values (repeat(char(ascii('a')+19),7+54));
-insert into t2 values (repeat(char(ascii('a')+20),6+54));
-insert into t2 values (repeat(char(ascii('a')+21),5+54));
-insert into t2 values (repeat(char(ascii('a')+22),4+54));
-insert into t2 values (repeat(char(ascii('a')+23),3+54));
-insert into t2 values (repeat(char(ascii('a')+24),2+54));
-insert into t2 values (repeat(char(ascii('a')+25),1+54));
select count(*) from t2;
count(*)
26
@@ -258,32 +206,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26*26));
-insert into t2 values (repeat(char(ascii('a')+1),25*25));
-insert into t2 values (repeat(char(ascii('a')+2),24*24));
-insert into t2 values (repeat(char(ascii('a')+3),23*23));
-insert into t2 values (repeat(char(ascii('a')+4),22*22));
-insert into t2 values (repeat(char(ascii('a')+5),21*21));
-insert into t2 values (repeat(char(ascii('a')+6),20*20));
-insert into t2 values (repeat(char(ascii('a')+7),19*19));
-insert into t2 values (repeat(char(ascii('a')+8),18*18));
-insert into t2 values (repeat(char(ascii('a')+9),17*17));
-insert into t2 values (repeat(char(ascii('a')+10),16*16));
-insert into t2 values (repeat(char(ascii('a')+11),15*15));
-insert into t2 values (repeat(char(ascii('a')+12),14*14));
-insert into t2 values (repeat(char(ascii('a')+13),13*13));
-insert into t2 values (repeat(char(ascii('a')+14),12*12));
-insert into t2 values (repeat(char(ascii('a')+15),11*11));
-insert into t2 values (repeat(char(ascii('a')+16),10*10));
-insert into t2 values (repeat(char(ascii('a')+17),9*9));
-insert into t2 values (repeat(char(ascii('a')+18),8*8));
-insert into t2 values (repeat(char(ascii('a')+19),7*7));
-insert into t2 values (repeat(char(ascii('a')+20),6*6));
-insert into t2 values (repeat(char(ascii('a')+21),5*5));
-insert into t2 values (repeat(char(ascii('a')+22),4*4));
-insert into t2 values (repeat(char(ascii('a')+23),3*3));
-insert into t2 values (repeat(char(ascii('a')+24),2*2));
-insert into t2 values (repeat(char(ascii('a')+25),1*1));
select count(*) from t2;
count(*)
26
@@ -363,32 +285,6 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 30 */
26 inserts;
-insert into t2 values (repeat(char(ascii('a')+0),26*26));
-insert into t2 values (repeat(char(ascii('a')+1),25*25));
-insert into t2 values (repeat(char(ascii('a')+2),24*24));
-insert into t2 values (repeat(char(ascii('a')+3),23*23));
-insert into t2 values (repeat(char(ascii('a')+4),22*22));
-insert into t2 values (repeat(char(ascii('a')+5),21*21));
-insert into t2 values (repeat(char(ascii('a')+6),20*20));
-insert into t2 values (repeat(char(ascii('a')+7),19*19));
-insert into t2 values (repeat(char(ascii('a')+8),18*18));
-insert into t2 values (repeat(char(ascii('a')+9),17*17));
-insert into t2 values (repeat(char(ascii('a')+10),16*16));
-insert into t2 values (repeat(char(ascii('a')+11),15*15));
-insert into t2 values (repeat(char(ascii('a')+12),14*14));
-insert into t2 values (repeat(char(ascii('a')+13),13*13));
-insert into t2 values (repeat(char(ascii('a')+14),12*12));
-insert into t2 values (repeat(char(ascii('a')+15),11*11));
-insert into t2 values (repeat(char(ascii('a')+16),10*10));
-insert into t2 values (repeat(char(ascii('a')+17),9*9));
-insert into t2 values (repeat(char(ascii('a')+18),8*8));
-insert into t2 values (repeat(char(ascii('a')+19),7*7));
-insert into t2 values (repeat(char(ascii('a')+20),6*6));
-insert into t2 values (repeat(char(ascii('a')+21),5*5));
-insert into t2 values (repeat(char(ascii('a')+22),4*4));
-insert into t2 values (repeat(char(ascii('a')+23),3*3));
-insert into t2 values (repeat(char(ascii('a')+24),2*2));
-insert into t2 values (repeat(char(ascii('a')+25),1*1));
select count(*) from t2;
count(*)
26
@@ -479,34 +375,8 @@ t2 CREATE TABLE `t2` (
/*!50100 PARTITION BY KEY (a)
PARTITIONS 27 */
0 inserts;
-insert into t2 values (char(ascii('A')+26));
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
-insert into t2 values (char(ascii('A')+25));
-insert into t2 values (char(ascii('A')+24));
-insert into t2 values (char(ascii('A')+23));
-insert into t2 values (char(ascii('A')+22));
-insert into t2 values (char(ascii('A')+21));
-insert into t2 values (char(ascii('A')+20));
-insert into t2 values (char(ascii('A')+19));
-insert into t2 values (char(ascii('A')+18));
-insert into t2 values (char(ascii('A')+17));
-insert into t2 values (char(ascii('A')+16));
-insert into t2 values (char(ascii('A')+15));
-insert into t2 values (char(ascii('A')+14));
-insert into t2 values (char(ascii('A')+13));
-insert into t2 values (char(ascii('A')+12));
-insert into t2 values (char(ascii('A')+11));
-insert into t2 values (char(ascii('A')+10));
-insert into t2 values (char(ascii('A')+9));
-insert into t2 values (char(ascii('A')+8));
-insert into t2 values (char(ascii('A')+7));
-insert into t2 values (char(ascii('A')+6));
-insert into t2 values (char(ascii('A')+5));
-insert into t2 values (char(ascii('A')+4));
-insert into t2 values (char(ascii('A')+3));
-insert into t2 values (char(ascii('A')+2));
-insert into t2 values (char(ascii('A')+1));
insert into t2 values ('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('0');
select count(*) from t2;
count(*)
=== modified file 'mysql-test/suite/parts/r/partition_datetime_innodb.result'
--- a/mysql-test/suite/parts/r/partition_datetime_innodb.result 2008-11-04 07:43:21 +0000
+++ b/mysql-test/suite/parts/r/partition_datetime_innodb.result 2009-10-28 07:52:34 +0000
@@ -60,65 +60,6 @@ a
2020-12-31 10:11:12
delete from t2;
59 inserts;
-insert into t2 values (19710101000000+59);
-insert into t2 values (19710101000000+58);
-insert into t2 values (19710101000000+57);
-insert into t2 values (19710101000000+56);
-insert into t2 values (19710101000000+55);
-insert into t2 values (19710101000000+54);
-insert into t2 values (19710101000000+53);
-insert into t2 values (19710101000000+52);
-insert into t2 values (19710101000000+51);
-insert into t2 values (19710101000000+50);
-insert into t2 values (19710101000000+49);
-insert into t2 values (19710101000000+48);
-insert into t2 values (19710101000000+47);
-insert into t2 values (19710101000000+46);
-insert into t2 values (19710101000000+45);
-insert into t2 values (19710101000000+44);
-insert into t2 values (19710101000000+43);
-insert into t2 values (19710101000000+42);
-insert into t2 values (19710101000000+41);
-insert into t2 values (19710101000000+40);
-insert into t2 values (19710101000000+39);
-insert into t2 values (19710101000000+38);
-insert into t2 values (19710101000000+37);
-insert into t2 values (19710101000000+36);
-insert into t2 values (19710101000000+35);
-insert into t2 values (19710101000000+34);
-insert into t2 values (19710101000000+33);
-insert into t2 values (19710101000000+32);
-insert into t2 values (19710101000000+31);
-insert into t2 values (19710101000000+30);
-insert into t2 values (19710101000000+29);
-insert into t2 values (19710101000000+28);
-insert into t2 values (19710101000000+27);
-insert into t2 values (19710101000000+26);
-insert into t2 values (19710101000000+25);
-insert into t2 values (19710101000000+24);
-insert into t2 values (19710101000000+23);
-insert into t2 values (19710101000000+22);
-insert into t2 values (19710101000000+21);
-insert into t2 values (19710101000000+20);
-insert into t2 values (19710101000000+19);
-insert into t2 values (19710101000000+18);
-insert into t2 values (19710101000000+17);
-insert into t2 values (19710101000000+16);
-insert into t2 values (19710101000000+15);
-insert into t2 values (19710101000000+14);
-insert into t2 values (19710101000000+13);
-insert into t2 values (19710101000000+12);
-insert into t2 values (19710101000000+11);
-insert into t2 values (19710101000000+10);
-insert into t2 values (19710101000000+9);
-insert into t2 values (19710101000000+8);
-insert into t2 values (19710101000000+7);
-insert into t2 values (19710101000000+6);
-insert into t2 values (19710101000000+5);
-insert into t2 values (19710101000000+4);
-insert into t2 values (19710101000000+3);
-insert into t2 values (19710101000000+2);
-insert into t2 values (19710101000000+1);
select count(*) from t2;
count(*)
59
@@ -206,18 +147,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */
12 inserts;
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month));
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
select count(*) from t3;
@@ -260,18 +189,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB,
PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */
12 inserts;
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month));
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
select count(*) from t4;
@@ -354,90 +271,6 @@ a
2020-12-31
delete from t2;
28 inserts;
-insert into t2 values (19700101+28-1);
-insert into t2 values (19700201+28-1);
-insert into t2 values (19700301+28-1);
-insert into t2 values (19700101+27-1);
-insert into t2 values (19700201+27-1);
-insert into t2 values (19700301+27-1);
-insert into t2 values (19700101+26-1);
-insert into t2 values (19700201+26-1);
-insert into t2 values (19700301+26-1);
-insert into t2 values (19700101+25-1);
-insert into t2 values (19700201+25-1);
-insert into t2 values (19700301+25-1);
-insert into t2 values (19700101+24-1);
-insert into t2 values (19700201+24-1);
-insert into t2 values (19700301+24-1);
-insert into t2 values (19700101+23-1);
-insert into t2 values (19700201+23-1);
-insert into t2 values (19700301+23-1);
-insert into t2 values (19700101+22-1);
-insert into t2 values (19700201+22-1);
-insert into t2 values (19700301+22-1);
-insert into t2 values (19700101+21-1);
-insert into t2 values (19700201+21-1);
-insert into t2 values (19700301+21-1);
-insert into t2 values (19700101+20-1);
-insert into t2 values (19700201+20-1);
-insert into t2 values (19700301+20-1);
-insert into t2 values (19700101+19-1);
-insert into t2 values (19700201+19-1);
-insert into t2 values (19700301+19-1);
-insert into t2 values (19700101+18-1);
-insert into t2 values (19700201+18-1);
-insert into t2 values (19700301+18-1);
-insert into t2 values (19700101+17-1);
-insert into t2 values (19700201+17-1);
-insert into t2 values (19700301+17-1);
-insert into t2 values (19700101+16-1);
-insert into t2 values (19700201+16-1);
-insert into t2 values (19700301+16-1);
-insert into t2 values (19700101+15-1);
-insert into t2 values (19700201+15-1);
-insert into t2 values (19700301+15-1);
-insert into t2 values (19700101+14-1);
-insert into t2 values (19700201+14-1);
-insert into t2 values (19700301+14-1);
-insert into t2 values (19700101+13-1);
-insert into t2 values (19700201+13-1);
-insert into t2 values (19700301+13-1);
-insert into t2 values (19700101+12-1);
-insert into t2 values (19700201+12-1);
-insert into t2 values (19700301+12-1);
-insert into t2 values (19700101+11-1);
-insert into t2 values (19700201+11-1);
-insert into t2 values (19700301+11-1);
-insert into t2 values (19700101+10-1);
-insert into t2 values (19700201+10-1);
-insert into t2 values (19700301+10-1);
-insert into t2 values (19700101+9-1);
-insert into t2 values (19700201+9-1);
-insert into t2 values (19700301+9-1);
-insert into t2 values (19700101+8-1);
-insert into t2 values (19700201+8-1);
-insert into t2 values (19700301+8-1);
-insert into t2 values (19700101+7-1);
-insert into t2 values (19700201+7-1);
-insert into t2 values (19700301+7-1);
-insert into t2 values (19700101+6-1);
-insert into t2 values (19700201+6-1);
-insert into t2 values (19700301+6-1);
-insert into t2 values (19700101+5-1);
-insert into t2 values (19700201+5-1);
-insert into t2 values (19700301+5-1);
-insert into t2 values (19700101+4-1);
-insert into t2 values (19700201+4-1);
-insert into t2 values (19700301+4-1);
-insert into t2 values (19700101+3-1);
-insert into t2 values (19700201+3-1);
-insert into t2 values (19700301+3-1);
-insert into t2 values (19700101+2-1);
-insert into t2 values (19700201+2-1);
-insert into t2 values (19700301+2-1);
-insert into t2 values (19700101+1-1);
-insert into t2 values (19700201+1-1);
-insert into t2 values (19700301+1-1);
select count(*) from t2;
count(*)
84
@@ -550,18 +383,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */
12 inserts;
-insert into t3 values (adddate(19700101,interval 12-1 month));
-insert into t3 values (adddate(19700101,interval 11-1 month));
-insert into t3 values (adddate(19700101,interval 10-1 month));
-insert into t3 values (adddate(19700101,interval 9-1 month));
-insert into t3 values (adddate(19700101,interval 8-1 month));
-insert into t3 values (adddate(19700101,interval 7-1 month));
-insert into t3 values (adddate(19700101,interval 6-1 month));
-insert into t3 values (adddate(19700101,interval 5-1 month));
-insert into t3 values (adddate(19700101,interval 4-1 month));
-insert into t3 values (adddate(19700101,interval 3-1 month));
-insert into t3 values (adddate(19700101,interval 2-1 month));
-insert into t3 values (adddate(19700101,interval 1-1 month));
select count(*) from t3;
count(*)
12
@@ -602,18 +423,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB,
PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */
12 inserts;
-insert into t4 values (adddate(19700101,interval 12-1 month));
-insert into t4 values (adddate(19700101,interval 11-1 month));
-insert into t4 values (adddate(19700101,interval 10-1 month));
-insert into t4 values (adddate(19700101,interval 9-1 month));
-insert into t4 values (adddate(19700101,interval 8-1 month));
-insert into t4 values (adddate(19700101,interval 7-1 month));
-insert into t4 values (adddate(19700101,interval 6-1 month));
-insert into t4 values (adddate(19700101,interval 5-1 month));
-insert into t4 values (adddate(19700101,interval 4-1 month));
-insert into t4 values (adddate(19700101,interval 3-1 month));
-insert into t4 values (adddate(19700101,interval 2-1 month));
-insert into t4 values (adddate(19700101,interval 1-1 month));
select count(*) from t4;
count(*)
12
@@ -694,65 +503,6 @@ a
14:15:16
delete from t2;
59 inserts;
-insert into t2 values (000100+59);
-insert into t2 values (000100+58);
-insert into t2 values (000100+57);
-insert into t2 values (000100+56);
-insert into t2 values (000100+55);
-insert into t2 values (000100+54);
-insert into t2 values (000100+53);
-insert into t2 values (000100+52);
-insert into t2 values (000100+51);
-insert into t2 values (000100+50);
-insert into t2 values (000100+49);
-insert into t2 values (000100+48);
-insert into t2 values (000100+47);
-insert into t2 values (000100+46);
-insert into t2 values (000100+45);
-insert into t2 values (000100+44);
-insert into t2 values (000100+43);
-insert into t2 values (000100+42);
-insert into t2 values (000100+41);
-insert into t2 values (000100+40);
-insert into t2 values (000100+39);
-insert into t2 values (000100+38);
-insert into t2 values (000100+37);
-insert into t2 values (000100+36);
-insert into t2 values (000100+35);
-insert into t2 values (000100+34);
-insert into t2 values (000100+33);
-insert into t2 values (000100+32);
-insert into t2 values (000100+31);
-insert into t2 values (000100+30);
-insert into t2 values (000100+29);
-insert into t2 values (000100+28);
-insert into t2 values (000100+27);
-insert into t2 values (000100+26);
-insert into t2 values (000100+25);
-insert into t2 values (000100+24);
-insert into t2 values (000100+23);
-insert into t2 values (000100+22);
-insert into t2 values (000100+21);
-insert into t2 values (000100+20);
-insert into t2 values (000100+19);
-insert into t2 values (000100+18);
-insert into t2 values (000100+17);
-insert into t2 values (000100+16);
-insert into t2 values (000100+15);
-insert into t2 values (000100+14);
-insert into t2 values (000100+13);
-insert into t2 values (000100+12);
-insert into t2 values (000100+11);
-insert into t2 values (000100+10);
-insert into t2 values (000100+9);
-insert into t2 values (000100+8);
-insert into t2 values (000100+7);
-insert into t2 values (000100+6);
-insert into t2 values (000100+5);
-insert into t2 values (000100+4);
-insert into t2 values (000100+3);
-insert into t2 values (000100+2);
-insert into t2 values (000100+1);
select count(*) from t2;
count(*)
59
@@ -840,65 +590,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (46) ENGINE = InnoDB,
PARTITION quarter4 VALUES LESS THAN (61) ENGINE = InnoDB) */
59 inserts;
-insert into t3 values (100000+59);
-insert into t3 values (100000+58);
-insert into t3 values (100000+57);
-insert into t3 values (100000+56);
-insert into t3 values (100000+55);
-insert into t3 values (100000+54);
-insert into t3 values (100000+53);
-insert into t3 values (100000+52);
-insert into t3 values (100000+51);
-insert into t3 values (100000+50);
-insert into t3 values (100000+49);
-insert into t3 values (100000+48);
-insert into t3 values (100000+47);
-insert into t3 values (100000+46);
-insert into t3 values (100000+45);
-insert into t3 values (100000+44);
-insert into t3 values (100000+43);
-insert into t3 values (100000+42);
-insert into t3 values (100000+41);
-insert into t3 values (100000+40);
-insert into t3 values (100000+39);
-insert into t3 values (100000+38);
-insert into t3 values (100000+37);
-insert into t3 values (100000+36);
-insert into t3 values (100000+35);
-insert into t3 values (100000+34);
-insert into t3 values (100000+33);
-insert into t3 values (100000+32);
-insert into t3 values (100000+31);
-insert into t3 values (100000+30);
-insert into t3 values (100000+29);
-insert into t3 values (100000+28);
-insert into t3 values (100000+27);
-insert into t3 values (100000+26);
-insert into t3 values (100000+25);
-insert into t3 values (100000+24);
-insert into t3 values (100000+23);
-insert into t3 values (100000+22);
-insert into t3 values (100000+21);
-insert into t3 values (100000+20);
-insert into t3 values (100000+19);
-insert into t3 values (100000+18);
-insert into t3 values (100000+17);
-insert into t3 values (100000+16);
-insert into t3 values (100000+15);
-insert into t3 values (100000+14);
-insert into t3 values (100000+13);
-insert into t3 values (100000+12);
-insert into t3 values (100000+11);
-insert into t3 values (100000+10);
-insert into t3 values (100000+9);
-insert into t3 values (100000+8);
-insert into t3 values (100000+7);
-insert into t3 values (100000+6);
-insert into t3 values (100000+5);
-insert into t3 values (100000+4);
-insert into t3 values (100000+3);
-insert into t3 values (100000+2);
-insert into t3 values (100000+1);
select count(*) from t3;
count(*)
59
@@ -986,65 +677,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) ENGINE = InnoDB,
PARTITION quarter4 VALUES IN (46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) ENGINE = InnoDB) */
59 inserts;
-insert into t4 values (100000+59);
-insert into t4 values (100000+58);
-insert into t4 values (100000+57);
-insert into t4 values (100000+56);
-insert into t4 values (100000+55);
-insert into t4 values (100000+54);
-insert into t4 values (100000+53);
-insert into t4 values (100000+52);
-insert into t4 values (100000+51);
-insert into t4 values (100000+50);
-insert into t4 values (100000+49);
-insert into t4 values (100000+48);
-insert into t4 values (100000+47);
-insert into t4 values (100000+46);
-insert into t4 values (100000+45);
-insert into t4 values (100000+44);
-insert into t4 values (100000+43);
-insert into t4 values (100000+42);
-insert into t4 values (100000+41);
-insert into t4 values (100000+40);
-insert into t4 values (100000+39);
-insert into t4 values (100000+38);
-insert into t4 values (100000+37);
-insert into t4 values (100000+36);
-insert into t4 values (100000+35);
-insert into t4 values (100000+34);
-insert into t4 values (100000+33);
-insert into t4 values (100000+32);
-insert into t4 values (100000+31);
-insert into t4 values (100000+30);
-insert into t4 values (100000+29);
-insert into t4 values (100000+28);
-insert into t4 values (100000+27);
-insert into t4 values (100000+26);
-insert into t4 values (100000+25);
-insert into t4 values (100000+24);
-insert into t4 values (100000+23);
-insert into t4 values (100000+22);
-insert into t4 values (100000+21);
-insert into t4 values (100000+20);
-insert into t4 values (100000+19);
-insert into t4 values (100000+18);
-insert into t4 values (100000+17);
-insert into t4 values (100000+16);
-insert into t4 values (100000+15);
-insert into t4 values (100000+14);
-insert into t4 values (100000+13);
-insert into t4 values (100000+12);
-insert into t4 values (100000+11);
-insert into t4 values (100000+10);
-insert into t4 values (100000+9);
-insert into t4 values (100000+8);
-insert into t4 values (100000+7);
-insert into t4 values (100000+6);
-insert into t4 values (100000+5);
-insert into t4 values (100000+4);
-insert into t4 values (100000+3);
-insert into t4 values (100000+2);
-insert into t4 values (100000+1);
select count(*) from t4;
count(*)
59
@@ -1172,65 +804,6 @@ a
2020-12-31 10:11:12
delete from t2;
59 inserts;
-insert into t2 values (19700101000000+59);
-insert into t2 values (19700101000000+58);
-insert into t2 values (19700101000000+57);
-insert into t2 values (19700101000000+56);
-insert into t2 values (19700101000000+55);
-insert into t2 values (19700101000000+54);
-insert into t2 values (19700101000000+53);
-insert into t2 values (19700101000000+52);
-insert into t2 values (19700101000000+51);
-insert into t2 values (19700101000000+50);
-insert into t2 values (19700101000000+49);
-insert into t2 values (19700101000000+48);
-insert into t2 values (19700101000000+47);
-insert into t2 values (19700101000000+46);
-insert into t2 values (19700101000000+45);
-insert into t2 values (19700101000000+44);
-insert into t2 values (19700101000000+43);
-insert into t2 values (19700101000000+42);
-insert into t2 values (19700101000000+41);
-insert into t2 values (19700101000000+40);
-insert into t2 values (19700101000000+39);
-insert into t2 values (19700101000000+38);
-insert into t2 values (19700101000000+37);
-insert into t2 values (19700101000000+36);
-insert into t2 values (19700101000000+35);
-insert into t2 values (19700101000000+34);
-insert into t2 values (19700101000000+33);
-insert into t2 values (19700101000000+32);
-insert into t2 values (19700101000000+31);
-insert into t2 values (19700101000000+30);
-insert into t2 values (19700101000000+29);
-insert into t2 values (19700101000000+28);
-insert into t2 values (19700101000000+27);
-insert into t2 values (19700101000000+26);
-insert into t2 values (19700101000000+25);
-insert into t2 values (19700101000000+24);
-insert into t2 values (19700101000000+23);
-insert into t2 values (19700101000000+22);
-insert into t2 values (19700101000000+21);
-insert into t2 values (19700101000000+20);
-insert into t2 values (19700101000000+19);
-insert into t2 values (19700101000000+18);
-insert into t2 values (19700101000000+17);
-insert into t2 values (19700101000000+16);
-insert into t2 values (19700101000000+15);
-insert into t2 values (19700101000000+14);
-insert into t2 values (19700101000000+13);
-insert into t2 values (19700101000000+12);
-insert into t2 values (19700101000000+11);
-insert into t2 values (19700101000000+10);
-insert into t2 values (19700101000000+9);
-insert into t2 values (19700101000000+8);
-insert into t2 values (19700101000000+7);
-insert into t2 values (19700101000000+6);
-insert into t2 values (19700101000000+5);
-insert into t2 values (19700101000000+4);
-insert into t2 values (19700101000000+3);
-insert into t2 values (19700101000000+2);
-insert into t2 values (19700101000000+1);
select count(*) from t2;
count(*)
59
@@ -1318,18 +891,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */
12 inserts;
-insert into t3 values (adddate(19700101000000,interval 12-1 month));
-insert into t3 values (adddate(19700101000000,interval 11-1 month));
-insert into t3 values (adddate(19700101000000,interval 10-1 month));
-insert into t3 values (adddate(19700101000000,interval 9-1 month));
-insert into t3 values (adddate(19700101000000,interval 8-1 month));
-insert into t3 values (adddate(19700101000000,interval 7-1 month));
-insert into t3 values (adddate(19700101000000,interval 6-1 month));
-insert into t3 values (adddate(19700101000000,interval 5-1 month));
-insert into t3 values (adddate(19700101000000,interval 4-1 month));
-insert into t3 values (adddate(19700101000000,interval 3-1 month));
-insert into t3 values (adddate(19700101000000,interval 2-1 month));
-insert into t3 values (adddate(19700101000000,interval 1-1 month));
select count(*) from t3;
count(*)
12
@@ -1370,18 +931,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB,
PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */
12 inserts;
-insert into t4 values (adddate(19700101000000,interval 12-1 month));
-insert into t4 values (adddate(19700101000000,interval 11-1 month));
-insert into t4 values (adddate(19700101000000,interval 10-1 month));
-insert into t4 values (adddate(19700101000000,interval 9-1 month));
-insert into t4 values (adddate(19700101000000,interval 8-1 month));
-insert into t4 values (adddate(19700101000000,interval 7-1 month));
-insert into t4 values (adddate(19700101000000,interval 6-1 month));
-insert into t4 values (adddate(19700101000000,interval 5-1 month));
-insert into t4 values (adddate(19700101000000,interval 4-1 month));
-insert into t4 values (adddate(19700101000000,interval 3-1 month));
-insert into t4 values (adddate(19700101000000,interval 2-1 month));
-insert into t4 values (adddate(19700101000000,interval 1-1 month));
select count(*) from t4;
count(*)
12
=== modified file 'mysql-test/suite/parts/r/partition_datetime_myisam.result'
--- a/mysql-test/suite/parts/r/partition_datetime_myisam.result 2008-11-04 07:43:21 +0000
+++ b/mysql-test/suite/parts/r/partition_datetime_myisam.result 2009-10-28 07:52:34 +0000
@@ -60,65 +60,6 @@ a
2020-12-31 10:11:12
delete from t2;
59 inserts;
-insert into t2 values (19710101000000+59);
-insert into t2 values (19710101000000+58);
-insert into t2 values (19710101000000+57);
-insert into t2 values (19710101000000+56);
-insert into t2 values (19710101000000+55);
-insert into t2 values (19710101000000+54);
-insert into t2 values (19710101000000+53);
-insert into t2 values (19710101000000+52);
-insert into t2 values (19710101000000+51);
-insert into t2 values (19710101000000+50);
-insert into t2 values (19710101000000+49);
-insert into t2 values (19710101000000+48);
-insert into t2 values (19710101000000+47);
-insert into t2 values (19710101000000+46);
-insert into t2 values (19710101000000+45);
-insert into t2 values (19710101000000+44);
-insert into t2 values (19710101000000+43);
-insert into t2 values (19710101000000+42);
-insert into t2 values (19710101000000+41);
-insert into t2 values (19710101000000+40);
-insert into t2 values (19710101000000+39);
-insert into t2 values (19710101000000+38);
-insert into t2 values (19710101000000+37);
-insert into t2 values (19710101000000+36);
-insert into t2 values (19710101000000+35);
-insert into t2 values (19710101000000+34);
-insert into t2 values (19710101000000+33);
-insert into t2 values (19710101000000+32);
-insert into t2 values (19710101000000+31);
-insert into t2 values (19710101000000+30);
-insert into t2 values (19710101000000+29);
-insert into t2 values (19710101000000+28);
-insert into t2 values (19710101000000+27);
-insert into t2 values (19710101000000+26);
-insert into t2 values (19710101000000+25);
-insert into t2 values (19710101000000+24);
-insert into t2 values (19710101000000+23);
-insert into t2 values (19710101000000+22);
-insert into t2 values (19710101000000+21);
-insert into t2 values (19710101000000+20);
-insert into t2 values (19710101000000+19);
-insert into t2 values (19710101000000+18);
-insert into t2 values (19710101000000+17);
-insert into t2 values (19710101000000+16);
-insert into t2 values (19710101000000+15);
-insert into t2 values (19710101000000+14);
-insert into t2 values (19710101000000+13);
-insert into t2 values (19710101000000+12);
-insert into t2 values (19710101000000+11);
-insert into t2 values (19710101000000+10);
-insert into t2 values (19710101000000+9);
-insert into t2 values (19710101000000+8);
-insert into t2 values (19710101000000+7);
-insert into t2 values (19710101000000+6);
-insert into t2 values (19710101000000+5);
-insert into t2 values (19710101000000+4);
-insert into t2 values (19710101000000+3);
-insert into t2 values (19710101000000+2);
-insert into t2 values (19710101000000+1);
select count(*) from t2;
count(*)
59
@@ -206,18 +147,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM,
PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */
12 inserts;
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month));
-insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month));
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
select count(*) from t3;
@@ -260,18 +189,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM,
PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */
12 inserts;
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month));
-insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month));
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
select count(*) from t4;
@@ -354,90 +271,6 @@ a
2020-12-31
delete from t2;
28 inserts;
-insert into t2 values (19700101+28-1);
-insert into t2 values (19700201+28-1);
-insert into t2 values (19700301+28-1);
-insert into t2 values (19700101+27-1);
-insert into t2 values (19700201+27-1);
-insert into t2 values (19700301+27-1);
-insert into t2 values (19700101+26-1);
-insert into t2 values (19700201+26-1);
-insert into t2 values (19700301+26-1);
-insert into t2 values (19700101+25-1);
-insert into t2 values (19700201+25-1);
-insert into t2 values (19700301+25-1);
-insert into t2 values (19700101+24-1);
-insert into t2 values (19700201+24-1);
-insert into t2 values (19700301+24-1);
-insert into t2 values (19700101+23-1);
-insert into t2 values (19700201+23-1);
-insert into t2 values (19700301+23-1);
-insert into t2 values (19700101+22-1);
-insert into t2 values (19700201+22-1);
-insert into t2 values (19700301+22-1);
-insert into t2 values (19700101+21-1);
-insert into t2 values (19700201+21-1);
-insert into t2 values (19700301+21-1);
-insert into t2 values (19700101+20-1);
-insert into t2 values (19700201+20-1);
-insert into t2 values (19700301+20-1);
-insert into t2 values (19700101+19-1);
-insert into t2 values (19700201+19-1);
-insert into t2 values (19700301+19-1);
-insert into t2 values (19700101+18-1);
-insert into t2 values (19700201+18-1);
-insert into t2 values (19700301+18-1);
-insert into t2 values (19700101+17-1);
-insert into t2 values (19700201+17-1);
-insert into t2 values (19700301+17-1);
-insert into t2 values (19700101+16-1);
-insert into t2 values (19700201+16-1);
-insert into t2 values (19700301+16-1);
-insert into t2 values (19700101+15-1);
-insert into t2 values (19700201+15-1);
-insert into t2 values (19700301+15-1);
-insert into t2 values (19700101+14-1);
-insert into t2 values (19700201+14-1);
-insert into t2 values (19700301+14-1);
-insert into t2 values (19700101+13-1);
-insert into t2 values (19700201+13-1);
-insert into t2 values (19700301+13-1);
-insert into t2 values (19700101+12-1);
-insert into t2 values (19700201+12-1);
-insert into t2 values (19700301+12-1);
-insert into t2 values (19700101+11-1);
-insert into t2 values (19700201+11-1);
-insert into t2 values (19700301+11-1);
-insert into t2 values (19700101+10-1);
-insert into t2 values (19700201+10-1);
-insert into t2 values (19700301+10-1);
-insert into t2 values (19700101+9-1);
-insert into t2 values (19700201+9-1);
-insert into t2 values (19700301+9-1);
-insert into t2 values (19700101+8-1);
-insert into t2 values (19700201+8-1);
-insert into t2 values (19700301+8-1);
-insert into t2 values (19700101+7-1);
-insert into t2 values (19700201+7-1);
-insert into t2 values (19700301+7-1);
-insert into t2 values (19700101+6-1);
-insert into t2 values (19700201+6-1);
-insert into t2 values (19700301+6-1);
-insert into t2 values (19700101+5-1);
-insert into t2 values (19700201+5-1);
-insert into t2 values (19700301+5-1);
-insert into t2 values (19700101+4-1);
-insert into t2 values (19700201+4-1);
-insert into t2 values (19700301+4-1);
-insert into t2 values (19700101+3-1);
-insert into t2 values (19700201+3-1);
-insert into t2 values (19700301+3-1);
-insert into t2 values (19700101+2-1);
-insert into t2 values (19700201+2-1);
-insert into t2 values (19700301+2-1);
-insert into t2 values (19700101+1-1);
-insert into t2 values (19700201+1-1);
-insert into t2 values (19700301+1-1);
select count(*) from t2;
count(*)
84
@@ -550,18 +383,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM,
PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */
12 inserts;
-insert into t3 values (adddate(19700101,interval 12-1 month));
-insert into t3 values (adddate(19700101,interval 11-1 month));
-insert into t3 values (adddate(19700101,interval 10-1 month));
-insert into t3 values (adddate(19700101,interval 9-1 month));
-insert into t3 values (adddate(19700101,interval 8-1 month));
-insert into t3 values (adddate(19700101,interval 7-1 month));
-insert into t3 values (adddate(19700101,interval 6-1 month));
-insert into t3 values (adddate(19700101,interval 5-1 month));
-insert into t3 values (adddate(19700101,interval 4-1 month));
-insert into t3 values (adddate(19700101,interval 3-1 month));
-insert into t3 values (adddate(19700101,interval 2-1 month));
-insert into t3 values (adddate(19700101,interval 1-1 month));
select count(*) from t3;
count(*)
12
@@ -602,18 +423,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM,
PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */
12 inserts;
-insert into t4 values (adddate(19700101,interval 12-1 month));
-insert into t4 values (adddate(19700101,interval 11-1 month));
-insert into t4 values (adddate(19700101,interval 10-1 month));
-insert into t4 values (adddate(19700101,interval 9-1 month));
-insert into t4 values (adddate(19700101,interval 8-1 month));
-insert into t4 values (adddate(19700101,interval 7-1 month));
-insert into t4 values (adddate(19700101,interval 6-1 month));
-insert into t4 values (adddate(19700101,interval 5-1 month));
-insert into t4 values (adddate(19700101,interval 4-1 month));
-insert into t4 values (adddate(19700101,interval 3-1 month));
-insert into t4 values (adddate(19700101,interval 2-1 month));
-insert into t4 values (adddate(19700101,interval 1-1 month));
select count(*) from t4;
count(*)
12
@@ -694,65 +503,6 @@ a
14:15:16
delete from t2;
59 inserts;
-insert into t2 values (000100+59);
-insert into t2 values (000100+58);
-insert into t2 values (000100+57);
-insert into t2 values (000100+56);
-insert into t2 values (000100+55);
-insert into t2 values (000100+54);
-insert into t2 values (000100+53);
-insert into t2 values (000100+52);
-insert into t2 values (000100+51);
-insert into t2 values (000100+50);
-insert into t2 values (000100+49);
-insert into t2 values (000100+48);
-insert into t2 values (000100+47);
-insert into t2 values (000100+46);
-insert into t2 values (000100+45);
-insert into t2 values (000100+44);
-insert into t2 values (000100+43);
-insert into t2 values (000100+42);
-insert into t2 values (000100+41);
-insert into t2 values (000100+40);
-insert into t2 values (000100+39);
-insert into t2 values (000100+38);
-insert into t2 values (000100+37);
-insert into t2 values (000100+36);
-insert into t2 values (000100+35);
-insert into t2 values (000100+34);
-insert into t2 values (000100+33);
-insert into t2 values (000100+32);
-insert into t2 values (000100+31);
-insert into t2 values (000100+30);
-insert into t2 values (000100+29);
-insert into t2 values (000100+28);
-insert into t2 values (000100+27);
-insert into t2 values (000100+26);
-insert into t2 values (000100+25);
-insert into t2 values (000100+24);
-insert into t2 values (000100+23);
-insert into t2 values (000100+22);
-insert into t2 values (000100+21);
-insert into t2 values (000100+20);
-insert into t2 values (000100+19);
-insert into t2 values (000100+18);
-insert into t2 values (000100+17);
-insert into t2 values (000100+16);
-insert into t2 values (000100+15);
-insert into t2 values (000100+14);
-insert into t2 values (000100+13);
-insert into t2 values (000100+12);
-insert into t2 values (000100+11);
-insert into t2 values (000100+10);
-insert into t2 values (000100+9);
-insert into t2 values (000100+8);
-insert into t2 values (000100+7);
-insert into t2 values (000100+6);
-insert into t2 values (000100+5);
-insert into t2 values (000100+4);
-insert into t2 values (000100+3);
-insert into t2 values (000100+2);
-insert into t2 values (000100+1);
select count(*) from t2;
count(*)
59
@@ -840,65 +590,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (46) ENGINE = MyISAM,
PARTITION quarter4 VALUES LESS THAN (61) ENGINE = MyISAM) */
59 inserts;
-insert into t3 values (100000+59);
-insert into t3 values (100000+58);
-insert into t3 values (100000+57);
-insert into t3 values (100000+56);
-insert into t3 values (100000+55);
-insert into t3 values (100000+54);
-insert into t3 values (100000+53);
-insert into t3 values (100000+52);
-insert into t3 values (100000+51);
-insert into t3 values (100000+50);
-insert into t3 values (100000+49);
-insert into t3 values (100000+48);
-insert into t3 values (100000+47);
-insert into t3 values (100000+46);
-insert into t3 values (100000+45);
-insert into t3 values (100000+44);
-insert into t3 values (100000+43);
-insert into t3 values (100000+42);
-insert into t3 values (100000+41);
-insert into t3 values (100000+40);
-insert into t3 values (100000+39);
-insert into t3 values (100000+38);
-insert into t3 values (100000+37);
-insert into t3 values (100000+36);
-insert into t3 values (100000+35);
-insert into t3 values (100000+34);
-insert into t3 values (100000+33);
-insert into t3 values (100000+32);
-insert into t3 values (100000+31);
-insert into t3 values (100000+30);
-insert into t3 values (100000+29);
-insert into t3 values (100000+28);
-insert into t3 values (100000+27);
-insert into t3 values (100000+26);
-insert into t3 values (100000+25);
-insert into t3 values (100000+24);
-insert into t3 values (100000+23);
-insert into t3 values (100000+22);
-insert into t3 values (100000+21);
-insert into t3 values (100000+20);
-insert into t3 values (100000+19);
-insert into t3 values (100000+18);
-insert into t3 values (100000+17);
-insert into t3 values (100000+16);
-insert into t3 values (100000+15);
-insert into t3 values (100000+14);
-insert into t3 values (100000+13);
-insert into t3 values (100000+12);
-insert into t3 values (100000+11);
-insert into t3 values (100000+10);
-insert into t3 values (100000+9);
-insert into t3 values (100000+8);
-insert into t3 values (100000+7);
-insert into t3 values (100000+6);
-insert into t3 values (100000+5);
-insert into t3 values (100000+4);
-insert into t3 values (100000+3);
-insert into t3 values (100000+2);
-insert into t3 values (100000+1);
select count(*) from t3;
count(*)
59
@@ -986,65 +677,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) ENGINE = MyISAM,
PARTITION quarter4 VALUES IN (46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) ENGINE = MyISAM) */
59 inserts;
-insert into t4 values (100000+59);
-insert into t4 values (100000+58);
-insert into t4 values (100000+57);
-insert into t4 values (100000+56);
-insert into t4 values (100000+55);
-insert into t4 values (100000+54);
-insert into t4 values (100000+53);
-insert into t4 values (100000+52);
-insert into t4 values (100000+51);
-insert into t4 values (100000+50);
-insert into t4 values (100000+49);
-insert into t4 values (100000+48);
-insert into t4 values (100000+47);
-insert into t4 values (100000+46);
-insert into t4 values (100000+45);
-insert into t4 values (100000+44);
-insert into t4 values (100000+43);
-insert into t4 values (100000+42);
-insert into t4 values (100000+41);
-insert into t4 values (100000+40);
-insert into t4 values (100000+39);
-insert into t4 values (100000+38);
-insert into t4 values (100000+37);
-insert into t4 values (100000+36);
-insert into t4 values (100000+35);
-insert into t4 values (100000+34);
-insert into t4 values (100000+33);
-insert into t4 values (100000+32);
-insert into t4 values (100000+31);
-insert into t4 values (100000+30);
-insert into t4 values (100000+29);
-insert into t4 values (100000+28);
-insert into t4 values (100000+27);
-insert into t4 values (100000+26);
-insert into t4 values (100000+25);
-insert into t4 values (100000+24);
-insert into t4 values (100000+23);
-insert into t4 values (100000+22);
-insert into t4 values (100000+21);
-insert into t4 values (100000+20);
-insert into t4 values (100000+19);
-insert into t4 values (100000+18);
-insert into t4 values (100000+17);
-insert into t4 values (100000+16);
-insert into t4 values (100000+15);
-insert into t4 values (100000+14);
-insert into t4 values (100000+13);
-insert into t4 values (100000+12);
-insert into t4 values (100000+11);
-insert into t4 values (100000+10);
-insert into t4 values (100000+9);
-insert into t4 values (100000+8);
-insert into t4 values (100000+7);
-insert into t4 values (100000+6);
-insert into t4 values (100000+5);
-insert into t4 values (100000+4);
-insert into t4 values (100000+3);
-insert into t4 values (100000+2);
-insert into t4 values (100000+1);
select count(*) from t4;
count(*)
59
@@ -1172,65 +804,6 @@ a
2020-12-31 10:11:12
delete from t2;
59 inserts;
-insert into t2 values (19700101000000+59);
-insert into t2 values (19700101000000+58);
-insert into t2 values (19700101000000+57);
-insert into t2 values (19700101000000+56);
-insert into t2 values (19700101000000+55);
-insert into t2 values (19700101000000+54);
-insert into t2 values (19700101000000+53);
-insert into t2 values (19700101000000+52);
-insert into t2 values (19700101000000+51);
-insert into t2 values (19700101000000+50);
-insert into t2 values (19700101000000+49);
-insert into t2 values (19700101000000+48);
-insert into t2 values (19700101000000+47);
-insert into t2 values (19700101000000+46);
-insert into t2 values (19700101000000+45);
-insert into t2 values (19700101000000+44);
-insert into t2 values (19700101000000+43);
-insert into t2 values (19700101000000+42);
-insert into t2 values (19700101000000+41);
-insert into t2 values (19700101000000+40);
-insert into t2 values (19700101000000+39);
-insert into t2 values (19700101000000+38);
-insert into t2 values (19700101000000+37);
-insert into t2 values (19700101000000+36);
-insert into t2 values (19700101000000+35);
-insert into t2 values (19700101000000+34);
-insert into t2 values (19700101000000+33);
-insert into t2 values (19700101000000+32);
-insert into t2 values (19700101000000+31);
-insert into t2 values (19700101000000+30);
-insert into t2 values (19700101000000+29);
-insert into t2 values (19700101000000+28);
-insert into t2 values (19700101000000+27);
-insert into t2 values (19700101000000+26);
-insert into t2 values (19700101000000+25);
-insert into t2 values (19700101000000+24);
-insert into t2 values (19700101000000+23);
-insert into t2 values (19700101000000+22);
-insert into t2 values (19700101000000+21);
-insert into t2 values (19700101000000+20);
-insert into t2 values (19700101000000+19);
-insert into t2 values (19700101000000+18);
-insert into t2 values (19700101000000+17);
-insert into t2 values (19700101000000+16);
-insert into t2 values (19700101000000+15);
-insert into t2 values (19700101000000+14);
-insert into t2 values (19700101000000+13);
-insert into t2 values (19700101000000+12);
-insert into t2 values (19700101000000+11);
-insert into t2 values (19700101000000+10);
-insert into t2 values (19700101000000+9);
-insert into t2 values (19700101000000+8);
-insert into t2 values (19700101000000+7);
-insert into t2 values (19700101000000+6);
-insert into t2 values (19700101000000+5);
-insert into t2 values (19700101000000+4);
-insert into t2 values (19700101000000+3);
-insert into t2 values (19700101000000+2);
-insert into t2 values (19700101000000+1);
select count(*) from t2;
count(*)
59
@@ -1318,18 +891,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM,
PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */
12 inserts;
-insert into t3 values (adddate(19700101000000,interval 12-1 month));
-insert into t3 values (adddate(19700101000000,interval 11-1 month));
-insert into t3 values (adddate(19700101000000,interval 10-1 month));
-insert into t3 values (adddate(19700101000000,interval 9-1 month));
-insert into t3 values (adddate(19700101000000,interval 8-1 month));
-insert into t3 values (adddate(19700101000000,interval 7-1 month));
-insert into t3 values (adddate(19700101000000,interval 6-1 month));
-insert into t3 values (adddate(19700101000000,interval 5-1 month));
-insert into t3 values (adddate(19700101000000,interval 4-1 month));
-insert into t3 values (adddate(19700101000000,interval 3-1 month));
-insert into t3 values (adddate(19700101000000,interval 2-1 month));
-insert into t3 values (adddate(19700101000000,interval 1-1 month));
select count(*) from t3;
count(*)
12
@@ -1370,18 +931,6 @@ SUBPARTITIONS 3
PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM,
PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */
12 inserts;
-insert into t4 values (adddate(19700101000000,interval 12-1 month));
-insert into t4 values (adddate(19700101000000,interval 11-1 month));
-insert into t4 values (adddate(19700101000000,interval 10-1 month));
-insert into t4 values (adddate(19700101000000,interval 9-1 month));
-insert into t4 values (adddate(19700101000000,interval 8-1 month));
-insert into t4 values (adddate(19700101000000,interval 7-1 month));
-insert into t4 values (adddate(19700101000000,interval 6-1 month));
-insert into t4 values (adddate(19700101000000,interval 5-1 month));
-insert into t4 values (adddate(19700101000000,interval 4-1 month));
-insert into t4 values (adddate(19700101000000,interval 3-1 month));
-insert into t4 values (adddate(19700101000000,interval 2-1 month));
-insert into t4 values (adddate(19700101000000,interval 1-1 month));
select count(*) from t4;
count(*)
12
=== modified file 'mysql-test/suite/parts/t/part_supported_sql_func_innodb.test'
--- a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test 2007-11-20 15:04:07 +0000
+++ b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test 2009-10-28 08:08:54 +0000
@@ -25,6 +25,8 @@
let $debug= 0;
let $do_long_tests= 1;
+#
+--source include/big_test.inc
# The server must support partitioning.
--source include/have_partition.inc
=== modified file 'mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test'
--- a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test 2009-10-09 13:08:09 +0000
+++ b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test 2009-10-28 08:08:54 +0000
@@ -43,6 +43,8 @@ SET @max_row = 20;
let $more_trigger_tests= 0;
let $more_pk_ui_tests= 0;
+# Slow running test
+--source include/big_test.inc
# This test relies on connecting externally from mysqltest, doesn't
# work with embedded.
--source include/not_embedded.inc
=== modified file 'mysql-test/suite/parts/t/partition_alter4_myisam.test'
--- a/mysql-test/suite/parts/t/partition_alter4_myisam.test 2009-10-09 13:08:09 +0000
+++ b/mysql-test/suite/parts/t/partition_alter4_myisam.test 2009-10-28 08:08:54 +0000
@@ -40,6 +40,8 @@ SET @max_row = 20;
let $more_trigger_tests= 0;
let $more_pk_ui_tests= 0;
+# Slow running test
+--source include/big_test.inc
# This test relies on connecting externally from mysqltest, doesn't
# work with embedded.
--source include/not_embedded.inc
=== added file 'mysql-test/suite/pbxt/my.cnf'
--- a/mysql-test/suite/pbxt/my.cnf 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/pbxt/my.cnf 2009-10-26 11:35:42 +0000
@@ -0,0 +1,9 @@
+# Use default setting for mysqld processes
+!include include/default_mysqld.cnf
+
+[mysqld.1]
+default-storage-engine=pbxt
+
+[ENV]
+MASTER_MYSOCK= @mysqld.1.socket
+MASTER_MYPORT= @mysqld.1.port
=== modified file 'mysql-test/suite/pbxt/t/count_distinct3.test'
--- a/mysql-test/suite/pbxt/t/count_distinct3.test 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/t/count_distinct3.test 2009-10-26 11:35:42 +0000
@@ -11,6 +11,7 @@ CREATE TABLE t1 (id INTEGER, grp TINYINT
--disable_query_log
SET @rnd_max= 2147483647;
+begin;
let $1 = 1000;
while ($1)
{
@@ -21,6 +22,7 @@ while ($1)
INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
dec $1;
}
+commit;
set @@read_buffer_size=2*1024*1024;
CREATE TABLE t2 SELECT * FROM t1;
INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
=== modified file 'mysql-test/suite/pbxt/t/subselect.test'
--- a/mysql-test/suite/pbxt/t/subselect.test 2009-04-02 10:03:14 +0000
+++ b/mysql-test/suite/pbxt/t/subselect.test 2009-10-26 11:35:42 +0000
@@ -814,12 +814,14 @@ create table t3 (a int, b int, index a (
insert into t1 values (1,10), (2,20), (3,30), (4,40);
disable_query_log;
# making table large enough
+begin;
let $1 = 10000;
while ($1)
{
eval insert into t1 values (rand()*100000+200,rand()*100000);
dec $1;
}
+commit;
enable_query_log;
insert into t2 values (2), (3), (4), (5);
insert into t3 values (10,3), (20,4), (30,5);
@@ -2557,6 +2559,7 @@ CREATE TABLE t2 (x int auto_increment, y
PRIMARY KEY (x), FOREIGN KEY (y) REFERENCES t1 (b));
disable_query_log;
+begin;
let $1=3000;
while ($1)
{
@@ -2570,6 +2573,7 @@ while ($1)
}
dec $1;
}
+commit;
enable_query_log;
SET SESSION sort_buffer_size = 32 * 1024;
@@ -3156,11 +3160,13 @@ insert into t1 values(1,1),(2,2), (3, 3)
let $i=10000;
--disable_query_log
--disable_warnings
+begin;
while ($i)
{
eval insert into t2 values (-1 , $i/5000 + 1, '$i');
dec $i;
}
+commit;
--enable_warnings
--enable_query_log
set session sort_buffer_size= 33*1024;
=== modified file 'mysql-test/t/almost_full.test'
--- a/mysql-test/t/almost_full.test 2007-11-12 09:00:22 +0000
+++ b/mysql-test/t/almost_full.test 2009-10-28 07:52:34 +0000
@@ -11,11 +11,13 @@ CREATE TABLE t1 (a int auto_increment pr
--disable_query_log
let $1= 303;
+begin;
while ($1)
{
INSERT INTO t1 SET b=repeat('a',200);
dec $1;
}
+commit;
--enable_query_log
DELETE FROM t1 WHERE a=1 or a=5;
=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test 2009-06-07 10:05:19 +0000
+++ b/mysql-test/t/alter_table.test 2009-10-28 07:52:34 +0000
@@ -121,11 +121,15 @@ alter table t1 disable keys;
show keys from t1;
#let $1=10000;
let $1=10;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values($1,RAND()*1000,RAND()*1000,RAND());
dec $1;
}
+commit;
+--enable_query_log
alter table t1 enable keys;
show keys from t1;
drop table t1;
@@ -144,11 +148,15 @@ drop table t1;
create table t1 (a int, b int);
let $1=100;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values(1,$1), (2,$1), (3, $1);
dec $1;
}
+commit;
+--enable_query_log
alter table t1 add unique (a,b), add key (b);
show keys from t1;
analyze table t1;
@@ -966,12 +974,14 @@ DROP TABLE t1;
create table t1(f1 int not null, f2 int not null, key (f1), key (f2));
let $count= 50;
--disable_query_log
+begin;
while ($count)
{
EVAL insert into t1 values (1,1),(1,1),(1,1),(1,1),(1,1);
EVAL insert into t1 values (2,2),(2,2),(2,2),(2,2),(2,2);
dec $count ;
}
+commit;
--enable_query_log
select index_length into @unpaked_keys_size from
=== modified file 'mysql-test/t/archive.test'
--- a/mysql-test/t/archive.test 2009-03-26 14:27:34 +0000
+++ b/mysql-test/t/archive.test 2009-10-28 07:52:34 +0000
@@ -1576,11 +1576,13 @@ CREATE TABLE t1(a VARCHAR(510)) ENGINE =
let $bug31036=41;
--disable_query_log
+begin;
while($bug31036)
{
INSERT INTO t1(a) VALUES (REPEAT('a', 510));
dec $bug31036;
}
+commit;
--enable_query_log
INSERT INTO t1(a) VALUES ('');
=== modified file 'mysql-test/t/bench_count_distinct.test'
--- a/mysql-test/t/bench_count_distinct.test 2005-07-28 00:22:47 +0000
+++ b/mysql-test/t/bench_count_distinct.test 2009-10-28 07:52:34 +0000
@@ -7,14 +7,16 @@ drop table if exists t1;
--enable_warnings
create table t1(n int not null, key(n)) delay_key_write = 1;
let $1=100;
-disable_query_log;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values($1);
eval insert into t1 values($1);
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
select count(distinct n) from t1;
explain extended select count(distinct n) from t1;
drop table t1;
=== modified file 'mysql-test/t/change_user.test'
--- a/mysql-test/t/change_user.test 2009-02-12 14:08:56 +0000
+++ b/mysql-test/t/change_user.test 2009-10-28 07:52:34 +0000
@@ -57,13 +57,13 @@ FLUSH STATUS;
--disable_query_log
let $i = 100;
-
+begin;
while ($i)
{
dec $i;
-
SELECT 1;
}
+commit;
--enable_query_log
--enable_result_log
=== modified file 'mysql-test/t/check.test'
--- a/mysql-test/t/check.test 2009-02-09 21:00:15 +0000
+++ b/mysql-test/t/check.test 2009-10-28 07:52:34 +0000
@@ -12,13 +12,15 @@ drop view if exists v1;
# Add a lot of keys to slow down check
create table t1(n int not null, key(n), key(n), key(n), key(n));
let $1=10000;
-disable_query_log;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values ($1);
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
send check table t1 extended;
connection con2;
insert into t1 values (200000);
=== modified file 'mysql-test/t/count_distinct2.test'
--- a/mysql-test/t/count_distinct2.test 2005-07-28 14:09:54 +0000
+++ b/mysql-test/t/count_distinct2.test 2009-10-28 07:52:34 +0000
@@ -51,13 +51,15 @@ drop table t1;
# test the conversion from tree to MyISAM
create table t1 (n int default NULL);
let $1=5000;
-disable_query_log;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values($1);
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
flush status;
select count(distinct n) from t1;
@@ -67,13 +69,15 @@ drop table t1;
# Test use of MyISAM tmp tables
create table t1 (s text);
let $1=5000;
-disable_query_log;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values('$1');
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
flush status;
select count(distinct s) from t1;
show status like 'Created_tmp_disk_tables';
=== modified file 'mysql-test/t/count_distinct3.test'
--- a/mysql-test/t/count_distinct3.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/count_distinct3.test 2009-10-28 07:52:34 +0000
@@ -14,6 +14,7 @@ CREATE TABLE t1 (id INTEGER, grp TINYINT
--disable_query_log
SET @rnd_max= 2147483647;
let $1 = 1000;
+begin;
while ($1)
{
SET @rnd= RAND();
@@ -23,7 +24,7 @@ while ($1)
INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
dec $1;
}
-
+commit;
# We increase the size of t1 here.
SET @orig_myisam_sort_buffer_size = @@session.myisam_sort_buffer_size;
SET session myisam_sort_buffer_size=20000000;
=== modified file 'mysql-test/t/ctype_euckr.test'
--- a/mysql-test/t/ctype_euckr.test 2009-07-24 06:27:23 +0000
+++ b/mysql-test/t/ctype_euckr.test 2009-10-28 07:52:34 +0000
@@ -77,11 +77,13 @@ DROP TABLE t1;
CREATE TABLE t1 (a binary(1), key(a));
--disable_query_log
let $1=255;
+begin;
while($1)
{
eval INSERT INTO t1 VALUES (unhex(hex($1)));
dec $1;
}
+commit;
--enable_query_log
CREATE TABLE t2 (s VARCHAR(4), a VARCHAR(1) CHARACTER SET euckr);
=== modified file 'mysql-test/t/derived.test'
--- a/mysql-test/t/derived.test 2009-07-11 18:44:29 +0000
+++ b/mysql-test/t/derived.test 2009-10-28 07:52:34 +0000
@@ -45,14 +45,16 @@ select * from (select * from t1 where t1
explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
drop table t1, t2;
create table t1(a int not null, t char(8), index(a));
-disable_query_log;
+--disable_query_log
+begin;
let $1 = 10000;
while ($1)
{
eval insert into t1 values ($1,'$1');
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
explain select count(*) from t1 as tt1, (select * from t1) as tt2;
drop table t1;
=== modified file 'mysql-test/t/events_time_zone.test'
--- a/mysql-test/t/events_time_zone.test 2009-10-06 18:15:09 +0000
+++ b/mysql-test/t/events_time_zone.test 2009-10-28 07:52:34 +0000
@@ -118,6 +118,7 @@ INSERT INTO mysql.time_zone_transition_t
let $transition_unix_time= `SELECT @unix_time`;
let $count= 30;
--disable_query_log
+begin;
while ($count)
{
eval INSERT INTO mysql.time_zone_transition
@@ -126,6 +127,7 @@ while ($count)
let $transition_unix_time= `SELECT $transition_unix_time + @step3`;
dec $count;
}
+commit;
--enable_query_log
let $tz_name = `SELECT CONCAT('b16420_a',UNIX_TIMESTAMP())`;
--replace_result $tz_name <TZ_NAME_1>
=== modified file 'mysql-test/t/fulltext2.test'
--- a/mysql-test/t/fulltext2.test 2007-07-06 18:39:55 +0000
+++ b/mysql-test/t/fulltext2.test 2009-10-28 07:52:34 +0000
@@ -18,6 +18,7 @@ CREATE TABLE t1 (
# two-level entry, second-level tree with depth 2
--disable_query_log
+begin;
let $1=260;
while ($1)
{
@@ -40,6 +41,7 @@ while ($1)
eval insert t1 (a) values ('aaayyy');
dec $1;
}
+commit;
--enable_query_log
# converting to two-level
@@ -113,6 +115,7 @@ CREATE TABLE t1 (
# two-level entry, second-level tree with depth 2
--disable_query_log
let $1=260;
+begin;
while ($1)
{
eval insert t1 (a) values ('aaaxxx');
@@ -130,6 +133,7 @@ while ($1)
eval insert t1 (a) values ('aaayyy');
dec $1;
}
+commit;
--enable_query_log
select count(*) from t1 where match a against ('aaaxxx');
=== modified file 'mysql-test/t/func_misc.test'
--- a/mysql-test/t/func_misc.test 2009-06-11 16:21:32 +0000
+++ b/mysql-test/t/func_misc.test 2009-10-28 07:52:34 +0000
@@ -213,11 +213,15 @@ start_ts DATETIME, end_ts DATETIME,
start_cached INTEGER, end_cached INTEGER);
CREATE TABLE t1 (f1 BIGINT);
let $num = `SELECT @row_count`;
+--disable_query_log
+begin;
while ($num)
{
INSERT INTO t1 VALUES (1);
dec $num;
}
+commit;
+--enable_query_log
let $loops = 4;
let $num = $loops;
=== modified file 'mysql-test/t/gis-rtree.test'
--- a/mysql-test/t/gis-rtree.test 2009-07-10 23:12:13 +0000
+++ b/mysql-test/t/gis-rtree.test 2009-10-28 07:52:34 +0000
@@ -17,12 +17,16 @@ SHOW CREATE TABLE t1;
let $1=150;
let $2=150;
+--disable_query_log
+begin;
while ($1)
{
eval INSERT INTO t1 (g) VALUES (GeomFromText('LineString($1 $1, $2 $2)'));
dec $1;
inc $2;
}
+commit;
+--enable_query_log
SELECT count(*) FROM t1;
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
@@ -35,6 +39,8 @@ CREATE TABLE t2 (
g GEOMETRY NOT NULL
) ENGINE=MyISAM;
+--disable_query_log
+begin;
let $1=10;
while ($1)
{
@@ -46,6 +52,8 @@ while ($1)
}
dec $1;
}
+commit;
+--enable_query_log
ALTER TABLE t2 ADD SPATIAL KEY(g);
SHOW CREATE TABLE t2;
@@ -55,6 +63,8 @@ EXPLAIN SELECT fid, AsText(g) FROM t2 WH
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
+--disable_query_log
+begin;
let $1=10;
while ($1)
{
@@ -67,6 +77,8 @@ while ($1)
}
dec $1;
}
+commit;
+--enable_query_log
DROP TABLE t2;
=== modified file 'mysql-test/t/heap.test'
--- a/mysql-test/t/heap.test 2007-06-06 17:57:07 +0000
+++ b/mysql-test/t/heap.test 2009-10-28 07:52:34 +0000
@@ -234,7 +234,8 @@ drop table t1,t2,t3;
#
create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
show create table t1;
-disable_query_log;
+--disable_query_log
+begin;
let $1=10;
while ($1)
{
@@ -248,7 +249,9 @@ while ($1)
}
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
+
select count(*) from t1;
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
@@ -318,7 +321,8 @@ drop table t1;
create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10)));
show create table t1;
-disable_query_log;
+--disable_query_log
+begin;
let $1=10;
while ($1)
{
@@ -332,7 +336,8 @@ while ($1)
}
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
select count(*) from t1;
insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
select count(*) from t1 where v='a';
=== modified file 'mysql-test/t/innodb_xtradb_bug317074.test'
--- a/mysql-test/t/innodb_xtradb_bug317074.test 2009-09-18 19:27:04 +0000
+++ b/mysql-test/t/innodb_xtradb_bug317074.test 2009-10-28 07:52:34 +0000
@@ -1,4 +1,3 @@
---source include/big_test.inc
--source include/have_innodb.inc
SET @old_innodb_file_format=@@innodb_file_format;
@@ -7,16 +6,16 @@ SET @old_innodb_file_format_check=@@inno
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;
--- disable_query_log
--- disable_result_log
-
+--disable_warnings
DROP TABLE IF EXISTS `test1`;
+--enable_warnings
CREATE TABLE IF NOT EXISTS `test1` (
`a` int primary key auto_increment,
`b` int default 0,
`c` char(100) default 'testtest'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
+set autocommit=0;
delimiter |;
CREATE PROCEDURE insert_many(p1 int)
BEGIN
@@ -26,14 +25,18 @@ REPEAT
insert into test1 set b=1;
SET @x = @x + 1;
SET @y = @y + 1;
- IF @y >= 100 THEN
+ IF @y >= 1000 THEN
commit;
SET @y = 0;
END IF;
UNTIL @x >= p1 END REPEAT;
END|
delimiter ;|
+--disable_query_log
+--disable_result_log
call insert_many(100000);
+--enable_query_log
+--enable_result_log
DROP PROCEDURE insert_many;
# The bug is hangup at the following statement
=== modified file 'mysql-test/t/insert.test'
--- a/mysql-test/t/insert.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/insert.test 2009-10-28 07:52:34 +0000
@@ -151,7 +151,8 @@ drop table t1;
create table t1(id1 int not null auto_increment primary key, t char(12));
create table t2(id2 int not null, t char(12));
create table t3(id3 int not null, t char(12), index(id3));
-disable_query_log;
+--disable_query_log
+begin;
let $1 = 100;
while ($1)
{
@@ -170,7 +171,9 @@ while ($1)
}
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
+
select count(*) from t2;
insert into t2 select t1.* from t1, t2 t, t3 where t1.id1 = t.id2 and t.id2 = t3.id3;
select count(*) from t2;
=== modified file 'mysql-test/t/kill.test'
--- a/mysql-test/t/kill.test 2008-03-13 17:54:29 +0000
+++ b/mysql-test/t/kill.test 2009-10-28 07:52:34 +0000
@@ -67,12 +67,14 @@ connection conn1;
-- disable_result_log
-- disable_query_log
+begin;
let $1 = 4096;
while ($1)
{
eval insert into t1 values ($1);
dec $1;
}
+commit;
-- enable_query_log
-- enable_result_log
@@ -265,6 +267,8 @@ connection con1;
let $ID= `select connection_id()`;
let $tab_count= 40;
+--disable_query_log
+begin;
let $i= $tab_count;
while ($i)
{
@@ -272,6 +276,8 @@ while ($i)
eval INSERT INTO t$i VALUES (1),(2),(3),(4),(5),(6),(7);
dec $i ;
}
+commit;
+--enable_query_log
set session optimizer_search_depth=0;
let $i=$tab_count;
=== modified file 'mysql-test/t/merge.test'
--- a/mysql-test/t/merge.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/merge.test 2009-10-28 07:52:34 +0000
@@ -1274,6 +1274,8 @@ DROP TABLE t1, t2, t3;
CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER);
SET @rnd_max= 2147483647;
let $1 = 10;
+--disable_query_log
+begin;
while ($1)
{
SET @rnd= RAND();
@@ -1283,6 +1285,8 @@ while ($1)
INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
dec $1;
}
+commit;
+--enable_query_log
set @@read_buffer_size=2*1024*1024;
CREATE TABLE t2 SELECT * FROM t1;
INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
=== modified file 'mysql-test/t/multi_update.test'
--- a/mysql-test/t/multi_update.test 2009-02-09 21:00:15 +0000
+++ b/mysql-test/t/multi_update.test 2009-10-28 07:52:34 +0000
@@ -20,7 +20,8 @@ delete from mysql.user where user=_binar
create table t1(id1 int not null auto_increment primary key, t char(12));
create table t2(id2 int not null, t char(12));
create table t3(id3 int not null, t char(12), index(id3));
-disable_query_log;
+--disable_query_log
+begin;
let $1 = 100;
while ($1)
{
@@ -39,7 +40,8 @@ while ($1)
}
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
select count(*) from t1 where id1 > 95;
select count(*) from t2 where id2 > 95;
@@ -75,7 +77,8 @@ drop table t1,t2,t3;
create table t1(id1 int not null primary key, t varchar(100)) pack_keys = 1;
create table t2(id2 int not null, t varchar(100), index(id2)) pack_keys = 1;
-disable_query_log;
+--disable_query_log
+begin;
let $1 = 1000;
while ($1)
{
@@ -88,7 +91,8 @@ while ($1)
}
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
delete t1 from t1,t2 where t1.id1 = t2.id2 and t1.id1 > 500;
drop table t1,t2;
=== modified file 'mysql-test/t/multi_update2.test'
--- a/mysql-test/t/multi_update2.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/multi_update2.test 2009-10-28 07:52:34 +0000
@@ -48,13 +48,14 @@ CREATE TABLE t1 ( a INT NOT NULL, b INT
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4);
let $1=19;
set @d=4;
+begin;
while ($1)
{
eval INSERT INTO t1 SELECT a+@d,b+@d FROM t1;
eval SET @d=@d*2;
dec $1;
}
-
+commit;
--enable_query_log
ALTER TABLE t1 ADD INDEX i1(a);
DELETE FROM t1 WHERE a > 2000000;
=== modified file 'mysql-test/t/myisam.test'
--- a/mysql-test/t/myisam.test 2009-09-18 01:04:43 +0000
+++ b/mysql-test/t/myisam.test 2009-10-28 07:52:34 +0000
@@ -33,7 +33,8 @@ drop table t1;
create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a));
let $1=100;
-disable_query_log;
+--disable_query_log
+begin;
--disable_warnings
SET SQL_WARNINGS=0;
while ($1)
@@ -41,9 +42,10 @@ while ($1)
eval insert into t1 (b) values(repeat(char(65+$1),65550-$1));
dec $1;
}
+commit;
SET SQL_WARNINGS=1;
--enable_warnings
-enable_query_log;
+--enable_query_log
check table t1;
repair table t1;
delete from t1 where (a & 1);
@@ -380,14 +382,16 @@ check table t1;
# check updating with keys
#
-disable_query_log;
+--disable_query_log
+begin;
let $1 = 100;
while ($1)
{
eval insert into t1 (b) values (repeat(char(($1 & 32)+65), $1));
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
update t1 set b=repeat(left(b,1),255) where a between 1 and 5;
update t1 set b=repeat(left(b,1),10) where a between 32 and 43;
update t1 set b=repeat(left(b,1),2) where a between 64 and 66;
@@ -551,11 +555,13 @@ create table t2 (a int);
let $i=1000;
set @@rand_seed1=31415926,@@rand_seed2=2718281828;
--disable_query_log
+begin;
while ($i)
{
dec $i;
insert t2 values (rand()*100000);
}
+commit;
--enable_query_log
insert t1 select * from t2;
show keys from t1;
@@ -1360,11 +1366,13 @@ CREATE TABLE t1 (
--disable_query_log
let $count= 100;
--echo # Insert $count rows. Query log disabled.
+begin;
while ($count)
{
INSERT INTO t1 VALUES ('a', 'b');
dec $count;
}
+commit;
--enable_query_log
#
# Change most of the rows into long character values with > 127 characters.
@@ -1444,11 +1452,13 @@ CREATE TABLE t1 (
--disable_query_log
let $count= 100;
--echo # Insert $count rows. Query log disabled.
+begin;
while ($count)
{
INSERT INTO t1 VALUES ('a', 'b');
dec $count;
}
+commit;
--enable_query_log
#
# Change most of the rows into long character values with > 42 characters.
=== modified file 'mysql-test/t/myisam_debug.test'
--- a/mysql-test/t/myisam_debug.test 2009-05-04 09:05:16 +0000
+++ b/mysql-test/t/myisam_debug.test 2009-10-28 07:52:34 +0000
@@ -24,11 +24,15 @@ CREATE TABLE `t2` (
INSERT INTO t2 (id) VALUES (123);
let $i = 10;
+--disable_query_log
+begin;
while ($i)
{
INSERT INTO t2 (id) SELECT id FROM t2;
dec $i;
}
+commit;
+--enable_query_log
--echo # Switch to insert Connection
CONNECTION insertConn;
=== modified file 'mysql-test/t/myisampack.test'
--- a/mysql-test/t/myisampack.test 2009-04-07 11:36:15 +0000
+++ b/mysql-test/t/myisampack.test 2009-10-28 07:52:34 +0000
@@ -69,11 +69,13 @@ CREATE TABLE t1(f1 VARCHAR(200), f2 TEX
INSERT INTO t1 VALUES ('foo', 'foo1'), ('bar', 'bar1');
let $i=9;
--disable_query_log
+begin;
while ($i)
{
INSERT INTO t1 SELECT * FROM t1;
dec $i;
}
+commit;
--enable_query_log
FLUSH TABLE t1;
--echo # Compress the table using MYISAMPACK tool
=== modified file 'mysql-test/t/order_by.test'
--- a/mysql-test/t/order_by.test 2009-08-07 11:51:40 +0000
+++ b/mysql-test/t/order_by.test 2009-10-28 07:52:34 +0000
@@ -374,14 +374,16 @@ DROP TABLE t1;
#
create table t1(id int not null auto_increment primary key, t char(12));
-disable_query_log;
+--disable_query_log
+begin;
let $1 = 1000;
while ($1)
{
eval insert into t1(t) values ('$1');
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
explain select id,t from t1 order by id;
explain select id,t from t1 force index (primary) order by id;
drop table t1;
=== modified file 'mysql-test/t/order_fill_sortbuf.test'
--- a/mysql-test/t/order_fill_sortbuf.test 2005-07-28 00:22:47 +0000
+++ b/mysql-test/t/order_fill_sortbuf.test 2009-10-28 07:52:34 +0000
@@ -12,13 +12,15 @@ CREATE TABLE `t1` (
`id2` int(11) NOT NULL default '0',
`id3` int(11) NOT NULL default '0');
let $1=4000;
-disable_query_log;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 (id,id2,id3) values ($1,$1,$1);
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
create table t2 select id2 from t1 order by id3;
select count(*) from t2;
drop table t1,t2;
=== modified file 'mysql-test/t/partition.test'
--- a/mysql-test/t/partition.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/partition.test 2009-10-28 07:52:34 +0000
@@ -1680,6 +1680,7 @@ create table t1
insert into t1 values (null,null);
--disable_query_log
+begin;
let $cnt= 1000;
while ($cnt)
{
@@ -1687,6 +1688,7 @@ while ($cnt)
update t1 set s2 = 2;
dec $cnt;
}
+commit;
--enable_query_log
drop table t1;
@@ -1804,11 +1806,13 @@ CREATE TABLE t1(id MEDIUMINT NOT NULL AU
PARTITION pa11 values less than MAXVALUE);
--disable_query_log
let $n= 15;
+begin;
while ($n)
{
insert into t1 (user) values ('mysql');
dec $n;
}
+commit;
--enable_query_log
show create table t1;
drop table t1;
=== modified file 'mysql-test/t/partition_archive.test'
--- a/mysql-test/t/partition_archive.test 2007-12-06 18:17:42 +0000
+++ b/mysql-test/t/partition_archive.test 2009-10-28 07:52:34 +0000
@@ -94,11 +94,13 @@ CREATE TABLE t1(id MEDIUMINT NOT NULL AU
--disable_query_log
let $n= 100;
+begin;
while ($n)
{
insert into t1 (f1) values (repeat('a',25));
dec $n;
}
+commit;
--enable_query_log
show create table t1;
=== modified file 'mysql-test/t/select_found.test'
--- a/mysql-test/t/select_found.test 2005-07-28 00:22:47 +0000
+++ b/mysql-test/t/select_found.test 2009-10-28 07:52:34 +0000
@@ -54,7 +54,8 @@ CREATE TABLE t2 (
UNIQUE KEY e_n (email,name)
);
-disable_query_log;
+--disable_query_log
+begin;
let $1=200;
let $2=0;
while ($1)
@@ -63,7 +64,8 @@ while ($1)
eval INSERT INTO t2 VALUES ($2,'name$2','email$2');
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
EXPLAIN SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
=== modified file 'mysql-test/t/sp-big.test'
--- a/mysql-test/t/sp-big.test 2005-12-07 14:01:17 +0000
+++ b/mysql-test/t/sp-big.test 2009-10-28 07:52:34 +0000
@@ -43,11 +43,13 @@ create table t2 like t1;
let $1=8;
--disable_query_log
--disable_result_log
+begin;
while ($1)
{
eval insert into t1 select * from t1;
dec $1;
}
+commit;
--enable_result_log
--enable_query_log
select count(*) from t1;
=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/subselect.test 2009-10-28 07:52:34 +0000
@@ -811,7 +811,8 @@ create table t1 (a int, b int, index a (
create table t2 (a int, index a (a));
create table t3 (a int, b int, index a (a));
insert into t1 values (1,10), (2,20), (3,30), (4,40);
-disable_query_log;
+--disable_query_log
+begin;
# making table large enough
let $1 = 10000;
while ($1)
@@ -819,7 +820,8 @@ while ($1)
eval insert into t1 values (rand()*100000+200,rand()*100000);
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
insert into t2 values (2), (3), (4), (5);
insert into t3 values (10,3), (20,4), (30,5);
select * from t2 where t2.a in (select a from t1);
@@ -2607,7 +2609,8 @@ CREATE TABLE t1 (a int, b int auto_incre
CREATE TABLE t2 (x int auto_increment, y int, z int,
PRIMARY KEY (x), FOREIGN KEY (y) REFERENCES t1 (b));
-disable_query_log;
+--disable_query_log
+begin;
let $1=3000;
while ($1)
{
@@ -2621,7 +2624,8 @@ while ($1)
}
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
SET SESSION sort_buffer_size = 32 * 1024;
SELECT SQL_NO_CACHE COUNT(*)
@@ -3222,11 +3226,13 @@ insert into t1 values(1,1),(2,2), (3, 3)
let $i=10000;
--disable_query_log
--disable_warnings
+begin;
while ($i)
{
eval insert into t2 values (-1 , $i/5000 + 1, '$i');
dec $i;
}
+commit;
--enable_warnings
--enable_query_log
set session sort_buffer_size= 33*1024;
=== modified file 'mysql-test/t/warnings.test'
--- a/mysql-test/t/warnings.test 2009-07-06 06:55:53 +0000
+++ b/mysql-test/t/warnings.test 2009-10-28 07:52:34 +0000
@@ -82,13 +82,15 @@ drop table t1, t2;
create table t1(a char(10));
let $1=50;
-disable_query_log;
+--disable_query_log
+begin;
while ($1)
{
eval insert into t1 values('mysql ab');
dec $1;
}
-enable_query_log;
+commit;
+--enable_query_log
alter table t1 add b char;
set max_error_count=10;
update t1 set b=a;
=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp 2009-09-15 10:46:35 +0000
+++ b/mysql-test/valgrind.supp 2009-10-30 18:50:56 +0000
@@ -880,3 +880,17 @@
fun:nptl_pthread_exit_hack_handler
fun:start_thread
}
+
+#
+# Problem with glibc and gethostbyaddr_r
+#
+
+{
+ libc_res_nsend: Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ fun: __libc_res_nsend
+ fun: __libc_res_nquery
+ obj: /lib64/libnss_dns-*so)
+ obj: /lib64/libnss_dns-*so)
+ fun: gethostbyaddr_r
+}
=== modified file 'mysys/errors.c'
--- a/mysys/errors.c 2009-04-01 09:34:52 +0000
+++ b/mysys/errors.c 2009-10-26 11:35:42 +0000
@@ -50,7 +50,8 @@ const char * NEAR globerrs[GLOBERRS]=
"Collation '%s' is not a compiled collation and is not specified in the '%s' file",
"File '%s' not found (Errcode: %d)",
"File '%s' (fileno: %d) was not closed",
- "Can't change mode for file '%s' to 0x%lx (Error: %d)"
+ "Can't change mode for file '%s' to 0x%lx (Error: %d)",
+ "Warning: Can't copy ownership for file '%s' (Error: %d)"
};
void init_glob_errs(void)
@@ -92,6 +93,7 @@ void init_glob_errs()
EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
EE(EE_FILE_NOT_CLOSED) = "File '%s' (fileno: %d) was not closed";
EE(EE_CANT_CHMOD) = "Can't change mode for file '%s' to 0x%lx (Error: %d)";
+ EE(EE_CANT_COPY_OWNERSHIP)= "Warning: Can't copy ownership for file '%s' (Error: %d)";
}
#endif
=== modified file 'mysys/my_copy.c'
--- a/mysys/my_copy.c 2009-02-13 16:41:47 +0000
+++ b/mysys/my_copy.c 2009-10-26 11:35:42 +0000
@@ -14,6 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
+#include "mysys_err.h"
#include <my_dir.h> /* for stat */
#include <m_string.h>
#if defined(HAVE_UTIME_H)
@@ -96,7 +97,10 @@ int my_copy(const char *from, const char
DBUG_RETURN(0); /* File copyed but not stat */
VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */
#if !defined(__WIN__) && !defined(__NETWARE__)
- VOID(chown(to, stat_buff.st_uid,stat_buff.st_gid)); /* Copy ownership */
+ if (chown(to, stat_buff.st_uid,stat_buff.st_gid))
+ {
+ my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_JUST_WARNING), to);
+ }
#endif
#if !defined(VMS) && !defined(__ZTC__)
if (MyFlags & MY_COPYTIME)
=== modified file 'mysys/my_redel.c'
--- a/mysys/my_redel.c 2007-03-29 17:01:51 +0000
+++ b/mysys/my_redel.c 2009-10-26 11:35:42 +0000
@@ -14,6 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
+#include "mysys_err.h"
#include <my_dir.h>
#include <m_string.h>
#include "mysys_err.h"
@@ -94,7 +95,10 @@ int my_copystat(const char *from, const
if (MyFlags & MY_LINK_WARNING)
my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink);
}
- VOID(chown(to, statbuf.st_uid, statbuf.st_gid)); /* Copy ownership */
+ if (chown(to, statbuf.st_uid, statbuf.st_gid))
+ {
+ my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_JUST_WARNING), to);
+ }
#endif /* !__WIN__ && !__NETWARE__ */
#ifndef VMS
=== modified file 'mysys/safemalloc.c'
--- a/mysys/safemalloc.c 2009-09-30 23:40:51 +0000
+++ b/mysys/safemalloc.c 2009-10-26 11:38:17 +0000
@@ -158,7 +158,7 @@ void *_mymalloc(size_t size, const char
my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH));
}
DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'",
- sf_malloc_max_memory,lineno, filename));
+ (ulong) sf_malloc_max_memory,lineno, filename));
if (MyFlags & MY_FAE)
exit(1);
DBUG_RETURN ((void*) 0);
=== modified file 'scripts/make_binary_distribution.sh'
--- a/scripts/make_binary_distribution.sh 2009-10-26 15:01:05 +0000
+++ b/scripts/make_binary_distribution.sh 2009-10-30 19:52:44 +0000
@@ -231,6 +231,18 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; t
# ----------------------------------------------------------------------
set -e
+ #
+ # Check that the client is compiled with libmysqlclient.a
+ #
+ if test -f ./client/.libs/mysql
+ then
+ echo ""
+ echo "The MySQL clients are compiled dynamicly, which is not allowed for"
+ echo "a MySQL binary tar file. Please configure with"
+ echo "--with-client-ldflags=-all-static and try again"
+ exit 1;
+ fi
+
# ----------------------------------------------------------------------
# Really ugly, one script, "mysql_install_db", needs prefix set to ".",
# i.e. makes access relative the current directory. This matches
=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc 2009-09-07 20:50:10 +0000
+++ b/sql/ha_partition.cc 2009-10-26 11:35:42 +0000
@@ -999,7 +999,7 @@ static bool print_admin_msg(THD* thd, co
if (!thd->vio_ok())
{
- sql_print_error(msgbuf);
+ sql_print_error(fmt, args);
return TRUE;
}
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2009-09-15 10:46:35 +0000
+++ b/sql/log.cc 2009-10-26 11:35:42 +0000
@@ -4830,7 +4830,8 @@ bool flush_error_log()
size_t bytes;
uchar buf[IO_SIZE];
- freopen(err_temp,"a+",stderr);
+ if (!freopen(err_temp,"a+",stderr))
+ sql_print_error("Couldn't reopen stderr");
setbuf(stderr, NULL);
(void) my_delete(err_renamed, MYF(0));
my_rename(log_error_file,err_renamed,MYF(0));
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2009-10-23 19:26:26 +0000
+++ b/sql/mysqld.cc 2009-10-29 00:04:56 +0000
@@ -1889,7 +1889,9 @@ void close_connection(THD *thd, uint err
extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
{
DBUG_ENTER("end_mysqld_signal");
- kill_mysql(); // Take down mysqld nicely
+ /* Don't call kill_mysql() if signal thread is not running */
+ if (signal_thread_in_use)
+ kill_mysql(); // Take down mysqld nicely
DBUG_VOID_RETURN; /* purecov: deadcode */
}
@@ -2117,8 +2119,8 @@ void win_install_sigabrt_handler(void)
#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
/*
- Wait for debugger to attach and break into debugger. If debugger is not attached,
- resume after timeout.
+ Wait for debugger to attach and break into debugger. If debugger is
+ not attached, resume after timeout.
*/
static void wait_for_debugger(int timeout_sec)
{
@@ -3855,7 +3857,8 @@ static int init_server_components()
if (freopen(log_error_file, "a+", stdout))
#endif
{
- freopen(log_error_file, "a+", stderr);
+ if (!(freopen(log_error_file, "a+", stderr)))
+ sql_print_warning("Couldn't reopen stderr");
setbuf(stderr, NULL);
}
}
@@ -4489,8 +4492,11 @@ we force server id to 2, but this MySQL
#ifdef __WIN__
if (!opt_console)
{
- freopen(log_error_file,"a+",stdout);
- freopen(log_error_file,"a+",stderr);
+ if (!freopen(log_error_file,"a+",stdout) ||
+ !freopen(log_error_file,"a+",stderr))
+ {
+ sql_print_warning("Couldn't reopen stdout or stderr");
+ }
setbuf(stderr, NULL);
FreeConsole(); // Remove window
}
@@ -5748,7 +5754,7 @@ enum options_mysqld
OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT,
OPT_RELAY_LOG_PURGE,
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
- OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
+ OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING, OPT_DEBUG_FLUSH,
OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE,
OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
@@ -5968,6 +5974,8 @@ struct my_option my_long_options[] =
"Call my_debug_put_break_here() if crc matches this number (for debug).",
(uchar**) &opt_my_crc_dbug_check, (uchar**) &opt_my_crc_dbug_check,
0, GET_ULONG, REQUIRED_ARG, 0, 0, ~(ulong) 0L, 0, 0, 0},
+ {"debug-flush", OPT_DEBUG_FLUSH, "Default debug log with flush after write",
+ (uchar**) 0, (uchar**) 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).",
(uchar**) &default_character_set_name, (uchar**) &default_character_set_name,
@@ -8075,6 +8083,9 @@ mysqld_get_one_option(int optid,
switch(optid) {
#ifndef DBUG_OFF
+ case OPT_DEBUG_FLUSH:
+ argument= IF_WIN(default_dbug_option, (char*) "d:t:i:O,/tmp/mysqld.trace");
+ /* fall through */
case '#':
if (!argument)
argument= (char*) default_dbug_option;
=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc 2009-09-07 20:50:10 +0000
+++ b/sql/rpl_rli.cc 2009-10-26 11:35:42 +0000
@@ -295,7 +295,7 @@ Failed to open the existing relay log in
DBUG_RETURN(error);
err:
- sql_print_error(msg);
+ sql_print_error("%s", msg);
end_io_cache(&rli->info_file);
if (info_fd >= 0)
my_close(info_fd, MYF(0));
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2009-09-15 10:46:35 +0000
+++ b/sql/set_var.cc 2009-10-26 11:35:42 +0000
@@ -4293,9 +4293,13 @@ uchar *sys_var_thd_dbug::value_ptr(THD *
{
char buf[256];
if (type == OPT_GLOBAL)
+ {
DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
+ }
else
+ {
DBUG_EXPLAIN(buf, sizeof(buf));
+ }
return (uchar*) thd->strdup(buf);
}
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2009-09-15 10:46:35 +0000
+++ b/sql/slave.cc 2009-10-26 11:35:42 +0000
@@ -1145,7 +1145,7 @@ err:
if (master_res)
mysql_free_result(master_res);
DBUG_ASSERT(err_code != 0);
- mi->report(ERROR_LEVEL, err_code, err_buff);
+ mi->report(ERROR_LEVEL, err_code, "%s", err_buff);
DBUG_RETURN(1);
}
@@ -2340,7 +2340,7 @@ static bool check_io_slave_killed(THD *t
if (io_slave_killed(thd, mi))
{
if (info && global_system_variables.log_warnings)
- sql_print_information(info);
+ sql_print_information("%s", info);
return TRUE;
}
return FALSE;
@@ -2410,13 +2410,13 @@ static int try_to_reconnect(THD *thd, MY
}
else
{
- sql_print_information(buf);
+ sql_print_information("%s", buf);
}
}
if (safe_reconnect(thd, mysql, mi, 1) || io_slave_killed(thd, mi))
{
if (global_system_variables.log_warnings)
- sql_print_information(messages[SLAVE_RECON_MSG_KILLED_AFTER]);
+ sql_print_information("%s", messages[SLAVE_RECON_MSG_KILLED_AFTER]);
return 1;
}
return 0;
@@ -2998,7 +2998,7 @@ log '%s' at position %s, relay log '%s'
This function is reporting an error which was not reported
while executing exec_relay_log_event().
*/
- rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), errmsg);
+ rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), "%s", errmsg);
}
else if (last_errno != thd->main_da.sql_errno())
{
=== modified file 'sql/sql_cache.cc'
--- a/sql/sql_cache.cc 2009-09-15 10:46:35 +0000
+++ b/sql/sql_cache.cc 2009-10-26 11:35:42 +0000
@@ -383,7 +383,7 @@ static void debug_wait_for_kill(const ch
thd= current_thd;
prev_info= thd->proc_info;
thd->proc_info= info;
- sql_print_information(info);
+ sql_print_information("%s", info);
while(!thd->killed)
my_sleep(1000);
thd->killed= THD::NOT_KILLED;
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2009-09-15 10:46:35 +0000
+++ b/sql/sql_parse.cc 2009-10-26 11:35:42 +0000
@@ -481,7 +481,11 @@ pthread_handler_t handle_bootstrap(void
break;
}
buff= (char*) thd->net.buff;
- fgets(buff + length, thd->net.max_packet - length, file);
+ if (!fgets(buff + length, thd->net.max_packet - length, file))
+ {
+ bootstrap_error= 1;
+ break;
+ }
length+= (ulong) strlen(buff + length);
/* purecov: end */
}
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2009-10-01 21:27:39 +0000
+++ b/sql/sql_plugin.cc 2009-10-29 00:04:56 +0000
@@ -367,8 +367,8 @@ static st_plugin_dl *plugin_dl_add(const
{
if (report & REPORT_TO_USER)
my_error(ER_UDF_NO_PATHS, MYF(0));
- if (report & REPORT_TO_LOG)
- sql_print_error(ER(ER_UDF_NO_PATHS));
+ if ((report & (REPORT_TO_LOG | REPORT_TO_USER)) == REPORT_TO_LOG)
+ sql_print_error("%s", ER(ER_UDF_NO_PATHS));
DBUG_RETURN(0);
}
/* If this dll is already loaded just increase ref_count. */
@@ -3226,7 +3226,6 @@ static int test_plugin_options(MEM_ROOT
my_bool can_disable;
bool disable_plugin;
enum_plugin_load_policy plugin_load_policy= PLUGIN_ON;
-
MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
&tmp->mem_root : &plugin_mem_root;
st_mysql_sys_var **opt;
@@ -3240,13 +3239,13 @@ static int test_plugin_options(MEM_ROOT
DBUG_ENTER("test_plugin_options");
DBUG_ASSERT(tmp->plugin && tmp->name.str);
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
/*
- The 'federated' and 'ndbcluster' storage engines are always disabled by
- default.
+ The 'ndbcluster' storage engines is always disabled by default.
*/
- if (!(my_strcasecmp(&my_charset_latin1, tmp->name.str, "federated") &&
- my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster")))
+ if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster"))
plugin_load_policy= PLUGIN_OFF;
+#endif
for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
@@ -3295,6 +3294,11 @@ static int test_plugin_options(MEM_ROOT
can_disable=
my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") &&
my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY");
+#ifdef USE_MARIA_FOR_TMP_TABLES
+ if (!can_disable)
+ can_disable= (my_strcasecmp(&my_charset_latin1, tmp->name.str, "Maria")
+ != 0);
+#endif
tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE) || !can_disable;
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2009-09-30 23:40:51 +0000
+++ b/sql/sql_select.cc 2009-10-26 11:38:17 +0000
@@ -9819,7 +9819,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
bool using_unique_constraint= 0;
bool use_packed_rows= 0;
bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
- char *tmpname,path[FN_REFLEN];
+ char *tmpname,path[FN_REFLEN], tmp_table_name[50];
uchar *pos, *group_buff, *bitmaps;
uchar *null_flags;
Field **reg_field, **from_field, **default_field;
@@ -9846,12 +9846,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
temp_pool_slot = bitmap_lock_set_next(&temp_pool);
if (temp_pool_slot != MY_BIT_NONE) // we got a slot
- sprintf(path, "%s_%lx_%i", tmp_file_prefix,
+ sprintf(tmp_table_name, "%s_%lx_%i", tmp_file_prefix,
current_pid, temp_pool_slot);
else
{
/* if we run out of slots or we are not using tempool */
- sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid,
+ sprintf(tmp_table_name, "%s%lx_%lx_%x", tmp_file_prefix,current_pid,
thd->thread_id, thd->tmp_table++);
}
@@ -9859,7 +9859,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
No need to change table name to lower case as we are only creating
MyISAM, Maria or HEAP tables here
*/
- fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+ fn_format(path, tmp_table_name, mysql_tmpdir, "",
+ MY_REPLACE_EXT|MY_UNPACK_FILENAME);
if (group)
{
@@ -9905,7 +9906,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
sizeof(*key_part_info)*(param->group_parts+1),
¶m->start_recinfo,
sizeof(*param->recinfo)*(field_count*2+4),
- &tmpname, (uint) strlen(path)+1,
+ &tmpname, (uint) strlen(tmp_table_name)+1,
&group_buff, (group && ! using_unique_constraint ?
param->group_length : 0),
&bitmaps, bitmap_buffer_size(field_count)*2,
@@ -9924,7 +9925,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
DBUG_RETURN(NULL); /* purecov: inspected */
}
param->items_to_copy= copy_func;
- strmov(tmpname,path);
+ strmov(tmpname, tmp_table_name);
/* make table according to fields */
bzero((char*) table,sizeof(*table));
=== modified file 'sql/sql_string.cc'
--- a/sql/sql_string.cc 2009-09-07 20:50:10 +0000
+++ b/sql/sql_string.cc 2009-10-13 16:57:36 +0000
@@ -27,14 +27,6 @@
#include <floatingpoint.h>
#endif
-/*
- The following extern declarations are ok as these are interface functions
- required by the string function
-*/
-
-extern uchar* sql_alloc(unsigned size);
-extern void sql_element_free(void *ptr);
-
#include "sql_string.h"
/*****************************************************************************
=== modified file 'sql/udf_example.c'
--- a/sql/udf_example.c 2009-09-30 23:40:51 +0000
+++ b/sql/udf_example.c 2009-10-26 11:38:17 +0000
@@ -139,7 +139,9 @@ typedef long long longlong;
#include <mysql.h>
#include <ctype.h>
+#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST)
static pthread_mutex_t LOCK_hostname;
+#endif
#ifdef HAVE_DLOPEN
=== added file 'storage/federated/README'
--- a/storage/federated/README 1970-01-01 00:00:00 +0000
+++ b/storage/federated/README 2009-10-30 18:50:56 +0000
@@ -0,0 +1,7 @@
+The files in this directory are not used by MariaDB
+
+MariaDB uses the new federated storage engine that can be found in the
+federatedx directory.
+
+This directory is only kept around to make it easy to merge code from the
+MySQL source repositories that uses the old and disabled federated code.
=== renamed file 'storage/federated/plug.in' => 'storage/federated/plug.in.disabled'
=== added directory 'storage/federatedx'
=== added file 'storage/federatedx/AUTHORS'
--- a/storage/federatedx/AUTHORS 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/AUTHORS 2009-10-30 18:50:56 +0000
@@ -0,0 +1,11 @@
+FederatedX
+
+Patrick Galbraith <patg(a)patg.net> - Federated
+
+Pluggable Storage Engine Skeleton setup
+
+Brian Aker <brian(a)mysql.com> | <brian(a)tangent.org> - Original Design
+Calvin Sun - Windows Support
+Brian Miezejewski - Bug fixes
+Antony T Curtis - Help in inital development, transactions and various help
+Michael Widenius - Bug fixes and some simple early optimizations
=== added file 'storage/federatedx/CMakeFiles.txt'
--- a/storage/federatedx/CMakeFiles.txt 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/CMakeFiles.txt 2009-10-30 18:50:56 +0000
@@ -0,0 +1,3 @@
+INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
+SET(FEDERATED_SOURCES ha_federatedx.cc)
+MYSQL_STORAGE_ENGINE(FEDERATED)
=== added file 'storage/federatedx/ChangeLog'
--- a/storage/federatedx/ChangeLog 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ChangeLog 2009-10-30 18:50:56 +0000
@@ -0,0 +1,18 @@
+0.2 - Thu March 8 00:00:00 EST 2008
+
+ - Fixed bug #30051 "CREATE TABLE does not connect and check existence of remote table"
+ Modified "real_connect" to take a share and create flag to in order to not rely
+ on any settings that are later instantiated and/or set by get_share
+ Also, put logic in the code to not attempt this if a localhost. There's an annoying
+ functionality that if federated tries to connect to itself during creater table, you
+ get 1159 error (timeout) - only when local. This prevents having this functionality
+ and is probably part of the reason it was removed.
+
+0.1 - Thu Feb 1 00:00:00 EST 2008
+
+ - This is the FederatedX Storage Engine,
+ first release.
+ - Added documentation
+ - Added simple test and README file to explain
+ how to run the test
+ - Added FAQ
=== added file 'storage/federatedx/FAQ'
--- a/storage/federatedx/FAQ 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/FAQ 2009-10-30 18:50:56 +0000
@@ -0,0 +1,40 @@
+Q. What is the FederatedX pluggable storage engine?
+
+A. It is a fork of the Federated Storage Engine that Brian Aker and I
+(Patrick Galbraith) developed originally . It is a storage engine that
+uses a client connection to a remote MySQL data source as its data
+source instead of a local file on disk.
+
+Q. Why did you fork from Federated?
+
+A. To enhance the storage engine independently of the
+MySQL Server release schedule. Many people have been
+mentioning their dissatisfaction with the limitations
+of Federated. I think the engine is a great concept and
+have a sense of obligation to continue to improve it.
+There are some patches already that are in dire need
+of being applied and tested.
+
+Q. What do you plan to do with FederatedX?
+
+A. Many things need addressing:
+
+- Outstanding bugs
+- How do deal with huge result sets
+- Pushdown conditions (being able to pass things like LIMIT
+ to the remote connection to keep from returning huge
+ result sets).
+- Better transactional support
+- Other connection mechanisms (ODBC, JDBC, native drivers
+ of other RDBMSs)
+
+Q. What FederatedX is and is not?
+
+A. FederatedX is not yet a complete "federated" solution in
+ the sense that other venders have developed (IBM, etc). It
+ is essentially a networked storage engine. It is my hope
+ to make it a real federated solution.
+
+Q. In which MySQL distributions/forks/branches can I find FederateX
+
+A. MariaDB (http://www.mariadb.com)
=== added file 'storage/federatedx/Makefile.am'
--- a/storage/federatedx/Makefile.am 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/Makefile.am 2009-10-30 18:50:56 +0000
@@ -0,0 +1,64 @@
+# Used to build Makefile.in
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+pkgplugindir = $(pkglibdir)/plugin
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir)
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_federatedx.h federatedx_probes.h
+
+EXTRA_LTLIBRARIES = ha_federatedx.la
+pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@
+ha_federatedx_la_LDFLAGS = -module -rpath $(pkgplugindir)
+ha_federatedx_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_federatedx_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_federatedx_la_SOURCES = ha_federatedx.cc
+
+
+EXTRA_LIBRARIES = libfederatedx.a
+noinst_LIBRARIES = @plugin_federated_static_target@
+libfederatedx_a_CXXFLAGS = $(AM_CFLAGS)
+libfederatedx_a_CFLAGS = $(AM_CFLAGS)
+libfederatedx_a_SOURCES= ha_federatedx.cc federatedx_txn.cc \
+ federatedx_io.cc federatedx_io_null.cc \
+ federatedx_io_mysql.cc
+
+EXTRA_DIST = CMakeLists.txt plug.in ha_federatedx.h \
+ federatedx_probes.d
+
+ha_federatedx_la_SOURCES = ha_federatedx.cc federatedx_txn.cc \
+ federatedx_io.cc federatedx_io_null.cc \
+ federatedx_io_mysql.cc $(top_srcdir)/mysys/string.c
+ha_federatedx_la_LIBADD =
+
+#DTRACE = @DTRACE@
+#DTRACEFLAGS = @DTRACEFLAGS@
+#DTRACEFILES = .libs/libfederatedx_engine_la-ha_federatedx.o
+
+# #if HAVE_DTRACE
+# # libfederatedx_engine_la_LIBADD += federatedx_probes.o
+# #endif
+
+# federatedx_probes.h: federatedx_probes.d
+# $(DTRACE) $(DTRACEFLAGS) -h -s federatedx_probes.d
+# mv federatedx_probes.h federatedx_probes.h.bak
+# sed "s/#include <unistd.h>//g" federatedx_probes.h.bak > federatedx_probes.h
+# rm federatedx_probes.h.bak
+
+#federatedx_probes.o:
+# $(DTRACE) $(DTRACEFLAGS) -G -s federatedx_probes.d $(DTRACEFILES)
+
+# End
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
=== added file 'storage/federatedx/README'
--- a/storage/federatedx/README 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/README 2009-10-30 18:50:56 +0000
@@ -0,0 +1,33 @@
+This is the FederatedX Storage Engine, developed as an external storage engine.
+
+NOTE:
+
+The following is only relevant if you use it for MySQL. MariaDB already comes
+with the latest version of FederatedX.
+
+To install, grab a copy of the mysql source code and run this:
+
+./configure --with-mysql=/path/to/src/mysql-5.x --libdir=/usr/local/lib/mysql/
+
+make install
+
+And then inside of MySQL:
+
+mysql> INSTALL PLUGIN federatedx SONAME 'libfederatedx_engine.so';
+
+mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="mysql://root@host/schema/table"
+
+or
+
+mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="server" CHARSET=latin1;
+
+You will probably need to edit the Makefile.am in the src/ tree if you want
+to build on anything other then Linux (and the Makefile assumes that the
+server was not compiled for debug). The reason for the two possible
+configure lines is that libdir is dependent on where MySQL was installed. If
+you run the "INSTALL PLUGIN ..." and you get a file not found, check that
+your configured this directory correctly.
+
+For Solaris you can enable DTrace probes by adding to configure
+--enable-dtrace
+
=== added file 'storage/federatedx/README.windows'
--- a/storage/federatedx/README.windows 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/README.windows 2009-10-30 18:50:56 +0000
@@ -0,0 +1,23 @@
+The following files are changed in order to build a new engine on Windows:
+
+- Update win\configure.js with
+case "WITH_FEDERATEDX_STORAGE_ENGINE":
+to make sure it will pass WITH_FEDERATEDX_STORAGE_ENGINE in.
+
+- Update CMakeFiles.txt under mysql root:
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ ADD_DEFINITIONS(-D WITH_FEDERATEDX_STORAGE_ENGINE)
+ SET (mysql_plugin_defs
+ "${mysql_plugin_defs},builtin_skeleton_plugin")
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
+
+ and,
+
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/skeleton/src)
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
+
+ - Update CMakeFiles.txt under sql:
+ IF(WITH_FEDERATEDX_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld skeleton)
+ ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
=== added file 'storage/federatedx/TODO'
--- a/storage/federatedx/TODO 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/TODO 2009-10-30 18:50:56 +0000
@@ -0,0 +1,30 @@
+Features
+
+* Add Pushdown conditions
+* Add other network driver interfaces
+* Handle large result sets
+* Auto-discovery of tables on foreign data sources
+
+Bugs (http://bugs.mysql.com)
+
+20026 2006-05-23 FEDERATED lacks support for auto_increment_increment and auto_increment_offset
+20724 2006-06-27 FEDERATED does not honour SET INSERT_ID
+28269 2007-05-06 Any FEDERATED engine fails to quote reserved words for field names
+25509 2007-01-10 Federated: Failure with non-ASCII characters
+26697 2007-02-27 Every query to a federated table results in a full scan of MyISAM table.
+21360 2006-07-31 Microsoft Windows (Windows/Linux) mysqldump error on federated tables
+34189 2008-01-31 Any ALTER TABLE t1 ENGINE=FEDERATED CONNECTION='connectionString' on MyISAM fails
+31757 2007-10-22 Any Federated tables break replication Antony Curtis
+33953 2008-01-21 Any mysqld dies on search federated table using nullable index with < or <= operator
+34015 2008-01-23 Linux Problems with float fields using federated tables
+21583 2006-08-11 Linux (Linux) Federated table returns broken strings.
+33702 2008-01-05 Accessing a federated table with a non existing server returns random error code
+25512 2007-01-10 Federated: CREATE failures
+32426 2007-11-16 Any FEDERATED query returns corrupt results for ORDER BY on a TEXT field
+25510 2007-01-10 Federated: double trigger activation
+33250 2007-12-14 SELECT * FROM really_big_federated_table eats lots of virtual memory (OOM)
+14874 2005-11-11 Error 2013: Lost connection to MySQL server with Federated table
+25508 2007-01-10 Federated: Failure to Remove Partitioning
+27180 2007-03-15 #1030 - Got error 1 from storage engine with big tables
+33947 2008-01-20 Any Join on Federated tables with Unique index and IS NOT NULL crashes server
+30051 (fixed) CREATE TABLE does not connect and check existence of remote table
=== added file 'storage/federatedx/federatedx_io.cc'
--- a/storage/federatedx/federatedx_io.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+typedef federatedx_io *(*instantiate_io_type)(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+struct io_schemes_st
+{
+ const char *scheme;
+ instantiate_io_type instantiate;
+};
+
+
+static const io_schemes_st federated_io_schemes[] =
+{
+ { "mysql", &instantiate_io_mysql },
+ { "null", instantiate_io_null } /* must be last element */
+};
+
+const uint federated_io_schemes_count= array_elements(federated_io_schemes);
+
+federatedx_io::federatedx_io(FEDERATEDX_SERVER *aserver)
+ : server(aserver), owner_ptr(0), txn_next(0), idle_next(0),
+ active(FALSE), busy(FALSE), readonly(TRUE)
+{
+ DBUG_ENTER("federatedx_io::federatedx_io");
+ DBUG_ASSERT(server);
+
+ safe_mutex_assert_owner(&server->mutex);
+ server->io_count++;
+
+ DBUG_VOID_RETURN;
+}
+
+
+federatedx_io::~federatedx_io()
+{
+ DBUG_ENTER("federatedx_io::~federatedx_io");
+
+ server->io_count--;
+
+ DBUG_VOID_RETURN;
+}
+
+
+bool federatedx_io::handles_scheme(const char *scheme)
+{
+ const io_schemes_st *ptr = federated_io_schemes;
+ const io_schemes_st *end = ptr + array_elements(federated_io_schemes);
+ while (ptr != end && strcasecmp(scheme, ptr->scheme))
+ ++ptr;
+ return ptr != end;
+}
+
+
+federatedx_io *federatedx_io::construct(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ const io_schemes_st *ptr = federated_io_schemes;
+ const io_schemes_st *end = ptr + (array_elements(federated_io_schemes) - 1);
+ while (ptr != end && strcasecmp(server->scheme, ptr->scheme))
+ ++ptr;
+ return ptr->instantiate(server_root, server);
+}
+
+
=== added file 'storage/federatedx/federatedx_io_mysql.cc'
--- a/storage/federatedx/federatedx_io_mysql.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io_mysql.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,592 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+#define SAVEPOINT_REALIZED 1
+#define SAVEPOINT_RESTRICT 2
+#define SAVEPOINT_EMITTED 4
+
+
+typedef struct federatedx_savepoint
+{
+ ulong level;
+ uint flags;
+} SAVEPT;
+
+
+class federatedx_io_mysql :public federatedx_io
+{
+ MYSQL mysql; /* MySQL connection */
+ DYNAMIC_ARRAY savepoints;
+ bool requested_autocommit;
+ bool actual_autocommit;
+
+ int actual_query(const char *buffer, uint length);
+ bool test_all_restrict() const;
+public:
+ federatedx_io_mysql(FEDERATEDX_SERVER *);
+ ~federatedx_io_mysql();
+
+ int simple_query(const char *fmt, ...);
+ int query(const char *buffer, uint length);
+ virtual FEDERATEDX_IO_RESULT *store_result();
+
+ virtual size_t max_query_size() const;
+
+ virtual my_ulonglong affected_rows() const;
+ virtual my_ulonglong last_insert_id() const;
+
+ virtual int error_code();
+ virtual const char *error_str();
+
+ void reset();
+ int commit();
+ int rollback();
+
+ int savepoint_set(ulong sp);
+ ulong savepoint_release(ulong sp);
+ ulong savepoint_rollback(ulong sp);
+ void savepoint_restrict(ulong sp);
+
+ ulong last_savepoint() const;
+ ulong actual_savepoint() const;
+ bool is_autocommit() const;
+
+ bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag);
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column);
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const;
+};
+
+
+federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ return new (server_root) federatedx_io_mysql(server);
+}
+
+
+federatedx_io_mysql::federatedx_io_mysql(FEDERATEDX_SERVER *aserver)
+ : federatedx_io(aserver),
+ requested_autocommit(TRUE), actual_autocommit(TRUE)
+{
+ DBUG_ENTER("federatedx_io_mysql::federatedx_io_mysql");
+
+ bzero(&mysql, sizeof(MYSQL));
+ bzero(&savepoints, sizeof(DYNAMIC_ARRAY));
+
+ my_init_dynamic_array(&savepoints, sizeof(SAVEPT), 16, 16);
+
+ DBUG_VOID_RETURN;
+}
+
+
+federatedx_io_mysql::~federatedx_io_mysql()
+{
+ DBUG_ENTER("federatedx_io_mysql::~federatedx_io_mysql");
+
+ mysql_close(&mysql);
+ delete_dynamic(&savepoints);
+
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_io_mysql::reset()
+{
+ reset_dynamic(&savepoints);
+ set_active(FALSE);
+
+ requested_autocommit= TRUE;
+ mysql.reconnect= 1;
+}
+
+
+int federatedx_io_mysql::commit()
+{
+ int error= 0;
+ DBUG_ENTER("federatedx_io_mysql::commit");
+
+ if (!actual_autocommit && (error= actual_query("COMMIT", 6)))
+ rollback();
+
+ reset();
+
+ DBUG_RETURN(error);
+}
+
+int federatedx_io_mysql::rollback()
+{
+ int error= 0;
+ DBUG_ENTER("federatedx_io_mysql::rollback");
+
+ if (!actual_autocommit)
+ error= actual_query("ROLLBACK", 8);
+ else
+ error= ER_WARNING_NOT_COMPLETE_ROLLBACK;
+
+ reset();
+
+ DBUG_RETURN(error);
+}
+
+
+ulong federatedx_io_mysql::last_savepoint() const
+{
+ SAVEPT *savept= NULL;
+ DBUG_ENTER("federatedx_io_mysql::last_savepoint");
+
+ if (savepoints.elements)
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+
+ DBUG_RETURN(savept ? savept->level : 0);
+}
+
+
+ulong federatedx_io_mysql::actual_savepoint() const
+{
+ SAVEPT *savept= NULL;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::last_savepoint");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->flags & SAVEPOINT_REALIZED)
+ break;
+ savept= NULL;
+ }
+
+ DBUG_RETURN(savept ? savept->level : 0);
+}
+
+bool federatedx_io_mysql::is_autocommit() const
+{
+ return actual_autocommit;
+}
+
+
+int federatedx_io_mysql::savepoint_set(ulong sp)
+{
+ int error;
+ SAVEPT savept;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_set");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+ DBUG_ASSERT(sp > last_savepoint());
+
+ savept.level= sp;
+ savept.flags= 0;
+
+ if ((error= insert_dynamic(&savepoints, (uchar*) &savept) ? -1 : 0))
+ goto err;
+
+ set_active(TRUE);
+ mysql.reconnect= 0;
+ requested_autocommit= FALSE;
+
+err:
+ DBUG_RETURN(error);
+}
+
+
+ulong federatedx_io_mysql::savepoint_release(ulong sp)
+{
+ SAVEPT *savept, *last= NULL;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_release");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+
+ while (savepoints.elements)
+ {
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+ if (savept->level < sp)
+ break;
+ if ((savept->flags & (SAVEPOINT_REALIZED |
+ SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED)
+ last= savept;
+ savepoints.elements--;
+ }
+
+ if (last)
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length= my_snprintf(buffer, sizeof(buffer),
+ "RELEASE SAVEPOINT save%lu", last->level);
+ actual_query(buffer, length);
+ }
+
+ DBUG_RETURN(last_savepoint());
+}
+
+
+ulong federatedx_io_mysql::savepoint_rollback(ulong sp)
+{
+ SAVEPT *savept;
+ uint index;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_release");
+ DBUG_PRINT("info",("savepoint=%lu", sp));
+
+ while (savepoints.elements)
+ {
+ savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
+ if (savept->level <= sp)
+ break;
+ savepoints.elements--;
+ }
+
+ for (index= savepoints.elements, savept= NULL; index;)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->flags & SAVEPOINT_REALIZED)
+ break;
+ savept= NULL;
+ }
+
+ if (savept && !(savept->flags & SAVEPOINT_RESTRICT))
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length= my_snprintf(buffer, sizeof(buffer),
+ "ROLLBACK TO SAVEPOINT save%lu", savept->level);
+ actual_query(buffer, length);
+ }
+
+ DBUG_RETURN(last_savepoint());
+}
+
+
+void federatedx_io_mysql::savepoint_restrict(ulong sp)
+{
+ SAVEPT *savept;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::savepoint_restrict");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if (savept->level > sp)
+ continue;
+ if (savept->level < sp)
+ break;
+ savept->flags|= SAVEPOINT_RESTRICT;
+ break;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+int federatedx_io_mysql::simple_query(const char *fmt, ...)
+{
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int length, error;
+ va_list arg;
+ DBUG_ENTER("federatedx_io_mysql::simple_query");
+
+ va_start(arg, fmt);
+ length= my_vsnprintf(buffer, sizeof(buffer), fmt, arg);
+ va_end(arg);
+
+ error= query(buffer, length);
+
+ DBUG_RETURN(error);
+}
+
+
+bool federatedx_io_mysql::test_all_restrict() const
+{
+ bool result= FALSE;
+ SAVEPT *savept;
+ uint index= savepoints.elements;
+ DBUG_ENTER("federatedx_io_mysql::test_all_restrict");
+
+ while (index)
+ {
+ savept= dynamic_element(&savepoints, --index, SAVEPT *);
+ if ((savept->flags & (SAVEPOINT_REALIZED |
+ SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED ||
+ (savept->flags & SAVEPOINT_EMITTED))
+ DBUG_RETURN(FALSE);
+ if (savept->flags & SAVEPOINT_RESTRICT)
+ result= TRUE;
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_io_mysql::query(const char *buffer, uint length)
+{
+ int error;
+ bool wants_autocommit= requested_autocommit | is_readonly();
+ DBUG_ENTER("federatedx_io_mysql::query");
+
+ if (!wants_autocommit && test_all_restrict())
+ wants_autocommit= TRUE;
+
+ if (wants_autocommit != actual_autocommit)
+ {
+ if ((error= actual_query(wants_autocommit ? "SET AUTOCOMMIT=1"
+ : "SET AUTOCOMMIT=0", 16)))
+ DBUG_RETURN(error);
+ mysql.reconnect= wants_autocommit ? 1 : 0;
+ actual_autocommit= wants_autocommit;
+ }
+
+ if (!actual_autocommit && last_savepoint() != actual_savepoint())
+ {
+ SAVEPT *savept= dynamic_element(&savepoints, savepoints.elements - 1,
+ SAVEPT *);
+ if (!(savept->flags & SAVEPOINT_RESTRICT))
+ {
+ char buf[STRING_BUFFER_USUAL_SIZE];
+ int len= my_snprintf(buf, sizeof(buf),
+ "SAVEPOINT save%lu", savept->level);
+ if ((error= actual_query(buf, len)))
+ DBUG_RETURN(error);
+ set_active(TRUE);
+ savept->flags|= SAVEPOINT_EMITTED;
+ }
+ savept->flags|= SAVEPOINT_REALIZED;
+ }
+
+ if (!(error= actual_query(buffer, length)))
+ set_active(is_active() || !actual_autocommit);
+
+ DBUG_RETURN(error);
+}
+
+
+int federatedx_io_mysql::actual_query(const char *buffer, uint length)
+{
+ int error;
+ DBUG_ENTER("federatedx_io_mysql::actual_query");
+
+ if (!mysql.master)
+ {
+ if (!(mysql_init(&mysql)))
+ DBUG_RETURN(-1);
+
+ /*
+ BUG# 17044 Federated Storage Engine is not UTF8 clean
+ Add set names to whatever charset the table is at open
+ of table
+ */
+ /* this sets the csname like 'set names utf8' */
+ mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, get_charsetname());
+
+ if (!mysql_real_connect(&mysql,
+ get_hostname(),
+ get_username(),
+ get_password(),
+ get_database(),
+ get_port(),
+ get_socket(), 0))
+ DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
+ mysql.reconnect= 1;
+ }
+
+ error= mysql_real_query(&mysql, buffer, length);
+
+ DBUG_RETURN(error);
+}
+
+size_t federatedx_io_mysql::max_query_size() const
+{
+ return mysql.net.max_packet_size;
+}
+
+
+my_ulonglong federatedx_io_mysql::affected_rows() const
+{
+ return mysql.affected_rows;
+}
+
+
+my_ulonglong federatedx_io_mysql::last_insert_id() const
+{
+ return mysql.last_used_con->insert_id;
+}
+
+
+int federatedx_io_mysql::error_code()
+{
+ return mysql_errno(&mysql);
+}
+
+
+const char *federatedx_io_mysql::error_str()
+{
+ return mysql_error(&mysql);
+}
+
+
+FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result()
+{
+ FEDERATEDX_IO_RESULT *result;
+ DBUG_ENTER("federatedx_io_mysql::store_result");
+
+ result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql);
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_io_mysql::free_result(FEDERATEDX_IO_RESULT *io_result)
+{
+ mysql_free_result((MYSQL_RES *) io_result);
+}
+
+
+unsigned int federatedx_io_mysql::get_num_fields(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_num_fields((MYSQL_RES *) io_result);
+}
+
+
+my_ulonglong federatedx_io_mysql::get_num_rows(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_num_rows((MYSQL_RES *) io_result);
+}
+
+
+FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result)
+{
+ return (FEDERATEDX_IO_ROW *) mysql_fetch_row((MYSQL_RES *) io_result);
+}
+
+
+ulong *federatedx_io_mysql::fetch_lengths(FEDERATEDX_IO_RESULT *io_result)
+{
+ return mysql_fetch_lengths((MYSQL_RES *) io_result);
+}
+
+
+const char *federatedx_io_mysql::get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column)
+{
+ return ((MYSQL_ROW)row)[column];
+}
+
+
+bool federatedx_io_mysql::is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const
+{
+ return !((MYSQL_ROW)row)[column];
+}
+
+bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
+ const char *table_name,
+ uint table_name_length, uint flag)
+{
+ char status_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ FEDERATEDX_IO_RESULT *result= 0;
+ FEDERATEDX_IO_ROW *row;
+ String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin);
+ int error;
+
+ status_query_string.length(0);
+ status_query_string.append(STRING_WITH_LEN("SHOW TABLE STATUS LIKE "));
+ append_ident(&status_query_string, table_name,
+ table_name_length, value_quote_char);
+
+ if (query(status_query_string.ptr(), status_query_string.length()))
+ goto error;
+
+ status_query_string.length(0);
+
+ result= store_result();
+
+ /*
+ We're going to use fields num. 4, 12 and 13 of the resultset,
+ so make sure we have these fields.
+ */
+ if (!result || (get_num_fields(result) < 14))
+ goto error;
+
+ if (!get_num_rows(result))
+ goto error;
+
+ if (!(row= fetch_row(result)))
+ goto error;
+
+ /*
+ deleted is set in ha_federatedx::info
+ */
+ /*
+ need to figure out what this means as far as federatedx is concerned,
+ since we don't have a "file"
+
+ data_file_length = ?
+ index_file_length = ?
+ delete_length = ?
+ */
+ if (!is_column_null(row, 4))
+ stats->records= (ha_rows) my_strtoll10(get_column_data(row, 4),
+ (char**) 0, &error);
+ if (!is_column_null(row, 5))
+ stats->mean_rec_length= (ulong) my_strtoll10(get_column_data(row, 5),
+ (char**) 0, &error);
+
+ stats->data_file_length= stats->records * stats->mean_rec_length;
+
+ if (!is_column_null(row, 12))
+ stats->update_time= (time_t) my_strtoll10(get_column_data(row, 12),
+ (char**) 0, &error);
+ if (!is_column_null(row, 13))
+ stats->check_time= (time_t) my_strtoll10(get_column_data(row, 13),
+ (char**) 0, &error);
+
+ free_result(result);
+ return 0;
+
+error:
+ free_result(result);
+ return 1;
+}
=== added file 'storage/federatedx/federatedx_io_null.cc'
--- a/storage/federatedx/federatedx_io_null.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_io_null.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,277 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+#define SAVEPOINT_REALIZED 1
+#define SAVEPOINT_RESTRICT 2
+#define SAVEPOINT_EMITTED 4
+
+
+typedef struct federatedx_savepoint
+{
+ ulong level;
+ uint flags;
+} SAVEPT;
+
+
+class federatedx_io_null :public federatedx_io
+{
+public:
+ federatedx_io_null(FEDERATEDX_SERVER *);
+ ~federatedx_io_null();
+
+ int query(const char *buffer, uint length);
+ virtual FEDERATEDX_IO_RESULT *store_result();
+
+ virtual size_t max_query_size() const;
+
+ virtual my_ulonglong affected_rows() const;
+ virtual my_ulonglong last_insert_id() const;
+
+ virtual int error_code();
+ virtual const char *error_str();
+
+ void reset();
+ int commit();
+ int rollback();
+
+ int savepoint_set(ulong sp);
+ ulong savepoint_release(ulong sp);
+ ulong savepoint_rollback(ulong sp);
+ void savepoint_restrict(ulong sp);
+
+ ulong last_savepoint() const;
+ ulong actual_savepoint() const;
+ bool is_autocommit() const;
+
+ bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag);
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column);
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const;
+};
+
+
+federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server)
+{
+ return new (server_root) federatedx_io_null(server);
+}
+
+
+federatedx_io_null::federatedx_io_null(FEDERATEDX_SERVER *aserver)
+ : federatedx_io(aserver)
+{
+}
+
+
+federatedx_io_null::~federatedx_io_null()
+{
+}
+
+
+void federatedx_io_null::reset()
+{
+}
+
+
+int federatedx_io_null::commit()
+{
+ return 0;
+}
+
+int federatedx_io_null::rollback()
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::last_savepoint() const
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::actual_savepoint() const
+{
+ return 0;
+}
+
+bool federatedx_io_null::is_autocommit() const
+{
+ return 0;
+}
+
+
+int federatedx_io_null::savepoint_set(ulong sp)
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::savepoint_release(ulong sp)
+{
+ return 0;
+}
+
+
+ulong federatedx_io_null::savepoint_rollback(ulong sp)
+{
+ return 0;
+}
+
+
+void federatedx_io_null::savepoint_restrict(ulong sp)
+{
+}
+
+
+int federatedx_io_null::query(const char *buffer, uint length)
+{
+ return 0;
+}
+
+
+size_t federatedx_io_null::max_query_size() const
+{
+ return INT_MAX;
+}
+
+
+my_ulonglong federatedx_io_null::affected_rows() const
+{
+ return 0;
+}
+
+
+my_ulonglong federatedx_io_null::last_insert_id() const
+{
+ return 0;
+}
+
+
+int federatedx_io_null::error_code()
+{
+ return 0;
+}
+
+
+const char *federatedx_io_null::error_str()
+{
+ return "";
+}
+
+
+FEDERATEDX_IO_RESULT *federatedx_io_null::store_result()
+{
+ FEDERATEDX_IO_RESULT *result;
+ DBUG_ENTER("federatedx_io_null::store_result");
+
+ result= NULL;
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_io_null::free_result(FEDERATEDX_IO_RESULT *)
+{
+}
+
+
+unsigned int federatedx_io_null::get_num_fields(FEDERATEDX_IO_RESULT *)
+{
+ return 0;
+}
+
+
+my_ulonglong federatedx_io_null::get_num_rows(FEDERATEDX_IO_RESULT *)
+{
+ return 0;
+}
+
+
+FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *)
+{
+ return NULL;
+}
+
+
+ulong *federatedx_io_null::fetch_lengths(FEDERATEDX_IO_RESULT *)
+{
+ return NULL;
+}
+
+
+const char *federatedx_io_null::get_column_data(FEDERATEDX_IO_ROW *,
+ unsigned int)
+{
+ return "";
+}
+
+
+bool federatedx_io_null::is_column_null(const FEDERATEDX_IO_ROW *,
+ unsigned int) const
+{
+ return true;
+}
+
+bool federatedx_io_null::table_metadata(ha_statistics *stats,
+ const char *table_name,
+ uint table_name_length, uint flag)
+{
+ stats->records= (ha_rows) 0;
+ stats->mean_rec_length= (ulong) 0;
+ stats->data_file_length= 0;
+
+ stats->update_time= (time_t) 0;
+ stats->check_time= (time_t) 0;
+
+ return 0;
+}
=== added file 'storage/federatedx/federatedx_probes.h'
--- a/storage/federatedx/federatedx_probes.h 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_probes.h 2009-10-30 18:50:56 +0000
@@ -0,0 +1,45 @@
+/*
+ * Generated by dtrace(1M).
+ */
+
+#ifndef _FEDERATED_PROBES_H
+#define _FEDERATED_PROBES_H
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if _DTRACE_VERSION
+
+#define FEDERATED_CLOSE() \
+ __dtrace_federated___close()
+#define FEDERATED_CLOSE_ENABLED() \
+ __dtraceenabled_federated___close()
+#define FEDERATED_OPEN() \
+ __dtrace_federated___open()
+#define FEDERATED_OPEN_ENABLED() \
+ __dtraceenabled_federated___open()
+
+
+extern void __dtrace_federated___close(void);
+extern int __dtraceenabled_federated___close(void);
+extern void __dtrace_federated___open(void);
+extern int __dtraceenabled_federated___open(void);
+
+#else
+
+#define FEDERATED_CLOSE()
+#define FEDERATED_CLOSE_ENABLED() (0)
+#define FEDERATED_OPEN()
+#define FEDERATED_OPEN_ENABLED() (0)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FEDERATED_PROBES_H */
=== added file 'storage/federatedx/federatedx_txn.cc'
--- a/storage/federatedx/federatedx_txn.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/federatedx_txn.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,424 @@
+/*
+Copyright (c) 2007, Antony T Curtis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of FederatedX nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*#define MYSQL_SERVER 1*/
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+
+federatedx_txn::federatedx_txn()
+ : txn_list(0), savepoint_level(0), savepoint_stmt(0), savepoint_next(0)
+{
+ DBUG_ENTER("federatedx_txn::federatedx_txn");
+ DBUG_VOID_RETURN;
+}
+
+federatedx_txn::~federatedx_txn()
+{
+ DBUG_ENTER("federatedx_txn::~federatedx_txn");
+ DBUG_ASSERT(!txn_list);
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_txn::close(FEDERATEDX_SERVER *server)
+{
+ uint count= 0;
+ federatedx_io *io, **iop;
+ DBUG_ENTER("federatedx_txn::close");
+
+ DBUG_ASSERT(!server->use_count);
+ DBUG_PRINT("info",("use count: %u connections: %u",
+ server->use_count, server->io_count));
+
+ for (iop= &txn_list; (io= *iop);)
+ {
+ if (io->server != server)
+ iop= &io->txn_next;
+ else
+ {
+ *iop= io->txn_next;
+ io->txn_next= NULL;
+ io->busy= FALSE;
+
+ io->idle_next= server->idle_list;
+ server->idle_list= io;
+ }
+ }
+
+ while ((io= server->idle_list))
+ {
+ server->idle_list= io->idle_next;
+ delete io;
+ count++;
+ }
+
+ DBUG_PRINT("info",("closed %u connections, txn_list: %s", count,
+ txn_list ? "active": "empty"));
+ DBUG_VOID_RETURN;
+}
+
+
+int federatedx_txn::acquire(FEDERATEDX_SHARE *share, bool readonly,
+ federatedx_io **ioptr)
+{
+ federatedx_io *io;
+ FEDERATEDX_SERVER *server= share->s;
+ DBUG_ENTER("federatedx_txn::acquire");
+ DBUG_ASSERT(ioptr && server);
+
+ if (!(io= *ioptr))
+ {
+ /* check to see if we have an available IO connection */
+ for (io= txn_list; io; io= io->txn_next)
+ if (io->server == server)
+ break;
+
+ if (!io)
+ {
+ /* check to see if there are any unowned IO connections */
+ pthread_mutex_lock(&server->mutex);
+ if ((io= server->idle_list))
+ {
+ server->idle_list= io->idle_next;
+ io->idle_next= NULL;
+ }
+ else
+ io= federatedx_io::construct(&server->mem_root, server);
+
+ io->txn_next= txn_list;
+ txn_list= io;
+
+ pthread_mutex_unlock(&server->mutex);
+ }
+
+ if (io->busy)
+ *io->owner_ptr= NULL;
+
+ io->busy= TRUE;
+ io->owner_ptr= ioptr;
+ }
+
+ DBUG_ASSERT(io->busy && io->server == server);
+
+ io->readonly&= readonly;
+
+ DBUG_RETURN((*ioptr= io) ? 0 : -1);
+}
+
+
+void federatedx_txn::release(federatedx_io **ioptr)
+{
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::release");
+ DBUG_ASSERT(ioptr);
+
+ if ((io= *ioptr))
+ {
+ /* mark as available for reuse in this transaction */
+ io->busy= FALSE;
+ *ioptr= NULL;
+
+ DBUG_PRINT("info", ("active: %d autocommit: %d",
+ io->active, io->is_autocommit()));
+
+ if (io->is_autocommit())
+ io->active= FALSE;
+ }
+
+ release_scan();
+
+ DBUG_VOID_RETURN;
+}
+
+
+void federatedx_txn::release_scan()
+{
+ uint count= 0, returned= 0;
+ federatedx_io *io, **pio;
+ DBUG_ENTER("federatedx_txn::release_scan");
+
+ /* return any inactive and idle connections to the server */
+ for (pio= &txn_list; (io= *pio); count++)
+ {
+ if (io->active || io->busy)
+ pio= &io->txn_next;
+ else
+ {
+ FEDERATEDX_SERVER *server= io->server;
+
+ /* unlink from list of connections bound to the transaction */
+ *pio= io->txn_next;
+ io->txn_next= NULL;
+
+ /* reset some values */
+ io->readonly= TRUE;
+
+ pthread_mutex_lock(&server->mutex);
+ io->idle_next= server->idle_list;
+ server->idle_list= io;
+ pthread_mutex_unlock(&server->mutex);
+ returned++;
+ }
+ }
+ DBUG_PRINT("info",("returned %u of %u connections(s)", returned, count));
+
+ DBUG_VOID_RETURN;
+}
+
+
+bool federatedx_txn::txn_begin()
+{
+ ulong level= 0;
+ DBUG_ENTER("federatedx_txn::txn_begin");
+
+ if (savepoint_next == 0)
+ {
+ savepoint_next++;
+ savepoint_level= savepoint_stmt= 0;
+ sp_acquire(&level);
+ }
+
+ DBUG_RETURN(level == 1);
+}
+
+
+int federatedx_txn::txn_commit()
+{
+ int error= 0;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::txn_commit");
+
+ if (savepoint_next)
+ {
+ DBUG_ASSERT(savepoint_stmt != 1);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ int rc= 0;
+
+ if (io->active)
+ rc= io->commit();
+ else
+ io->rollback();
+
+ if (io->active && rc)
+ error= -1;
+
+ io->reset();
+ }
+
+ release_scan();
+
+ savepoint_next= savepoint_stmt= savepoint_level= 0;
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int federatedx_txn::txn_rollback()
+{
+ int error= 0;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::txn_commit");
+
+ if (savepoint_next)
+ {
+ DBUG_ASSERT(savepoint_stmt != 1);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ int rc= io->rollback();
+
+ if (io->active && rc)
+ error= -1;
+
+ io->reset();
+ }
+
+ release_scan();
+
+ savepoint_next= savepoint_stmt= savepoint_level= 0;
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+bool federatedx_txn::sp_acquire(ulong *sp)
+{
+ bool rc= FALSE;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_acquire");
+ DBUG_ASSERT(sp && savepoint_next);
+
+ *sp= savepoint_level= savepoint_next++;
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ io->savepoint_set(savepoint_level);
+ rc= TRUE;
+ }
+
+ DBUG_RETURN(rc);
+}
+
+
+int federatedx_txn::sp_rollback(ulong *sp)
+{
+ ulong level, new_level= savepoint_level;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_rollback");
+ DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ if ((level= io->savepoint_rollback(*sp)) < new_level)
+ new_level= level;
+ }
+
+ savepoint_level= new_level;
+
+ DBUG_RETURN(0);
+}
+
+
+int federatedx_txn::sp_release(ulong *sp)
+{
+ ulong level, new_level= savepoint_level;
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::sp_release");
+ DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
+
+ for (io= txn_list; io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ if ((level= io->savepoint_release(*sp)) < new_level)
+ new_level= level;
+ }
+
+ savepoint_level= new_level;
+ *sp= 0;
+
+ DBUG_RETURN(0);
+}
+
+
+bool federatedx_txn::stmt_begin()
+{
+ bool result= FALSE;
+ DBUG_ENTER("federatedx_txn::stmt_begin");
+
+ if (!savepoint_stmt)
+ {
+ if (!savepoint_next)
+ {
+ savepoint_next++;
+ savepoint_level= savepoint_stmt= 0;
+ }
+ result= sp_acquire(&savepoint_stmt);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_txn::stmt_commit()
+{
+ int result= 0;
+ DBUG_ENTER("federatedx_txn::stmt_commit");
+
+ if (savepoint_stmt == 1)
+ {
+ savepoint_stmt= 0;
+ result= txn_commit();
+ }
+ else
+ if (savepoint_stmt)
+ result= sp_release(&savepoint_stmt);
+
+ DBUG_RETURN(result);
+}
+
+
+int federatedx_txn::stmt_rollback()
+{
+ int result= 0;
+ DBUG_ENTER("federated:txn::stmt_rollback");
+
+ if (savepoint_stmt == 1)
+ {
+ savepoint_stmt= 0;
+ result= txn_rollback();
+ }
+ else
+ if (savepoint_stmt)
+ {
+ result= sp_rollback(&savepoint_stmt);
+ sp_release(&savepoint_stmt);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+void federatedx_txn::stmt_autocommit()
+{
+ federatedx_io *io;
+ DBUG_ENTER("federatedx_txn::stmt_autocommit");
+
+ for (io= txn_list; savepoint_stmt && io; io= io->txn_next)
+ {
+ if (io->readonly)
+ continue;
+
+ io->savepoint_restrict(savepoint_stmt);
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
=== added file 'storage/federatedx/ha_federatedx.cc'
--- a/storage/federatedx/ha_federatedx.cc 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ha_federatedx.cc 2009-10-30 18:50:56 +0000
@@ -0,0 +1,3487 @@
+/*
+Copyright (c) 2008, Patrick Galbraith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Neither the name of Patrick Galbraith nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*
+
+ FederatedX Pluggable Storage Engine
+
+ ha_federatedx.cc - FederatedX Pluggable Storage Engine
+ Patrick Galbraith, 2008
+
+ This is a handler which uses a foreign database as the data file, as
+ opposed to a handler like MyISAM, which uses .MYD files locally.
+
+ How this handler works
+ ----------------------------------
+ Normal database files are local and as such: You create a table called
+ 'users', a file such as 'users.MYD' is created. A handler reads, inserts,
+ deletes, updates data in this file. The data is stored in particular format,
+ so to read, that data has to be parsed into fields, to write, fields have to
+ be stored in this format to write to this data file.
+
+ With FederatedX storage engine, there will be no local files
+ for each table's data (such as .MYD). A foreign database will store
+ the data that would normally be in this file. This will necessitate
+ the use of MySQL client API to read, delete, update, insert this
+ data. The data will have to be retrieve via an SQL call "SELECT *
+ FROM users". Then, to read this data, it will have to be retrieved
+ via mysql_fetch_row one row at a time, then converted from the
+ column in this select into the format that the handler expects.
+
+ The create table will simply create the .frm file, and within the
+ "CREATE TABLE" SQL, there SHALL be any of the following :
+
+ connection=scheme://username:password@hostname:port/database/tablename
+ connection=scheme://username@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+
+ - OR -
+
+ As of 5.1 federatedx now allows you to use a non-url
+ format, taking advantage of mysql.servers:
+
+ connection="connection_one"
+ connection="connection_one/table_foo"
+
+ An example would be:
+
+ connection=mysql://username:password@hostname:port/database/tablename
+
+ or, if we had:
+
+ create server 'server_one' foreign data wrapper 'mysql' options
+ (HOST '127.0.0.1',
+ DATABASE 'db1',
+ USER 'root',
+ PASSWORD '',
+ PORT 3306,
+ SOCKET '',
+ OWNER 'root');
+
+ CREATE TABLE federatedx.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(64) NOT NULL default ''
+ )
+ ENGINE="FEDERATEDX" DEFAULT CHARSET=latin1
+ CONNECTION='server_one';
+
+ So, this will have been the equivalent of
+
+ CONNECTION="mysql://root@127.0.0.1:3306/db1/t1"
+
+ Then, we can also change the server to point to a new schema:
+
+ ALTER SERVER 'server_one' options(DATABASE 'db2');
+
+ All subsequent calls will now be against db2.t1! Guess what? You don't
+ have to perform an alter table!
+
+ This connecton="connection string" is necessary for the handler to be
+ able to connect to the foreign server, either by URL, or by server
+ name.
+
+
+ The basic flow is this:
+
+ SQL calls issues locally ->
+ mysql handler API (data in handler format) ->
+ mysql client API (data converted to SQL calls) ->
+ foreign database -> mysql client API ->
+ convert result sets (if any) to handler format ->
+ handler API -> results or rows affected to local
+
+ What this handler does and doesn't support
+ ------------------------------------------
+ * Tables MUST be created on the foreign server prior to any action on those
+ tables via the handler, first version. IMPORTANT: IF you MUST use the
+ federatedx storage engine type on the REMOTE end, MAKE SURE [ :) ] That
+ the table you connect to IS NOT a table pointing BACK to your ORIGNAL
+ table! You know and have heard the screaching of audio feedback? You
+ know putting two mirror in front of each other how the reflection
+ continues for eternity? Well, need I say more?!
+ * There will not be support for transactions.
+ * There is no way for the handler to know if the foreign database or table
+ has changed. The reason for this is that this database has to work like a
+ data file that would never be written to by anything other than the
+ database. The integrity of the data in the local table could be breached
+ if there was any change to the foreign database.
+ * Support for SELECT, INSERT, UPDATE , DELETE, indexes.
+ * No ALTER TABLE, DROP TABLE or any other Data Definition Language calls.
+ * Prepared statements will not be used in the first implementation, it
+ remains to to be seen whether the limited subset of the client API for the
+ server supports this.
+ * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its
+ implementation.
+ * This will not work with the query cache.
+
+ Method calls
+
+ A two column table, with one record:
+
+ (SELECT)
+
+ "SELECT * FROM foo"
+ ha_federatedx::info
+ ha_federatedx::scan_time:
+ ha_federatedx::rnd_init: share->select_query SELECT * FROM foo
+ ha_federatedx::extra
+
+ <for every row of data retrieved>
+ ha_federatedx::rnd_next
+ ha_federatedx::convert_row_to_internal_format
+ ha_federatedx::rnd_next
+ </for every row of data retrieved>
+
+ ha_federatedx::rnd_end
+ ha_federatedx::extra
+ ha_federatedx::reset
+
+ (INSERT)
+
+ "INSERT INTO foo (id, ts) VALUES (2, now());"
+
+ ha_federatedx::write_row
+
+ ha_federatedx::reset
+
+ (UPDATE)
+
+ "UPDATE foo SET ts = now() WHERE id = 1;"
+
+ ha_federatedx::index_init
+ ha_federatedx::index_read
+ ha_federatedx::index_read_idx
+ ha_federatedx::rnd_next
+ ha_federatedx::convert_row_to_internal_format
+ ha_federatedx::update_row
+
+ ha_federatedx::extra
+ ha_federatedx::extra
+ ha_federatedx::extra
+ ha_federatedx::external_lock
+ ha_federatedx::reset
+
+
+ How do I use this handler?
+ --------------------------
+
+ <insert text about plugin storage engine>
+
+ Next, to use this handler, it's very simple. You must
+ have two databases running, either both on the same host, or
+ on different hosts.
+
+ One the server that will be connecting to the foreign
+ host (client), you create your table as such:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="FEDERATEDX"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:9306/federatedx/test_federatedx';
+
+ Notice the "COMMENT" and "ENGINE" field? This is where you
+ respectively set the engine type, "FEDERATEDX" and foreign
+ host information, this being the database your 'client' database
+ will connect to and use as the "data file". Obviously, the foreign
+ database is running on port 9306, so you want to start up your other
+ database so that it is indeed on port 9306, and your federatedx
+ database on a port other than that. In my setup, I use port 5554
+ for federatedx, and port 5555 for the foreign database.
+
+ Then, on the foreign database:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="<NAME>" <-- whatever you want, or not specify
+ DEFAULT CHARSET=latin1 ;
+
+ This table is exactly the same (and must be exactly the same),
+ except that it is not using the federatedx handler and does
+ not need the URL.
+
+
+ How to see the handler in action
+ --------------------------------
+
+ When developing this handler, I compiled the federatedx database with
+ debugging:
+
+ ./configure --with-federatedx-storage-engine
+ --prefix=/home/mysql/mysql-build/federatedx/ --with-debug
+
+ Once compiled, I did a 'make install' (not for the purpose of installing
+ the binary, but to install all the files the binary expects to see in the
+ diretory I specified in the build with --prefix,
+ "/home/mysql/mysql-build/federatedx".
+
+ Then, I started the foreign server:
+
+ /usr/local/mysql/bin/mysqld_safe
+ --user=mysql --log=/tmp/mysqld.5555.log -P 5555
+
+ Then, I went back to the directory containing the newly compiled mysqld,
+ <builddir>/sql/, started up gdb:
+
+ gdb ./mysqld
+
+ Then, withn the (gdb) prompt:
+ (gdb) run --gdb --port=5554 --socket=/tmp/mysqld.5554 --skip-innodb --debug
+
+ Next, I open several windows for each:
+
+ 1. Tail the debug trace: tail -f /tmp/mysqld.trace|grep ha_fed
+ 2. Tail the SQL calls to the foreign database: tail -f /tmp/mysqld.5555.log
+ 3. A window with a client open to the federatedx server on port 5554
+ 4. A window with a client open to the federatedx server on port 5555
+
+ I would create a table on the client to the foreign server on port
+ 5555, and then to the federatedx server on port 5554. At this point,
+ I would run whatever queries I wanted to on the federatedx server,
+ just always remembering that whatever changes I wanted to make on
+ the table, or if I created new tables, that I would have to do that
+ on the foreign server.
+
+ Another thing to look for is 'show variables' to show you that you have
+ support for federatedx handler support:
+
+ show variables like '%federat%'
+
+ and:
+
+ show storage engines;
+
+ Both should display the federatedx storage handler.
+
+
+ Testing
+ -------
+
+ Testing for FederatedX as a pluggable storage engine for
+ now is a manual process that I intend to build a test
+ suite that works for all pluggable storage engines.
+
+ How to test
+
+ 1. cp fed.dat /tmp
+ (make sure you have access to "test". Use a user that has
+ super privileges for now)
+ 2. mysql -f -u root test < federated.test > federated.myresult 2>&1
+ 3. diff federated.result federated.myresult (there _should_ be no differences)
+
+
+*/
+
+
+#define MYSQL_SERVER 1q
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "ha_federatedx.h"
+
+#include "m_string.h"
+
+#include <mysql/plugin.h>
+
+/* Variables for federatedx share methods */
+static HASH federatedx_open_tables; // To track open tables
+static HASH federatedx_open_servers; // To track open servers
+pthread_mutex_t federatedx_mutex; // To init the hash
+const char ident_quote_char= '`'; // Character for quoting
+ // identifiers
+const char value_quote_char= '\''; // Character for quoting
+ // literals
+static const int bulk_padding= 64; // bytes "overhead" in packet
+
+/* Variables used when chopping off trailing characters */
+static const uint sizeof_trailing_comma= sizeof(", ") - 1;
+static const uint sizeof_trailing_closeparen= sizeof(") ") - 1;
+static const uint sizeof_trailing_and= sizeof(" AND ") - 1;
+static const uint sizeof_trailing_where= sizeof(" WHERE ") - 1;
+
+/* Static declaration for handerton */
+static handler *federatedx_create_handler(handlerton *hton,
+ TABLE_SHARE *table,
+ MEM_ROOT *mem_root);
+
+/* FederatedX storage engine handlerton */
+
+static handler *federatedx_create_handler(handlerton *hton,
+ TABLE_SHARE *table,
+ MEM_ROOT *mem_root)
+{
+ return new (mem_root) ha_federatedx(hton, table);
+}
+
+
+/* Function we use in the creation of our hash to get key */
+
+static uchar *
+federatedx_share_get_key(FEDERATEDX_SHARE *share, size_t *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= share->share_key_length;
+ return (uchar*) share->share_key;
+}
+
+
+static uchar *
+federatedx_server_get_key(FEDERATEDX_SERVER *server, size_t *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= server->key_length;
+ return server->key;
+}
+
+
+/*
+ Initialize the federatedx handler.
+
+ SYNOPSIS
+ federatedx_db_init()
+ p Handlerton
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+int federatedx_db_init(void *p)
+{
+ DBUG_ENTER("federatedx_db_init");
+ handlerton *federatedx_hton= (handlerton *)p;
+ federatedx_hton->state= SHOW_OPTION_YES;
+ /* This is no longer needed for plugin storage engines */
+ federatedx_hton->db_type= DB_TYPE_DEFAULT;
+ federatedx_hton->savepoint_offset= sizeof(ulong);
+ federatedx_hton->close_connection= ha_federatedx::disconnect;
+ federatedx_hton->savepoint_set= ha_federatedx::savepoint_set;
+ federatedx_hton->savepoint_rollback= ha_federatedx::savepoint_rollback;
+ federatedx_hton->savepoint_release= ha_federatedx::savepoint_release;
+ federatedx_hton->commit= ha_federatedx::commit;
+ federatedx_hton->rollback= ha_federatedx::rollback;
+ federatedx_hton->create= federatedx_create_handler;
+ federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION;
+
+ if (pthread_mutex_init(&federatedx_mutex, MY_MUTEX_INIT_FAST))
+ goto error;
+ if (!hash_init(&federatedx_open_tables, &my_charset_bin, 32, 0, 0,
+ (hash_get_key) federatedx_share_get_key, 0, 0) &&
+ !hash_init(&federatedx_open_servers, &my_charset_bin, 32, 0, 0,
+ (hash_get_key) federatedx_server_get_key, 0, 0))
+ {
+ DBUG_RETURN(FALSE);
+ }
+
+ VOID(pthread_mutex_destroy(&federatedx_mutex));
+error:
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Release the federatedx handler.
+
+ SYNOPSIS
+ federatedx_db_end()
+
+ RETURN
+ FALSE OK
+*/
+
+int federatedx_done(void *p)
+{
+ hash_free(&federatedx_open_tables);
+ hash_free(&federatedx_open_servers);
+ VOID(pthread_mutex_destroy(&federatedx_mutex));
+
+ return 0;
+}
+
+/**
+ @brief Append identifiers to the string.
+
+ @param[in,out] string The target string.
+ @param[in] name Identifier name
+ @param[in] length Length of identifier name in bytes
+ @param[in] quote_char Quote char to use for quoting identifier.
+
+ @return Operation Status
+ @retval FALSE OK
+ @retval TRUE There was an error appending to the string.
+
+ @note This function is based upon the append_identifier() function
+ in sql_show.cc except that quoting always occurs.
+*/
+
+bool append_ident(String *string, const char *name, uint length,
+ const char quote_char)
+{
+ bool result;
+ uint clen;
+ const char *name_end;
+ DBUG_ENTER("append_ident");
+
+ if (quote_char)
+ {
+ string->reserve(length * 2 + 2);
+ if ((result= string->append("e_char, 1, system_charset_info)))
+ goto err;
+
+ for (name_end= name+length; name < name_end; name+= clen)
+ {
+ uchar c= *(uchar *) name;
+ if (!(clen= my_mbcharlen(system_charset_info, c)))
+ clen= 1;
+ if (clen == 1 && c == (uchar) quote_char &&
+ (result= string->append("e_char, 1, system_charset_info)))
+ goto err;
+ if ((result= string->append(name, clen, string->charset())))
+ goto err;
+ }
+ result= string->append("e_char, 1, system_charset_info);
+ }
+ else
+ result= string->append(name, length, system_charset_info);
+
+err:
+ DBUG_RETURN(result);
+}
+
+
+static int parse_url_error(FEDERATEDX_SHARE *share, TABLE *table, int error_num)
+{
+ char buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ int buf_len;
+ DBUG_ENTER("ha_federatedx parse_url_error");
+
+ buf_len= min(table->s->connect_string.length,
+ FEDERATEDX_QUERY_BUFFER_SIZE-1);
+ strmake(buf, table->s->connect_string.str, buf_len);
+ my_error(error_num, MYF(0), buf);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ retrieve server object which contains server meta-data
+ from the system table given a server's name, set share
+ connection parameter members
+*/
+int get_connection(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share)
+{
+ int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ FOREIGN_SERVER *server, server_buffer;
+ DBUG_ENTER("ha_federatedx::get_connection");
+
+ /*
+ get_server_by_name() clones the server if exists and allocates
+ copies of strings in the supplied mem_root
+ */
+ if (!(server=
+ get_server_by_name(mem_root, share->connection_string, &server_buffer)))
+ {
+ DBUG_PRINT("info", ("get_server_by_name returned > 0 error condition!"));
+ /* need to come up with error handling */
+ error_num=1;
+ goto error;
+ }
+ DBUG_PRINT("info", ("get_server_by_name returned server at %lx",
+ (long unsigned int) server));
+
+ /*
+ Most of these should never be empty strings, error handling will
+ need to be implemented. Also, is this the best way to set the share
+ members? Is there some allocation needed? In running this code, it works
+ except there are errors in the trace file of the share being overrun
+ at the address of the share.
+ */
+ share->server_name_length= server->server_name_length;
+ share->server_name= server->server_name;
+ share->username= server->username;
+ share->password= server->password;
+ share->database= server->db;
+#ifndef I_AM_PARANOID
+ share->port= server->port > 0 && server->port < 65536 ?
+#else
+ share->port= server->port > 1023 && server->port < 65536 ?
+#endif
+ (ushort) server->port : MYSQL_PORT;
+ share->hostname= server->host;
+ if (!(share->socket= server->socket) &&
+ !strcmp(share->hostname, my_localhost))
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ share->scheme= server->scheme;
+
+ DBUG_PRINT("info", ("share->username: %s", share->username));
+ DBUG_PRINT("info", ("share->password: %s", share->password));
+ DBUG_PRINT("info", ("share->hostname: %s", share->hostname));
+ DBUG_PRINT("info", ("share->database: %s", share->database));
+ DBUG_PRINT("info", ("share->port: %d", share->port));
+ DBUG_PRINT("info", ("share->socket: %s", share->socket));
+ DBUG_RETURN(0);
+
+error:
+ my_sprintf(error_buffer,
+ (error_buffer, "server name: '%s' doesn't exist!",
+ share->connection_string));
+ my_error(error_num, MYF(0), error_buffer);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ Parse connection info from table->s->connect_string
+
+ SYNOPSIS
+ parse_url()
+ mem_root MEM_ROOT pointer for memory allocation
+ share pointer to FEDERATEDX share
+ table pointer to current TABLE class
+ table_create_flag determines what error to throw
+
+ DESCRIPTION
+ Populates the share with information about the connection
+ to the foreign database that will serve as the data source.
+ This string must be specified (currently) in the "CONNECTION" field,
+ listed in the CREATE TABLE statement.
+
+ This string MUST be in the format of any of these:
+
+ CONNECTION="scheme://username:password@hostname:port/database/table"
+ CONNECTION="scheme://username@hostname/database/table"
+ CONNECTION="scheme://username@hostname:port/database/table"
+ CONNECTION="scheme://username:password@hostname/database/table"
+
+ _OR_
+
+ CONNECTION="connection name"
+
+
+
+ An Example:
+
+ CREATE TABLE t1 (id int(32))
+ ENGINE="FEDERATEDX"
+ CONNECTION="mysql://joe:joespass@192.168.1.111:9308/federatedx/testtable";
+
+ CREATE TABLE t2 (
+ id int(4) NOT NULL auto_increment,
+ name varchar(32) NOT NULL,
+ PRIMARY KEY(id)
+ ) ENGINE="FEDERATEDX" CONNECTION="my_conn";
+
+ ***IMPORTANT***
+ Currently, the FederatedX Storage Engine only supports connecting to another
+ Database ("scheme" of "mysql"). Connections using JDBC as well as
+ other connectors are in the planning stage.
+
+
+ 'password' and 'port' are both optional.
+
+ RETURN VALUE
+ 0 success
+ error_num particular error code
+
+*/
+
+static int parse_url(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share, TABLE *table,
+ uint table_create_flag)
+{
+ uint error_num= (table_create_flag ?
+ ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE :
+ ER_FOREIGN_DATA_STRING_INVALID);
+ DBUG_ENTER("ha_federatedx::parse_url");
+
+ share->port= 0;
+ share->socket= 0;
+ DBUG_PRINT("info", ("share at %lx", (long unsigned int) share));
+ DBUG_PRINT("info", ("Length: %u", (uint) table->s->connect_string.length));
+ DBUG_PRINT("info", ("String: '%.*s'", (int) table->s->connect_string.length,
+ table->s->connect_string.str));
+ share->connection_string= strmake_root(mem_root, table->s->connect_string.str,
+ table->s->connect_string.length);
+
+ DBUG_PRINT("info",("parse_url alloced share->connection_string %lx",
+ (long unsigned int) share->connection_string));
+
+ DBUG_PRINT("info",("share->connection_string: %s",share->connection_string));
+ /*
+ No :// or @ in connection string. Must be a straight connection name of
+ either "servername" or "servername/tablename"
+ */
+ if ((!strstr(share->connection_string, "://") &&
+ (!strchr(share->connection_string, '@'))))
+ {
+
+ DBUG_PRINT("info",
+ ("share->connection_string: %s internal format "
+ "share->connection_string: %lx",
+ share->connection_string,
+ (ulong) share->connection_string));
+
+ /* ok, so we do a little parsing, but not completely! */
+ share->parsed= FALSE;
+ /*
+ If there is a single '/' in the connection string, this means the user is
+ specifying a table name
+ */
+
+ if ((share->table_name= strchr(share->connection_string, '/')))
+ {
+ *share->table_name++= '\0';
+ share->table_name_length= strlen(share->table_name);
+
+ DBUG_PRINT("info",
+ ("internal format, parsed table_name "
+ "share->connection_string: %s share->table_name: %s",
+ share->connection_string, share->table_name));
+
+ /*
+ there better not be any more '/'s !
+ */
+ if (strchr(share->table_name, '/'))
+ goto error;
+ }
+ /*
+ Otherwise, straight server name, use tablename of federatedx table
+ as remote table name
+ */
+ else
+ {
+ /*
+ Connection specifies everything but, resort to
+ expecting remote and foreign table names to match
+ */
+ share->table_name= strmake_root(mem_root, table->s->table_name.str,
+ (share->table_name_length=
+ table->s->table_name.length));
+ DBUG_PRINT("info",
+ ("internal format, default table_name "
+ "share->connection_string: %s share->table_name: %s",
+ share->connection_string, share->table_name));
+ }
+
+ if ((error_num= get_connection(mem_root, share)))
+ goto error;
+ }
+ else
+ {
+ share->parsed= TRUE;
+ // Add a null for later termination of table name
+ share->connection_string[table->s->connect_string.length]= 0;
+ share->scheme= share->connection_string;
+ DBUG_PRINT("info",("parse_url alloced share->scheme: %lx",
+ (ulong) share->scheme));
+
+ /*
+ Remove addition of null terminator and store length
+ for each string in share
+ */
+ if (!(share->username= strstr(share->scheme, "://")))
+ goto error;
+ share->scheme[share->username - share->scheme]= '\0';
+
+ if (!federatedx_io::handles_scheme(share->scheme))
+ goto error;
+
+ share->username+= 3;
+
+ if (!(share->hostname= strchr(share->username, '@')))
+ goto error;
+ *share->hostname++= '\0'; // End username
+
+ if ((share->password= strchr(share->username, ':')))
+ {
+ *share->password++= '\0'; // End username
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
+ goto error;
+ /*
+ Found that if the string is:
+ user:@hostname:port/db/table
+ Then password is a null string, so set to NULL
+ */
+ if ((share->password[0] == '\0'))
+ share->password= NULL;
+ }
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
+ goto error;
+
+ if (!(share->database= strchr(share->hostname, '/')))
+ goto error;
+ *share->database++= '\0';
+
+ if ((share->sport= strchr(share->hostname, ':')))
+ {
+ *share->sport++= '\0';
+ if (share->sport[0] == '\0')
+ share->sport= NULL;
+ else
+ share->port= atoi(share->sport);
+ }
+
+ if (!(share->table_name= strchr(share->database, '/')))
+ goto error;
+ *share->table_name++= '\0';
+
+ share->table_name_length= strlen(share->table_name);
+
+ /* make sure there's not an extra / */
+ if ((strchr(share->table_name, '/')))
+ goto error;
+
+ if (share->hostname[0] == '\0')
+ share->hostname= NULL;
+
+ }
+ if (!share->port)
+ {
+ if (!share->hostname || strcmp(share->hostname, my_localhost) == 0)
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ else
+ share->port= MYSQL_PORT;
+ }
+
+ DBUG_PRINT("info",
+ ("scheme: %s username: %s password: %s hostname: %s "
+ "port: %d db: %s tablename: %s",
+ share->scheme, share->username, share->password,
+ share->hostname, share->port, share->database,
+ share->table_name));
+
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(parse_url_error(share, table, error_num));
+}
+
+/*****************************************************************************
+** FEDERATEDX tables
+*****************************************************************************/
+
+ha_federatedx::ha_federatedx(handlerton *hton,
+ TABLE_SHARE *table_arg)
+ :handler(hton, table_arg),
+ txn(0), io(0), stored_result(0)
+{
+ bzero(&bulk_insert, sizeof(bulk_insert));
+}
+
+
+/*
+ Convert MySQL result set row to handler internal format
+
+ SYNOPSIS
+ convert_row_to_internal_format()
+ record Byte pointer to record
+ row MySQL result set row from fetchrow()
+ result Result set to use
+
+ DESCRIPTION
+ This method simply iterates through a row returned via fetchrow with
+ values from a successful SELECT , and then stores each column's value
+ in the field object via the field object pointer (pointing to the table's
+ array of field object pointers). This is how the handler needs the data
+ to be stored to then return results back to the user
+
+ RETURN VALUE
+ 0 After fields have had field values stored from record
+*/
+
+uint ha_federatedx::convert_row_to_internal_format(uchar *record,
+ FEDERATEDX_IO_ROW *row,
+ FEDERATEDX_IO_RESULT *result)
+{
+ ulong *lengths;
+ Field **field;
+ int column= 0;
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
+ DBUG_ENTER("ha_federatedx::convert_row_to_internal_format");
+
+ lengths= io->fetch_lengths(result);
+
+ for (field= table->field; *field; field++, column++)
+ {
+ /*
+ index variable to move us through the row at the
+ same iterative step as the field
+ */
+ my_ptrdiff_t old_ptr;
+ old_ptr= (my_ptrdiff_t) (record - table->record[0]);
+ (*field)->move_field_offset(old_ptr);
+ if (io->is_column_null(row, column))
+ (*field)->set_null();
+ else
+ {
+ if (bitmap_is_set(table->read_set, (*field)->field_index))
+ {
+ (*field)->set_notnull();
+ (*field)->store(io->get_column_data(row, column), lengths[column], &my_charset_bin);
+ }
+ }
+ (*field)->move_field_offset(-old_ptr);
+ }
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_name(String *to, KEY_PART_INFO *part)
+{
+ DBUG_ENTER("emit_key_part_name");
+ if (append_ident(to, part->field->field_name,
+ strlen(part->field->field_name), ident_quote_char))
+ DBUG_RETURN(1); // Out of memory
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_element(String *to, KEY_PART_INFO *part,
+ bool needs_quotes, bool is_like,
+ const uchar *ptr, uint len)
+{
+ Field *field= part->field;
+ DBUG_ENTER("emit_key_part_element");
+
+ if (needs_quotes && to->append(STRING_WITH_LEN("'")))
+ DBUG_RETURN(1);
+
+ if (part->type == HA_KEYTYPE_BIT)
+ {
+ char buff[STRING_BUFFER_USUAL_SIZE], *buf= buff;
+
+ *buf++= '0';
+ *buf++= 'x';
+ buf= octet2hex(buf, (char*) ptr, len);
+ if (to->append((char*) buff, (uint)(buf - buff)))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_BLOB_PART)
+ {
+ String blob;
+ uint blob_length= uint2korr(ptr);
+ blob.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ blob_length, &my_charset_bin);
+ if (append_escaped(to, &blob))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ String varchar;
+ uint var_length= uint2korr(ptr);
+ varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ var_length, &my_charset_bin);
+ if (append_escaped(to, &varchar))
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ char strbuff[MAX_FIELD_WIDTH];
+ String str(strbuff, sizeof(strbuff), part->field->charset()), *res;
+
+ res= field->val_str(&str, ptr);
+
+ if (field->result_type() == STRING_RESULT)
+ {
+ if (append_escaped(to, res))
+ DBUG_RETURN(1);
+ }
+ else if (to->append(res->ptr(), res->length()))
+ DBUG_RETURN(1);
+ }
+
+ if (is_like && to->append(STRING_WITH_LEN("%")))
+ DBUG_RETURN(1);
+
+ if (needs_quotes && to->append(STRING_WITH_LEN("'")))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Create a WHERE clause based off of values in keys
+ Note: This code was inspired by key_copy from key.cc
+
+ SYNOPSIS
+ create_where_from_key ()
+ to String object to store WHERE clause
+ key_info KEY struct pointer
+ key byte pointer containing key
+ key_length length of key
+ range_type 0 - no range, 1 - min range, 2 - max range
+ (see enum range_operation)
+
+ DESCRIPTION
+ Using iteration through all the keys via a KEY_PART_INFO pointer,
+ This method 'extracts' the value of each key in the byte pointer
+ *key, and for each key found, constructs an appropriate WHERE clause
+
+ RETURN VALUE
+ 0 After all keys have been accounted for to create the WHERE clause
+ 1 No keys found
+
+ Range flags Table per Timour:
+
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_OR_NEXT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+
+ records_in_range:
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_EXACT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+ * "=" -> HA_READ_AFTER_KEY
+
+0 HA_READ_KEY_EXACT, Find first record else error
+1 HA_READ_KEY_OR_NEXT, Record or next record
+2 HA_READ_KEY_OR_PREV, Record or previous
+3 HA_READ_AFTER_KEY, Find next rec. after key-record
+4 HA_READ_BEFORE_KEY, Find next rec. before key-record
+5 HA_READ_PREFIX, Key which as same prefix
+6 HA_READ_PREFIX_LAST, Last key with the same prefix
+7 HA_READ_PREFIX_LAST_OR_PREV, Last or prev key with the same prefix
+
+Flags that I've found:
+
+id, primary key, varchar
+
+id = 'ccccc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 'ccccc'
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id < 'ccccc'
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 'ccccc'
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id >= 'ccccc'
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id like 'cc%cc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id < 'ccccc'
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 'aaaaa' and id < 'ccccc';
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+numeric keys:
+
+id = 4
+index_read_idx: start_key 0 end_key NULL
+
+id > 4
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4
+full table scan, select * from
+
+id > 2 and id < 8
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 8
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 8
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 8
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+multi keys (id int, name varchar, other varchar)
+
+id = 1;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 4;
+id > 2 and name = '333'; remote: id > 2
+id > 2 and name > '333'; remote: id > 2
+id > 2 and name > '333' and other < 'ddd'; remote: id > 2 no results
+id > 2 and name >= '333' and other < 'ddd'; remote: id > 2 1 result
+id >= 4 and name = 'eric was here' and other > 'eeee';
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4;
+id >= 2 and name = '333' and other < 'ddd';
+remote: `id` >= 2 AND `name` >= '333';
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4;
+id < 3 and name = '222' and other <= 'ccc'; remote: id < 3
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4;
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4;
+full table scan
+
+id > 2 and id < 4;
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 4;
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 4;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 4;
+id = 6 and name = 'eric was here' and other > 'eeee';
+remote: (`id` > 6 AND `name` > 'eric was here' AND `other` > 'eeee')
+AND (`id` <= 6) AND ( AND `name` <= 'eric was here')
+no results
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+Summary:
+
+* If the start key flag is 0 the max key flag shouldn't even be set,
+ and if it is, the query produced would be invalid.
+* Multipart keys, even if containing some or all numeric columns,
+ are treated the same as non-numeric keys
+
+ If the query is " = " (quotes or not):
+ - records in range start key flag HA_READ_KEY_EXACT,
+ end key flag HA_READ_AFTER_KEY (incorrect)
+ - any other: start key flag HA_READ_KEY_OR_NEXT,
+ end key flag HA_READ_AFTER_KEY (correct)
+
+* 'like' queries (of key)
+ - Numeric, full table scan
+ - Non-numeric
+ records_in_range: start_key 0 end_key 3
+ other : start_key 1 end_key 3
+
+* If the key flag is HA_READ_AFTER_KEY:
+ if start_key, append >
+ if end_key, append <=
+
+* If create_where_key was called by records_in_range:
+
+ - if the key is numeric:
+ start key flag is 0 when end key is NULL, end key flag is 3 or 4
+ - if create_where_key was called by any other function:
+ start key flag is 1 when end key is NULL, end key flag is 3 or 4
+ - if the key is non-numeric, or multipart
+ When the query is an exact match, the start key flag is 0,
+ end key flag is 3 for what should be a no-range condition where
+ you should have 0 and max key NULL, which it is if called by
+ read_range_first
+
+Conclusion:
+
+1. Need logic to determin if a key is min or max when the flag is
+HA_READ_AFTER_KEY, and handle appending correct operator accordingly
+
+2. Need a boolean flag to pass to create_where_from_key, used in the
+switch statement. Add 1 to the flag if:
+ - start key flag is HA_READ_KEY_EXACT and the end key is NULL
+
+*/
+
+bool ha_federatedx::create_where_from_key(String *to,
+ KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool from_records_in_range,
+ bool eq_range)
+{
+ bool both_not_null=
+ (start_key != NULL && end_key != NULL) ? TRUE : FALSE;
+ const uchar *ptr;
+ uint remainder, length;
+ char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info);
+ const key_range *ranges[2]= { start_key, end_key };
+ my_bitmap_map *old_map;
+ DBUG_ENTER("ha_federatedx::create_where_from_key");
+
+ tmp.length(0);
+ if (start_key == NULL && end_key == NULL)
+ DBUG_RETURN(1);
+
+ old_map= dbug_tmp_use_all_columns(table, table->write_set);
+ for (uint i= 0; i <= 1; i++)
+ {
+ bool needs_quotes;
+ KEY_PART_INFO *key_part;
+ if (ranges[i] == NULL)
+ continue;
+
+ if (both_not_null)
+ {
+ if (i > 0)
+ tmp.append(STRING_WITH_LEN(") AND ("));
+ else
+ tmp.append(STRING_WITH_LEN(" ("));
+ }
+
+ for (key_part= key_info->key_part,
+ remainder= key_info->key_parts,
+ length= ranges[i]->length,
+ ptr= ranges[i]->key; ;
+ remainder--,
+ key_part++)
+ {
+ Field *field= key_part->field;
+ uint store_length= key_part->store_length;
+ uint part_length= min(store_length, length);
+ needs_quotes= field->str_needs_quotes();
+ DBUG_DUMP("key, start of loop", ptr, length);
+
+ if (key_part->null_bit)
+ {
+ if (*ptr++)
+ {
+ /*
+ We got "IS [NOT] NULL" condition against nullable column. We
+ distinguish between "IS NOT NULL" and "IS NULL" by flag. For
+ "IS NULL", flag is set to HA_READ_KEY_EXACT.
+ */
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(ranges[i]->flag == HA_READ_KEY_EXACT ?
+ " IS NULL " : " IS NOT NULL "))
+ goto err;
+ /*
+ We need to adjust pointer and length to be prepared for next
+ key part. As well as check if this was last key part.
+ */
+ goto prepare_for_next_key_part;
+ }
+ }
+
+ if (tmp.append(STRING_WITH_LEN(" (")))
+ goto err;
+
+ switch (ranges[i]->flag) {
+ case HA_READ_KEY_EXACT:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_EXACT %d", i));
+ if (store_length >= length ||
+ !needs_quotes ||
+ key_part->type == HA_KEYTYPE_BIT ||
+ field->result_type() != STRING_RESULT)
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ goto err;
+
+ if (from_records_in_range)
+ {
+ if (tmp.append(STRING_WITH_LEN(" >= ")))
+ goto err;
+ }
+ else
+ {
+ if (tmp.append(STRING_WITH_LEN(" = ")))
+ goto err;
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ }
+ else
+ {
+ /* LIKE */
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" LIKE ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 1, ptr,
+ part_length))
+ goto err;
+ }
+ break;
+ case HA_READ_AFTER_KEY:
+ if (eq_range)
+ {
+ if (tmp.append("1=1")) // Dummy
+ goto err;
+ break;
+ }
+ DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i));
+ if (store_length >= length) /* end key */
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ goto err;
+
+ if (i > 0) /* end key */
+ {
+ if (tmp.append(STRING_WITH_LEN(" <= ")))
+ goto err;
+ }
+ else /* start key */
+ {
+ if (tmp.append(STRING_WITH_LEN(" > ")))
+ goto err;
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ {
+ goto err;
+ }
+ break;
+ }
+ case HA_READ_KEY_OR_NEXT:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_NEXT %d", i));
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" >= ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ case HA_READ_BEFORE_KEY:
+ DBUG_PRINT("info", ("federatedx HA_READ_BEFORE_KEY %d", i));
+ if (store_length >= length)
+ {
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" < ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ }
+ case HA_READ_KEY_OR_PREV:
+ DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_PREV %d", i));
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(STRING_WITH_LEN(" <= ")) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ goto err;
+ break;
+ default:
+ DBUG_PRINT("info",("cannot handle flag %d", ranges[i]->flag));
+ goto err;
+ }
+ if (tmp.append(STRING_WITH_LEN(") ")))
+ goto err;
+
+prepare_for_next_key_part:
+ if (store_length >= length)
+ break;
+ DBUG_PRINT("info", ("remainder %d", remainder));
+ DBUG_ASSERT(remainder > 1);
+ length-= store_length;
+ /*
+ For nullable columns, null-byte is already skipped before, that is
+ ptr was incremented by 1. Since store_length still counts null-byte,
+ we need to subtract 1 from store_length.
+ */
+ ptr+= store_length - test(key_part->null_bit);
+ if (tmp.append(STRING_WITH_LEN(" AND ")))
+ goto err;
+
+ DBUG_PRINT("info",
+ ("create_where_from_key WHERE clause: %s",
+ tmp.c_ptr_quick()));
+ }
+ }
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+
+ if (both_not_null)
+ if (tmp.append(STRING_WITH_LEN(") ")))
+ DBUG_RETURN(1);
+
+ if (to->append(STRING_WITH_LEN(" WHERE ")))
+ DBUG_RETURN(1);
+
+ if (to->append(tmp))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+
+err:
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ DBUG_RETURN(1);
+}
+
+static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server,
+ FEDERATEDX_SHARE *share, CHARSET_INFO *table_charset)
+{
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String key(buffer, sizeof(buffer), &my_charset_bin);
+ String scheme(share->scheme, &my_charset_latin1);
+ String hostname(share->hostname, &my_charset_latin1);
+ String database(share->database, system_charset_info);
+ String username(share->username, system_charset_info);
+ String socket(share->socket ? share->socket : "", files_charset_info);
+ String password(share->password ? share->password : "", &my_charset_bin);
+ DBUG_ENTER("fill_server");
+
+ /* Do some case conversions */
+ scheme.reserve(scheme.length());
+ scheme.length(my_casedn_str(&my_charset_latin1, scheme.c_ptr_safe()));
+
+ hostname.reserve(hostname.length());
+ hostname.length(my_casedn_str(&my_charset_latin1, hostname.c_ptr_safe()));
+
+ if (lower_case_table_names)
+ {
+ database.reserve(database.length());
+ database.length(my_casedn_str(system_charset_info, database.c_ptr_safe()));
+ }
+
+ if (lower_case_file_system && socket.length())
+ {
+ socket.reserve(socket.length());
+ socket.length(my_casedn_str(files_charset_info, socket.c_ptr_safe()));
+ }
+
+ /* start with all bytes zeroed */
+ bzero(server, sizeof(*server));
+
+ key.length(0);
+ key.reserve(scheme.length() + hostname.length() + database.length() +
+ socket.length() + username.length() + password.length() +
+ sizeof(int) + 8);
+ key.append(scheme);
+ key.q_append('\0');
+ server->hostname= (const char *) (intptr) key.length();
+ key.append(hostname);
+ key.q_append('\0');
+ server->database= (const char *) (intptr) key.length();
+ key.append(database);
+ key.q_append('\0');
+ key.q_append((uint32) share->port);
+ server->socket= (const char *) (intptr) key.length();
+ key.append(socket);
+ key.q_append('\0');
+ server->username= (const char *) (intptr) key.length();
+ key.append(username);
+ key.q_append('\0');
+ server->password= (const char *) (intptr) key.length();
+ key.append(password);
+
+ server->key_length= key.length();
+ server->key= (uchar *) memdup_root(mem_root, key.ptr(), key.length()+1);
+
+ /* pointer magic */
+ server->scheme+= (intptr) server->key;
+ server->hostname+= (intptr) server->key;
+ server->database+= (intptr) server->key;
+ server->username+= (intptr) server->key;
+ server->password+= (intptr) server->key;
+ server->socket+= (intptr) server->key;
+ server->port= share->port;
+
+ if (!share->socket)
+ server->socket= NULL;
+ if (!share->password)
+ server->password= NULL;
+
+ if (table_charset)
+ server->csname= strdup_root(mem_root, table_charset->csname);
+
+ DBUG_VOID_RETURN;
+}
+
+
+static FEDERATEDX_SERVER *get_server(FEDERATEDX_SHARE *share, TABLE *table)
+{
+ FEDERATEDX_SERVER *server= NULL, tmp_server;
+ MEM_ROOT mem_root;
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String key(buffer, sizeof(buffer), &my_charset_bin);
+ String scheme(share->scheme, &my_charset_latin1);
+ String hostname(share->hostname, &my_charset_latin1);
+ String database(share->database, system_charset_info);
+ String username(share->username, system_charset_info);
+ String socket(share->socket ? share->socket : "", files_charset_info);
+ String password(share->password ? share->password : "", &my_charset_bin);
+ DBUG_ENTER("ha_federated.cc::get_server");
+
+ safe_mutex_assert_owner(&federatedx_mutex);
+
+ init_alloc_root(&mem_root, 4096, 4096);
+
+ fill_server(&mem_root, &tmp_server, share, table ? table->s->table_charset : 0);
+
+ if (!(server= (FEDERATEDX_SERVER *) hash_search(&federatedx_open_servers,
+ tmp_server.key,
+ tmp_server.key_length)))
+ {
+ if (!table || !tmp_server.csname)
+ goto error;
+
+ if (!(server= (FEDERATEDX_SERVER *) memdup_root(&mem_root,
+ (char *) &tmp_server,
+ sizeof(*server))))
+ goto error;
+
+ server->mem_root= mem_root;
+
+ if (my_hash_insert(&federatedx_open_servers, (uchar*) server))
+ goto error;
+
+ pthread_mutex_init(&server->mutex, MY_MUTEX_INIT_FAST);
+ }
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
+ server->use_count++;
+
+ DBUG_RETURN(server);
+error:
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
+}
+
+
+/*
+ Example of simple lock controls. The "share" it creates is structure we will
+ pass to each federatedx handler. Do you have to have one of these? Well, you
+ have pieces that are used for locking, and they are needed to function.
+*/
+
+static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
+{
+ char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ Field **field;
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ FEDERATEDX_SHARE *share= NULL, tmp_share;
+ MEM_ROOT mem_root;
+ DBUG_ENTER("ha_federatedx.cc::get_share");
+
+ /*
+ In order to use this string, we must first zero it's length,
+ or it will contain garbage
+ */
+ query.length(0);
+
+ bzero(&tmp_share, sizeof(tmp_share));
+ init_alloc_root(&mem_root, 256, 0);
+
+ pthread_mutex_lock(&federatedx_mutex);
+
+ tmp_share.share_key= table_name;
+ tmp_share.share_key_length= strlen(table_name);
+ if (parse_url(&mem_root, &tmp_share, table, 0))
+ goto error;
+
+ /* TODO: change tmp_share.scheme to LEX_STRING object */
+ if (!(share= (FEDERATEDX_SHARE *) hash_search(&federatedx_open_tables,
+ (uchar*) tmp_share.share_key,
+ tmp_share.
+ share_key_length)))
+ {
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("SELECT "));
+ for (field= table->field; *field; field++)
+ {
+ append_ident(&query, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+ query.append(STRING_WITH_LEN(", "));
+ }
+ /* chops off trailing comma */
+ query.length(query.length() - sizeof_trailing_comma);
+
+ query.append(STRING_WITH_LEN(" FROM "));
+
+ append_ident(&query, tmp_share.table_name,
+ tmp_share.table_name_length, ident_quote_char);
+
+ if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
+ !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length() + 1)))
+ goto error;
+
+ share->mem_root= mem_root;
+
+ DBUG_PRINT("info",
+ ("share->select_query %s", share->select_query));
+
+ if (!(share->s= get_server(share, table)))
+ goto error;
+
+ if (my_hash_insert(&federatedx_open_tables, (uchar*) share))
+ goto error;
+ thr_lock_init(&share->lock);
+ }
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
+ share->use_count++;
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ DBUG_RETURN(share);
+
+error:
+ pthread_mutex_unlock(&federatedx_mutex);
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
+}
+
+
+static int free_server(federatedx_txn *txn, FEDERATEDX_SERVER *server)
+{
+ bool destroy;
+ DBUG_ENTER("free_server");
+
+ pthread_mutex_lock(&federatedx_mutex);
+ if ((destroy= !--server->use_count))
+ hash_delete(&federatedx_open_servers, (uchar*) server);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (destroy)
+ {
+ MEM_ROOT mem_root;
+
+ txn->close(server);
+
+ DBUG_ASSERT(server->io_count == 0);
+
+ pthread_mutex_destroy(&server->mutex);
+ mem_root= server->mem_root;
+ free_root(&mem_root, MYF(0));
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Free lock controls. We call this whenever we close a table.
+ If the table had the last reference to the share then we
+ free memory associated with it.
+*/
+
+static int free_share(federatedx_txn *txn, FEDERATEDX_SHARE *share)
+{
+ bool destroy;
+ DBUG_ENTER("free_share");
+
+ pthread_mutex_lock(&federatedx_mutex);
+ if ((destroy= !--share->use_count))
+ hash_delete(&federatedx_open_tables, (uchar*) share);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (destroy)
+ {
+ MEM_ROOT mem_root;
+ FEDERATEDX_SERVER *server= share->s;
+
+ thr_lock_delete(&share->lock);
+
+ mem_root= share->mem_root;
+ free_root(&mem_root, MYF(0));
+
+ free_server(txn, server);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+ha_rows ha_federatedx::records_in_range(uint inx, key_range *start_key,
+ key_range *end_key)
+{
+ /*
+
+ We really want indexes to be used as often as possible, therefore
+ we just need to hard-code the return value to a very low number to
+ force the issue
+
+*/
+ DBUG_ENTER("ha_federatedx::records_in_range");
+ DBUG_RETURN(FEDERATEDX_RECORDS_IN_RANGE);
+}
+/*
+ If frm_error() is called then we will use this to to find out
+ what file extentions exist for the storage engine. This is
+ also used by the default rename_table and delete_table method
+ in handler.cc.
+*/
+
+const char **ha_federatedx::bas_ext() const
+{
+ static const char *ext[]=
+ {
+ NullS
+ };
+ return ext;
+}
+
+
+federatedx_txn *ha_federatedx::get_txn(THD *thd, bool no_create)
+{
+ federatedx_txn **txnp= (federatedx_txn **) ha_data(thd);
+ if (!*txnp && !no_create)
+ *txnp= new federatedx_txn();
+ return *txnp;
+}
+
+
+int ha_federatedx::disconnect(handlerton *hton, MYSQL_THD thd)
+{
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ delete txn;
+ return 0;
+}
+
+
+/*
+ Used for opening tables. The name will be the name of the file.
+ A table is opened when it needs to be opened. For instance
+ when a request comes in for a select on the table (tables are not
+ open and closed for each request, they are cached).
+
+ Called from handler.cc by handler::ha_open(). The server opens
+ all tables by calling ha_open() which then calls the handler
+ specific open().
+*/
+
+int ha_federatedx::open(const char *name, int mode, uint test_if_locked)
+{
+ int error;
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::open");
+
+ if (!(share= get_share(name, table)))
+ DBUG_RETURN(1);
+ thr_lock_data_init(&share->lock, &lock, NULL);
+
+ DBUG_ASSERT(io == NULL);
+
+ txn= get_txn(thd);
+
+ if ((error= txn->acquire(share, TRUE, &io)))
+ {
+ free_share(txn, share);
+ DBUG_RETURN(error);
+ }
+
+ txn->release(&io);
+
+ ref_length= (table->s->primary_key != MAX_KEY ?
+ table->key_info[table->s->primary_key].key_length :
+ table->s->reclength);
+ DBUG_PRINT("info", ("ref_length: %u", ref_length));
+
+ reset();
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Closes a table. We call the free_share() function to free any resources
+ that we have allocated in the "shared" structure.
+
+ Called from sql_base.cc, sql_select.cc, and table.cc.
+ In sql_select.cc it is only used to close up temporary tables or during
+ the process where a temporary table is converted over to being a
+ myisam table.
+ For sql_base.cc look at close_data_tables().
+*/
+
+int ha_federatedx::close(void)
+{
+ int retval, error;
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::close");
+
+ /* free the result set */
+ if (stored_result)
+ retval= free_result();
+
+ /* Disconnect from mysql */
+ if ((txn= get_txn(thd, true)))
+ txn->release(&io);
+
+ DBUG_ASSERT(io == NULL);
+
+ if ((error= free_share(txn, share)))
+ retval= error;
+ DBUG_RETURN(retval);
+}
+
+/*
+
+ Checks if a field in a record is SQL NULL.
+
+ SYNOPSIS
+ field_in_record_is_null()
+ table TABLE pointer, MySQL table object
+ field Field pointer, MySQL field object
+ record char pointer, contains record
+
+ DESCRIPTION
+ This method uses the record format information in table to track
+ the null bit in record.
+
+ RETURN VALUE
+ 1 if NULL
+ 0 otherwise
+*/
+
+static inline uint field_in_record_is_null(TABLE *table,
+ Field *field,
+ char *record)
+{
+ int null_offset;
+ DBUG_ENTER("ha_federatedx::field_in_record_is_null");
+
+ if (!field->null_ptr)
+ DBUG_RETURN(0);
+
+ null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]);
+
+ if (record[null_offset] & field->null_bit)
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Construct the INSERT statement.
+
+ @details This method will construct the INSERT statement and appends it to
+ the supplied query string buffer.
+
+ @return
+ @retval FALSE No error
+ @retval TRUE Failure
+*/
+
+bool ha_federatedx::append_stmt_insert(String *query)
+{
+ char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ Field **field;
+ uint tmp_length;
+ bool added_field= FALSE;
+
+ /* The main insert query string */
+ String insert_string(insert_buffer, sizeof(insert_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::append_stmt_insert");
+
+ insert_string.length(0);
+
+ if (replace_duplicates)
+ insert_string.append(STRING_WITH_LEN("REPLACE INTO "));
+ else if (ignore_duplicates && !insert_dup_update)
+ insert_string.append(STRING_WITH_LEN("INSERT IGNORE INTO "));
+ else
+ insert_string.append(STRING_WITH_LEN("INSERT INTO "));
+ append_ident(&insert_string, share->table_name, share->table_name_length,
+ ident_quote_char);
+ tmp_length= insert_string.length();
+ insert_string.append(STRING_WITH_LEN(" ("));
+
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that match the current query id
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ /* append the field name */
+ append_ident(&insert_string, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic if *(fields + 1) to
+ make the following appends conditional as we don't know if the
+ next field is in the write set
+ */
+ insert_string.append(STRING_WITH_LEN(", "));
+ added_field= TRUE;
+ }
+ }
+
+ if (added_field)
+ {
+ /* Remove trailing comma. */
+ insert_string.length(insert_string.length() - sizeof_trailing_comma);
+ insert_string.append(STRING_WITH_LEN(") "));
+ }
+ else
+ {
+ /* If there were no fields, we don't want to add a closing paren. */
+ insert_string.length(tmp_length);
+ }
+
+ insert_string.append(STRING_WITH_LEN(" VALUES "));
+
+ DBUG_RETURN(query->append(insert_string));
+}
+
+
+/*
+ write_row() inserts a row. No extra() hint is given currently if a bulk load
+ is happeneding. buf() is a byte array of data. You can use the field
+ information to extract the data from the native byte array type.
+ Example of this would be:
+ for (Field **field=table->field ; *field ; field++)
+ {
+ ...
+ }
+
+ Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
+ sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::write_row(uchar *buf)
+{
+ char values_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ Field **field;
+ uint tmp_length;
+ int error= 0;
+ bool use_bulk_insert;
+ bool auto_increment_update_required= (table->next_number_field != NULL);
+
+ /* The string containing the values to be added to the insert */
+ String values_string(values_buffer, sizeof(values_buffer), &my_charset_bin);
+ /* The actual value of the field, to be added to the values_string */
+ String insert_field_value_string(insert_field_value_buffer,
+ sizeof(insert_field_value_buffer),
+ &my_charset_bin);
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+ DBUG_ENTER("ha_federatedx::write_row");
+
+ values_string.length(0);
+ insert_field_value_string.length(0);
+ ha_statistic_increment(&SSV::ha_write_count);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
+
+ /*
+ start both our field and field values strings
+ We must disable multi-row insert for "INSERT...ON DUPLICATE KEY UPDATE"
+ Ignore duplicates is always true when insert_dup_update is true.
+ When replace_duplicates == TRUE, we can safely enable multi-row insert.
+ When performing multi-row insert, we only collect the columns values for
+ the row. The start of the statement is only created when the first
+ row is copied in to the bulk_insert string.
+ */
+ if (!(use_bulk_insert= bulk_insert.str &&
+ (!insert_dup_update || replace_duplicates)))
+ append_stmt_insert(&values_string);
+
+ values_string.append(STRING_WITH_LEN(" ("));
+ tmp_length= values_string.length();
+
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that is part of the write set
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ if ((*field)->is_null())
+ values_string.append(STRING_WITH_LEN(" NULL "));
+ else
+ {
+ bool needs_quote= (*field)->str_needs_quotes();
+ (*field)->val_str(&insert_field_value_string);
+ if (needs_quote)
+ values_string.append(value_quote_char);
+ insert_field_value_string.print(&values_string);
+ if (needs_quote)
+ values_string.append(value_quote_char);
+
+ insert_field_value_string.length(0);
+ }
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic if *(fields + 1) to
+ make the following appends conditional as we don't know if the
+ next field is in the write set
+ */
+ values_string.append(STRING_WITH_LEN(", "));
+ }
+ }
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+
+ /*
+ if there were no fields, we don't want to add a closing paren
+ AND, we don't want to chop off the last char '('
+ insert will be "INSERT INTO t1 VALUES ();"
+ */
+ if (values_string.length() > tmp_length)
+ {
+ /* chops off trailing comma */
+ values_string.length(values_string.length() - sizeof_trailing_comma);
+ }
+ /* we always want to append this, even if there aren't any fields */
+ values_string.append(STRING_WITH_LEN(") "));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (use_bulk_insert)
+ {
+ /*
+ Send the current bulk insert out if appending the current row would
+ cause the statement to overflow the packet size, otherwise set
+ auto_increment_update_required to FALSE as no query was executed.
+ */
+ if (bulk_insert.length + values_string.length() + bulk_padding >
+ io->max_query_size() && bulk_insert.length)
+ {
+ error= io->query(bulk_insert.str, bulk_insert.length);
+ bulk_insert.length= 0;
+ }
+ else
+ auto_increment_update_required= FALSE;
+
+ if (bulk_insert.length == 0)
+ {
+ char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String insert_string(insert_buffer, sizeof(insert_buffer),
+ &my_charset_bin);
+ insert_string.length(0);
+ append_stmt_insert(&insert_string);
+ dynstr_append_mem(&bulk_insert, insert_string.ptr(),
+ insert_string.length());
+ }
+ else
+ dynstr_append_mem(&bulk_insert, ",", 1);
+
+ dynstr_append_mem(&bulk_insert, values_string.ptr(),
+ values_string.length());
+ }
+ else
+ {
+ error= io->query(values_string.ptr(), values_string.length());
+ }
+
+ if (error)
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ /*
+ If the table we've just written a record to contains an auto_increment
+ field, then store the last_insert_id() value from the foreign server
+ */
+ if (auto_increment_update_required)
+ {
+ update_auto_increment();
+
+ /* mysql_insert() uses this for protocol return value */
+ table->next_number_field->store(stats.auto_increment_value, 1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Prepares the storage engine for bulk inserts.
+
+ @param[in] rows estimated number of rows in bulk insert
+ or 0 if unknown.
+
+ @details Initializes memory structures required for bulk insert.
+*/
+
+void ha_federatedx::start_bulk_insert(ha_rows rows)
+{
+ uint page_size;
+ DBUG_ENTER("ha_federatedx::start_bulk_insert");
+
+ dynstr_free(&bulk_insert);
+
+ /**
+ We don't bother with bulk-insert semantics when the estimated rows == 1
+ The rows value will be 0 if the server does not know how many rows
+ would be inserted. This can occur when performing INSERT...SELECT
+ */
+
+ if (rows == 1)
+ DBUG_VOID_RETURN;
+
+ /*
+ Make sure we have an open connection so that we know the
+ maximum packet size.
+ */
+ if (txn->acquire(share, FALSE, &io))
+ DBUG_VOID_RETURN;
+
+ page_size= (uint) my_getpagesize();
+
+ if (init_dynamic_string(&bulk_insert, NULL, page_size, page_size))
+ DBUG_VOID_RETURN;
+
+ bulk_insert.length= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief End bulk insert.
+
+ @details This method will send any remaining rows to the remote server.
+ Finally, it will deinitialize the bulk insert data structure.
+
+ @return Operation status
+ @retval 0 No error
+ @retval != 0 Error occured at remote server. Also sets my_errno.
+*/
+
+int ha_federatedx::end_bulk_insert(bool abort)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::end_bulk_insert");
+
+ if (bulk_insert.str && bulk_insert.length && !abort)
+ {
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+ if (io->query(bulk_insert.str, bulk_insert.length))
+ error= stash_remote_error();
+ else
+ if (table->next_number_field)
+ update_auto_increment();
+ }
+
+ dynstr_free(&bulk_insert);
+
+ DBUG_RETURN(my_errno= error);
+}
+
+
+/*
+ ha_federatedx::update_auto_increment
+
+ This method ensures that last_insert_id() works properly. What it simply does
+ is calls last_insert_id() on the foreign database immediately after insert
+ (if the table has an auto_increment field) and sets the insert id via
+ thd->insert_id(ID)).
+*/
+void ha_federatedx::update_auto_increment(void)
+{
+ THD *thd= current_thd;
+ DBUG_ENTER("ha_federatedx::update_auto_increment");
+
+ ha_federatedx::info(HA_STATUS_AUTO);
+ thd->first_successful_insert_id_in_cur_stmt=
+ stats.auto_increment_value;
+ DBUG_PRINT("info",("last_insert_id: %ld", (long) stats.auto_increment_value));
+
+ DBUG_VOID_RETURN;
+}
+
+int ha_federatedx::optimize(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ int error= 0;
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::optimize");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("OPTIMIZE TABLE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ error= stash_remote_error();
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::repair(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ int error= 0;
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::repair");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("REPAIR TABLE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+ if (check_opt->flags & T_QUICK)
+ query.append(STRING_WITH_LEN(" QUICK"));
+ if (check_opt->flags & T_EXTEND)
+ query.append(STRING_WITH_LEN(" EXTENDED"));
+ if (check_opt->sql_flags & TT_USEFRM)
+ query.append(STRING_WITH_LEN(" USE_FRM"));
+
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ error= stash_remote_error();
+
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Yes, update_row() does what you expect, it updates a row. old_data will have
+ the previous row record in it, while new_data will have the newest data in
+ it.
+
+ Keep in mind that the server can do updates based on ordering if an ORDER BY
+ clause was used. Consecutive ordering is not guaranteed.
+ Currently new_data will not have an updated auto_increament record, or
+ and updated timestamp field. You can do these for federatedx by doing these:
+ if (table->timestamp_on_update_now)
+ update_timestamp(new_row+table->timestamp_on_update_now-1);
+ if (table->next_number_field && record == table->record[0])
+ update_auto_increment();
+
+ Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
+*/
+
+int ha_federatedx::update_row(const uchar *old_data, uchar *new_data)
+{
+ /*
+ This used to control how the query was built. If there was a
+ primary key, the query would be built such that there was a where
+ clause with only that column as the condition. This is flawed,
+ because if we have a multi-part primary key, it would only use the
+ first part! We don't need to do this anyway, because
+ read_range_first will retrieve the correct record, which is what
+ is used to build the WHERE clause. We can however use this to
+ append a LIMIT to the end if there is NOT a primary key. Why do
+ this? Because we only are updating one record, and LIMIT enforces
+ this.
+ */
+ bool has_a_primary_key= test(table->s->primary_key != MAX_KEY);
+
+ /*
+ buffers for following strings
+ */
+ char field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char update_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char where_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+
+ /* Work area for field values */
+ String field_value(field_value_buffer, sizeof(field_value_buffer),
+ &my_charset_bin);
+ /* stores the update query */
+ String update_string(update_buffer,
+ sizeof(update_buffer),
+ &my_charset_bin);
+ /* stores the WHERE clause */
+ String where_string(where_buffer,
+ sizeof(where_buffer),
+ &my_charset_bin);
+ uchar *record= table->record[0];
+ int error;
+ DBUG_ENTER("ha_federatedx::update_row");
+ /*
+ set string lengths to 0 to avoid misc chars in string
+ */
+ field_value.length(0);
+ update_string.length(0);
+ where_string.length(0);
+
+ if (ignore_duplicates)
+ update_string.append(STRING_WITH_LEN("UPDATE IGNORE "));
+ else
+ update_string.append(STRING_WITH_LEN("UPDATE "));
+ append_ident(&update_string, share->table_name,
+ share->table_name_length, ident_quote_char);
+ update_string.append(STRING_WITH_LEN(" SET "));
+
+ /*
+ In this loop, we want to match column names to values being inserted
+ (while building INSERT statement).
+
+ Iterate through table->field (new data) and share->old_field (old_data)
+ using the same index to create an SQL UPDATE statement. New data is
+ used to create SET field=value and old data is used to create WHERE
+ field=oldvalue
+ */
+
+ for (Field **field= table->field; *field; field++)
+ {
+ if (bitmap_is_set(table->write_set, (*field)->field_index))
+ {
+ uint field_name_length= strlen((*field)->field_name);
+ append_ident(&update_string, (*field)->field_name, field_name_length,
+ ident_quote_char);
+ update_string.append(STRING_WITH_LEN(" = "));
+
+ if ((*field)->is_null())
+ update_string.append(STRING_WITH_LEN(" NULL "));
+ else
+ {
+ /* otherwise = */
+ my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
+ bool needs_quote= (*field)->str_needs_quotes();
+ (*field)->val_str(&field_value);
+ if (needs_quote)
+ update_string.append(value_quote_char);
+ field_value.print(&update_string);
+ if (needs_quote)
+ update_string.append(value_quote_char);
+ field_value.length(0);
+ tmp_restore_column_map(table->read_set, old_map);
+ }
+ update_string.append(STRING_WITH_LEN(", "));
+ }
+
+ if (bitmap_is_set(table->read_set, (*field)->field_index))
+ {
+ uint field_name_length= strlen((*field)->field_name);
+ append_ident(&where_string, (*field)->field_name, field_name_length,
+ ident_quote_char);
+ if (field_in_record_is_null(table, *field, (char*) old_data))
+ where_string.append(STRING_WITH_LEN(" IS NULL "));
+ else
+ {
+ bool needs_quote= (*field)->str_needs_quotes();
+ where_string.append(STRING_WITH_LEN(" = "));
+ (*field)->val_str(&field_value,
+ (old_data + (*field)->offset(record)));
+ if (needs_quote)
+ where_string.append(value_quote_char);
+ field_value.print(&where_string);
+ if (needs_quote)
+ where_string.append(value_quote_char);
+ field_value.length(0);
+ }
+ where_string.append(STRING_WITH_LEN(" AND "));
+ }
+ }
+
+ /* Remove last ', '. This works as there must be at least on updated field */
+ update_string.length(update_string.length() - sizeof_trailing_comma);
+
+ if (where_string.length())
+ {
+ /* chop off trailing AND */
+ where_string.length(where_string.length() - sizeof_trailing_and);
+ update_string.append(STRING_WITH_LEN(" WHERE "));
+ update_string.append(where_string);
+ }
+
+ /*
+ If this table has not a primary key, then we could possibly
+ update multiple rows. We want to make sure to only update one!
+ */
+ if (!has_a_primary_key)
+ update_string.append(STRING_WITH_LEN(" LIMIT 1"));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(update_string.ptr(), update_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ This will delete a row. 'buf' will contain a copy of the row to be =deleted.
+ The server will call this right after the current row has been called (from
+ either a previous rnd_next() or index call).
+ If you keep a pointer to the last row or can access a primary key it will
+ make doing the deletion quite a bit easier.
+ Keep in mind that the server does no guarentee consecutive deletions.
+ ORDER BY clauses can be used.
+
+ Called in sql_acl.cc and sql_udf.cc to manage internal table information.
+ Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select
+ it is used for removing duplicates while in insert it is used for REPLACE
+ calls.
+*/
+
+int ha_federatedx::delete_row(const uchar *buf)
+{
+ char delete_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char data_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String delete_string(delete_buffer, sizeof(delete_buffer), &my_charset_bin);
+ String data_string(data_buffer, sizeof(data_buffer), &my_charset_bin);
+ uint found= 0;
+ int error;
+ DBUG_ENTER("ha_federatedx::delete_row");
+
+ delete_string.length(0);
+ delete_string.append(STRING_WITH_LEN("DELETE FROM "));
+ append_ident(&delete_string, share->table_name,
+ share->table_name_length, ident_quote_char);
+ delete_string.append(STRING_WITH_LEN(" WHERE "));
+
+ for (Field **field= table->field; *field; field++)
+ {
+ Field *cur_field= *field;
+ found++;
+ if (bitmap_is_set(table->read_set, cur_field->field_index))
+ {
+ append_ident(&delete_string, (*field)->field_name,
+ strlen((*field)->field_name), ident_quote_char);
+ data_string.length(0);
+ if (cur_field->is_null())
+ {
+ delete_string.append(STRING_WITH_LEN(" IS NULL "));
+ }
+ else
+ {
+ bool needs_quote= cur_field->str_needs_quotes();
+ delete_string.append(STRING_WITH_LEN(" = "));
+ cur_field->val_str(&data_string);
+ if (needs_quote)
+ delete_string.append(value_quote_char);
+ data_string.print(&delete_string);
+ if (needs_quote)
+ delete_string.append(value_quote_char);
+ }
+ delete_string.append(STRING_WITH_LEN(" AND "));
+ }
+ }
+
+ // Remove trailing AND
+ delete_string.length(delete_string.length() - sizeof_trailing_and);
+ if (!found)
+ delete_string.length(delete_string.length() - sizeof_trailing_where);
+
+ delete_string.append(STRING_WITH_LEN(" LIMIT 1"));
+ DBUG_PRINT("info",
+ ("Delete sql: %s", delete_string.c_ptr_quick()));
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(delete_string.ptr(), delete_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ stats.deleted+= (ha_rows) io->affected_rows();
+ stats.records-= (ha_rows) io->affected_rows();
+ DBUG_PRINT("info",
+ ("rows deleted %ld rows deleted for all time %ld",
+ (long) io->affected_rows(), (long) stats.deleted));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Positions an index cursor to the index specified in the handle. Fetches the
+ row if available. If the key value is null, begin at the first key of the
+ index. This method, which is called in the case of an SQL statement having
+ a WHERE clause on a non-primary key index, simply calls index_read_idx.
+*/
+
+int ha_federatedx::index_read(uchar *buf, const uchar *key,
+ uint key_len, ha_rkey_function find_flag)
+{
+ DBUG_ENTER("ha_federatedx::index_read");
+
+ if (stored_result)
+ (void) free_result();
+ DBUG_RETURN(index_read_idx_with_result_set(buf, active_index, key,
+ key_len, find_flag,
+ &stored_result));
+}
+
+
+/*
+ Positions an index cursor to the index specified in key. Fetches the
+ row if any. This is only used to read whole keys.
+
+ This method is called via index_read in the case of a WHERE clause using
+ a primary key index OR is called DIRECTLY when the WHERE clause
+ uses a PRIMARY KEY index.
+
+ NOTES
+ This uses an internal result set that is deleted before function
+ returns. We need to be able to be callable from ha_rnd_pos()
+*/
+
+int ha_federatedx::index_read_idx(uchar *buf, uint index, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ int retval;
+ FEDERATEDX_IO_RESULT *io_result;
+ DBUG_ENTER("ha_federatedx::index_read_idx");
+
+ if ((retval= index_read_idx_with_result_set(buf, index, key,
+ key_len, find_flag,
+ &io_result)))
+ DBUG_RETURN(retval);
+ /* io is correct, as index_read_idx_with_result_set was ok */
+ io->free_result(io_result);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ Create result set for rows matching query and return first row
+
+ RESULT
+ 0 ok In this case *result will contain the result set
+ table->status == 0
+ # error In this case *result will contain 0
+ table->status == STATUS_NOT_FOUND
+*/
+
+int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index,
+ const uchar *key,
+ uint key_len,
+ ha_rkey_function find_flag,
+ FEDERATEDX_IO_RESULT **result)
+{
+ int retval;
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ char index_value[STRING_BUFFER_USUAL_SIZE];
+ char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String index_string(index_value,
+ sizeof(index_value),
+ &my_charset_bin);
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ key_range range;
+ DBUG_ENTER("ha_federatedx::index_read_idx_with_result_set");
+
+ *result= 0; // In case of errors
+ index_string.length(0);
+ sql_query.length(0);
+ ha_statistic_increment(&SSV::ha_read_key_count);
+
+ sql_query.append(share->select_query);
+
+ range.key= key;
+ range.length= key_len;
+ range.flag= find_flag;
+ create_where_from_key(&index_string,
+ &table->key_info[index],
+ &range,
+ NULL, 0, 0);
+ sql_query.append(index_string);
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ if (io->query(sql_query.ptr(), sql_query.length()))
+ {
+ my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
+ io->error_code(), io->error_str()));
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ if (!(*result= io->store_result()))
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+ if (!(retval= read_next(buf, *result)))
+ DBUG_RETURN(retval);
+
+ io->free_result(*result);
+ *result= 0;
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ my_error(retval, MYF(0), error_buffer);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ This method is used exlusevely by filesort() to check if we
+ can create sorting buffers of necessary size.
+ If the handler returns more records that it declares
+ here server can just crash on filesort().
+ We cannot guarantee that's not going to happen with
+ the FEDERATEDX engine, as we have records==0 always if the
+ client is a VIEW, and for the table the number of
+ records can inpredictably change during execution.
+ So we return maximum possible value here.
+*/
+
+ha_rows ha_federatedx::estimate_rows_upper_bound()
+{
+ return HA_POS_ERROR;
+}
+
+
+/* Initialized at each key walk (called multiple times unlike rnd_init()) */
+
+int ha_federatedx::index_init(uint keynr, bool sorted)
+{
+ DBUG_ENTER("ha_federatedx::index_init");
+ DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr));
+ active_index= keynr;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Read first range
+*/
+
+int ha_federatedx::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range_arg, bool sorted)
+{
+ char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ int retval;
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ DBUG_ENTER("ha_federatedx::read_range_first");
+
+ DBUG_ASSERT(!(start_key == NULL && end_key == NULL));
+
+ sql_query.length(0);
+ sql_query.append(share->select_query);
+ create_where_from_key(&sql_query,
+ &table->key_info[active_index],
+ start_key, end_key, 0, eq_range_arg);
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ if (stored_result)
+ {
+ io->free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (io->query(sql_query.ptr(), sql_query.length()))
+ {
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ sql_query.length(0);
+
+ if (!(stored_result= io->store_result()))
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+
+ retval= read_next(table->record[0], stored_result);
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(retval);
+}
+
+
+int ha_federatedx::read_range_next()
+{
+ int retval;
+ DBUG_ENTER("ha_federatedx::read_range_next");
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+}
+
+
+/* Used to read forward through the index. */
+int ha_federatedx::index_next(uchar *buf)
+{
+ DBUG_ENTER("ha_federatedx::index_next");
+ ha_statistic_increment(&SSV::ha_read_next_count);
+ DBUG_RETURN(read_next(buf, stored_result));
+}
+
+
+/*
+ rnd_init() is called when the system wants the storage engine to do a table
+ scan.
+
+ This is the method that gets data for the SELECT calls.
+
+ See the federatedx in the introduction at the top of this file to see when
+ rnd_init() is called.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::rnd_init(bool scan)
+{
+ DBUG_ENTER("ha_federatedx::rnd_init");
+ /*
+ The use of the 'scan' flag is incredibly important for this handler
+ to work properly, especially with updates containing WHERE clauses
+ using indexed columns.
+
+ When the initial query contains a WHERE clause of the query using an
+ indexed column, it's index_read_idx that selects the exact record from
+ the foreign database.
+
+ When there is NO index in the query, either due to not having a WHERE
+ clause, or the WHERE clause is using columns that are not indexed, a
+ 'full table scan' done by rnd_init, which in this situation simply means
+ a 'select * from ...' on the foreign table.
+
+ In other words, this 'scan' flag gives us the means to ensure that if
+ there is an index involved in the query, we want index_read_idx to
+ retrieve the exact record (scan flag is 0), and do not want rnd_init
+ to do a 'full table scan' and wipe out that result set.
+
+ Prior to using this flag, the problem was most apparent with updates.
+
+ An initial query like 'UPDATE tablename SET anything = whatever WHERE
+ indexedcol = someval', index_read_idx would get called, using a query
+ constructed with a WHERE clause built from the values of index ('indexcol'
+ in this case, having a value of 'someval'). mysql_store_result would
+ then get called (this would be the result set we want to use).
+
+ After this rnd_init (from sql_update.cc) would be called, it would then
+ unecessarily call "select * from table" on the foreign table, then call
+ mysql_store_result, which would wipe out the correct previous result set
+ from the previous call of index_read_idx's that had the result set
+ containing the correct record, hence update the wrong row!
+
+ */
+
+ if (scan)
+ {
+ int error;
+
+ if ((error= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(error);
+
+ if (stored_result)
+ {
+ io->free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (io->query(share->select_query,
+ strlen(share->select_query)))
+ goto error;
+
+ stored_result= io->store_result();
+ if (!stored_result)
+ goto error;
+ }
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(stash_remote_error());
+}
+
+
+int ha_federatedx::rnd_end()
+{
+ DBUG_ENTER("ha_federatedx::rnd_end");
+ DBUG_RETURN(index_end());
+}
+
+
+int ha_federatedx::free_result()
+{
+ int error;
+ DBUG_ASSERT(stored_result);
+ if ((error= txn->acquire(share, FALSE, &io)))
+ {
+ DBUG_ASSERT(0); // Fail when testing
+ return error;
+ }
+ io->free_result(stored_result);
+ stored_result= 0;
+ return 0;
+}
+
+int ha_federatedx::index_end(void)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::index_end");
+ if (stored_result)
+ error= free_result();
+ active_index= MAX_KEY;
+ DBUG_RETURN(error);
+}
+
+
+/*
+ This is called for each row of the table scan. When you run out of records
+ you should return HA_ERR_END_OF_FILE. Fill buff up with the row information.
+ The Field structure for the table is the key to getting data into buf
+ in a manner that will allow the server to understand it.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federatedx::rnd_next(uchar *buf)
+{
+ DBUG_ENTER("ha_federatedx::rnd_next");
+
+ if (stored_result == 0)
+ {
+ /*
+ Return value of rnd_init is not always checked (see records.cc),
+ so we can get here _even_ if there is _no_ pre-fetched result-set!
+ TODO: fix it. We can delete this in 5.1 when rnd_init() is checked.
+ */
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(read_next(buf, stored_result));
+}
+
+
+/*
+ ha_federatedx::read_next
+
+ reads from a result set and converts to mysql internal
+ format
+
+ SYNOPSIS
+ field_in_record_is_null()
+ buf byte pointer to record
+ result mysql result set
+
+ DESCRIPTION
+ This method is a wrapper method that reads one record from a result
+ set and converts it to the internal table format
+
+ RETURN VALUE
+ 1 error
+ 0 no error
+*/
+
+int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result)
+{
+ int retval;
+ FEDERATEDX_IO_ROW *row;
+ DBUG_ENTER("ha_federatedx::read_next");
+
+ table->status= STATUS_NOT_FOUND; // For easier return
+
+ if ((retval= txn->acquire(share, TRUE, &io)))
+ DBUG_RETURN(retval);
+
+ /* Fetch a row, insert it back in a row format. */
+ if (!(row= io->fetch_row(result)))
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ if (!(retval= convert_row_to_internal_format(buf, row, result)))
+ table->status= 0;
+
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ store reference to current row so that we can later find it for
+ a re-read, update or delete.
+
+ In case of federatedx, a reference is either a primary key or
+ the whole record.
+
+ Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
+*/
+
+void ha_federatedx::position(const uchar *record)
+{
+ DBUG_ENTER("ha_federatedx::position");
+ if (table->s->primary_key != MAX_KEY)
+ key_copy(ref, (uchar *)record, table->key_info + table->s->primary_key,
+ ref_length);
+ else
+ memcpy(ref, record, ref_length);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This is like rnd_next, but you are given a position to use to determine the
+ row. The position will be of the type that you stored in ref.
+
+ This method is required for an ORDER BY
+
+ Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
+*/
+
+int ha_federatedx::rnd_pos(uchar *buf, uchar *pos)
+{
+ int result;
+ DBUG_ENTER("ha_federatedx::rnd_pos");
+ ha_statistic_increment(&SSV::ha_read_rnd_count);
+ if (table->s->primary_key != MAX_KEY)
+ {
+ /* We have a primary key, so use index_read_idx to find row */
+ result= index_read_idx(buf, table->s->primary_key, pos,
+ ref_length, HA_READ_KEY_EXACT);
+ }
+ else
+ {
+ /* otherwise, get the old record ref as obtained in ::position */
+ memcpy(buf, pos, ref_length);
+ result= 0;
+ }
+ table->status= result ? STATUS_NOT_FOUND : 0;
+ DBUG_RETURN(result);
+}
+
+
+/*
+ ::info() is used to return information to the optimizer.
+ Currently this table handler doesn't implement most of the fields
+ really needed. SHOW also makes use of this data
+ Another note, you will probably want to have the following in your
+ code:
+ if (records < 2)
+ records = 2;
+ The reason is that the server will optimize for cases of only a single
+ record. If in a table scan you don't know the number of records
+ it will probably be better to set records to two so you can return
+ as many records as you need.
+ Along with records a few more variables you may wish to set are:
+ records
+ deleted
+ data_file_length
+ index_file_length
+ delete_length
+ check_time
+ Take a look at the public variables in handler.h for more information.
+
+ Called in:
+ filesort.cc
+ ha_heap.cc
+ item_sum.cc
+ opt_sum.cc
+ sql_delete.cc
+ sql_delete.cc
+ sql_derived.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_table.cc
+ sql_union.cc
+ sql_update.cc
+
+*/
+
+int ha_federatedx::info(uint flag)
+{
+ char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ uint error_code;
+ federatedx_io *tmp_io= 0;
+ DBUG_ENTER("ha_federatedx::info");
+
+ error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+
+ /* we want not to show table status if not needed to do so */
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO))
+ {
+ if ((error_code= txn->acquire(share, TRUE, &tmp_io)))
+ goto fail;
+ }
+
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST))
+ {
+ /*
+ size of IO operations (This is based on a good guess, no high science
+ involved)
+ */
+ if (flag & HA_STATUS_CONST)
+ stats.block_size= 4096;
+
+ if (tmp_io->table_metadata(&stats, share->table_name,
+ share->table_name_length, flag))
+ goto error;
+ }
+
+ if (flag & HA_STATUS_AUTO)
+ stats.auto_increment_value= tmp_io->last_insert_id();
+
+ /*
+ If ::info created it's own transaction, close it. This happens in case
+ of show table status;
+ */
+ txn->release(&tmp_io);
+
+ DBUG_RETURN(0);
+
+error:
+ if (tmp_io)
+ {
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ tmp_io->error_code(), tmp_io->error_str()));
+ my_error(error_code, MYF(0), error_buffer);
+ }
+ else
+ if (remote_error_number != -1 /* error already reported */)
+ {
+ error_code= remote_error_number;
+ my_error(error_code, MYF(0), ER(error_code));
+ }
+fail:
+ txn->release(&tmp_io);
+ DBUG_RETURN(error_code);
+}
+
+
+/**
+ @brief Handles extra signals from MySQL server
+
+ @param[in] operation Hint for storage engine
+
+ @return Operation Status
+ @retval 0 OK
+ */
+int ha_federatedx::extra(ha_extra_function operation)
+{
+ DBUG_ENTER("ha_federatedx::extra");
+ switch (operation) {
+ case HA_EXTRA_IGNORE_DUP_KEY:
+ ignore_duplicates= TRUE;
+ break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ insert_dup_update= FALSE;
+ ignore_duplicates= FALSE;
+ break;
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ replace_duplicates= TRUE;
+ break;
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ /*
+ We use this flag to ensure that we do not create an "INSERT IGNORE"
+ statement when inserting new rows into the remote table.
+ */
+ replace_duplicates= FALSE;
+ break;
+ case HA_EXTRA_INSERT_WITH_UPDATE:
+ insert_dup_update= TRUE;
+ break;
+ default:
+ /* do nothing */
+ DBUG_PRINT("info",("unhandled operation: %d", (uint) operation));
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**
+ @brief Reset state of file to after 'open'.
+
+ @detail This function is called after every statement for all tables
+ used by that statement.
+
+ @return Operation status
+ @retval 0 OK
+*/
+
+int ha_federatedx::reset(void)
+{
+ insert_dup_update= FALSE;
+ ignore_duplicates= FALSE;
+ replace_duplicates= FALSE;
+ return 0;
+}
+
+
+/*
+ Used to delete all rows in a table. Both for cases of truncate and
+ for cases where the optimizer realizes that all rows will be
+ removed as a result of a SQL statement.
+
+ Called from item_sum.cc by Item_func_group_concat::clear(),
+ Item_sum_count_distinct::clear(), and Item_func_group_concat::clear().
+ Called from sql_delete.cc by mysql_delete().
+ Called from sql_select.cc by JOIN::reinit().
+ Called from sql_union.cc by st_select_lex_unit::exec().
+*/
+
+int ha_federatedx::delete_all_rows()
+{
+ char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ int error;
+ DBUG_ENTER("ha_federatedx::delete_all_rows");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(STRING_WITH_LEN("TRUNCATE "));
+ append_ident(&query, share->table_name, share->table_name_length,
+ ident_quote_char);
+
+ /* no need for savepoint in autocommit mode */
+ if (!(ha_thd()->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ txn->stmt_autocommit();
+
+ /*
+ TRUNCATE won't return anything in mysql_affected_rows
+ */
+
+ if ((error= txn->acquire(share, FALSE, &io)))
+ DBUG_RETURN(error);
+
+ if (io->query(query.ptr(), query.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ stats.deleted+= stats.records;
+ stats.records= 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ The idea with handler::store_lock() is the following:
+
+ The statement decided which locks we should need for the table
+ for updates/deletes/inserts we get WRITE locks, for SELECT... we get
+ read locks.
+
+ Before adding the lock into the table lock handler (see thr_lock.c)
+ mysqld calls store lock with the requested locks. Store lock can now
+ modify a write lock to a read lock (or some other lock), ignore the
+ lock (if we don't want to use MySQL table locks at all) or add locks
+ for many tables (like we do when we are using a MERGE handler).
+
+ Berkeley DB for federatedx changes all WRITE locks to TL_WRITE_ALLOW_WRITE
+ (which signals that we are doing WRITES, but we are still allowing other
+ reader's and writer's.
+
+ When releasing locks, store_lock() are also called. In this case one
+ usually doesn't have to do anything.
+
+ In some exceptional cases MySQL may send a request for a TL_IGNORE;
+ This means that we are requesting the same lock as last time and this
+ should also be ignored. (This may happen when someone does a flush
+ table when we have opened a part of the tables, in which case mysqld
+ closes and reopens the tables and tries to get the same locks at last
+ time). In the future we will probably try to remove this.
+
+ Called from lock.cc by get_lock_data().
+*/
+
+THR_LOCK_DATA **ha_federatedx::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ DBUG_ENTER("ha_federatedx::store_lock");
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ {
+ /*
+ Here is where we get into the guts of a row level lock.
+ If TL_UNLOCK is set
+ If we are not doing a LOCK TABLE or DISCARD/IMPORT
+ TABLESPACE, then allow multiple writers
+ */
+
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
+ lock_type <= TL_WRITE) && !thd->in_lock_tables)
+ lock_type= TL_WRITE_ALLOW_WRITE;
+
+ /*
+ In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+ MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+ would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+ to t2. Convert the lock to a normal read lock to allow
+ concurrent inserts to t2.
+ */
+
+ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
+ lock_type= TL_READ;
+
+ lock.type= lock_type;
+ }
+
+ *to++= &lock;
+
+ DBUG_RETURN(to);
+}
+
+
+static int test_connection(MYSQL_THD thd, federatedx_io *io,
+ FEDERATEDX_SHARE *share)
+{
+ char buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
+ String str(buffer, sizeof(buffer), &my_charset_bin);
+ FEDERATEDX_IO_RESULT *resultset= NULL;
+ int retval;
+
+ str.length(0);
+ str.append(STRING_WITH_LEN("SELECT * FROM "));
+ append_identifier(thd, &str, share->table_name,
+ share->table_name_length);
+ str.append(STRING_WITH_LEN(" WHERE 1=0"));
+
+ if ((retval= io->query(str.ptr(), str.length())))
+ {
+ my_sprintf(buffer, (buffer,
+ "database: '%s' username: '%s' hostname: '%s'",
+ share->database, share->username, share->hostname));
+ DBUG_PRINT("info", ("error-code: %d", io->error_code()));
+ my_error(ER_CANT_CREATE_FEDERATED_TABLE, MYF(0), buffer);
+ }
+ else
+ resultset= io->store_result();
+
+ io->free_result(resultset);
+
+ return retval;
+}
+
+/*
+ create() does nothing, since we have no local setup of our own.
+ FUTURE: We should potentially connect to the foreign database and
+*/
+
+int ha_federatedx::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int retval;
+ THD *thd= current_thd;
+ FEDERATEDX_SHARE tmp_share; // Only a temporary share, to test the url
+ federatedx_txn *tmp_txn;
+ federatedx_io *tmp_io= NULL;
+ DBUG_ENTER("ha_federatedx::create");
+
+ if ((retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1)))
+ goto error;
+
+ /* loopback socket connections hang due to LOCK_open mutex */
+ if ((!tmp_share.hostname || !strcmp(tmp_share.hostname,my_localhost)) &&
+ !tmp_share.port)
+ goto error;
+
+ /*
+ If possible, we try to use an existing network connection to
+ the remote server. To ensure that no new FEDERATEDX_SERVER
+ instance is created, we pass NULL in get_server() TABLE arg.
+ */
+ pthread_mutex_lock(&federatedx_mutex);
+ tmp_share.s= get_server(&tmp_share, NULL);
+ pthread_mutex_unlock(&federatedx_mutex);
+
+ if (tmp_share.s)
+ {
+ tmp_txn= get_txn(thd);
+ if (!(retval= tmp_txn->acquire(&tmp_share, TRUE, &tmp_io)))
+ {
+ retval= test_connection(thd, tmp_io, &tmp_share);
+ tmp_txn->release(&tmp_io);
+ }
+ free_server(tmp_txn, tmp_share.s);
+ }
+ else
+ {
+ FEDERATEDX_SERVER server;
+
+#ifdef NOT_YET
+ /*
+ Bug#25679
+ Ensure that we do not hold the LOCK_open mutex while attempting
+ to establish FederatedX connection to guard against a trivial
+ Denial of Service scenerio.
+ */
+ safe_mutex_assert_not_owner(&LOCK_open);
+#endif
+
+ fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset);
+
+#ifndef DBUG_OFF
+ pthread_mutex_init(&server.mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_lock(&server.mutex);
+#endif
+
+ tmp_io= federatedx_io::construct(thd->mem_root, &server);
+
+ retval= test_connection(thd, tmp_io, &tmp_share);
+
+#ifndef DBUG_OFF
+ pthread_mutex_unlock(&server.mutex);
+ pthread_mutex_destroy(&server.mutex);
+#endif
+
+ delete tmp_io;
+ }
+
+error:
+ DBUG_RETURN(retval);
+
+}
+
+
+int ha_federatedx::stash_remote_error()
+{
+ DBUG_ENTER("ha_federatedx::stash_remote_error()");
+ if (!io)
+ DBUG_RETURN(remote_error_number);
+ remote_error_number= io->error_code();
+ strmake(remote_error_buf, io->error_str(), sizeof(remote_error_buf)-1);
+ if (remote_error_number == ER_DUP_ENTRY ||
+ remote_error_number == ER_DUP_KEY)
+ DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
+ DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM);
+}
+
+
+bool ha_federatedx::get_error_message(int error, String* buf)
+{
+ DBUG_ENTER("ha_federatedx::get_error_message");
+ DBUG_PRINT("enter", ("error: %d", error));
+ if (error == HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM)
+ {
+ buf->append(STRING_WITH_LEN("Error on remote system: "));
+ buf->qs_append(remote_error_number);
+ buf->append(STRING_WITH_LEN(": "));
+ buf->append(remote_error_buf);
+
+ remote_error_number= 0;
+ remote_error_buf[0]= '\0';
+ }
+ DBUG_PRINT("exit", ("message: %s", buf->ptr()));
+ DBUG_RETURN(FALSE);
+}
+
+
+int ha_federatedx::start_stmt(MYSQL_THD thd, thr_lock_type lock_type)
+{
+ DBUG_ENTER("ha_federatedx::start_stmt");
+ DBUG_ASSERT(txn == get_txn(thd));
+
+ if (!txn->in_transaction())
+ {
+ txn->stmt_begin();
+ trans_register_ha(thd, FALSE, ht);
+ }
+ DBUG_RETURN(0);
+}
+
+
+int ha_federatedx::external_lock(MYSQL_THD thd, int lock_type)
+{
+ int error= 0;
+ DBUG_ENTER("ha_federatedx::external_lock");
+
+ if (lock_type == F_UNLCK)
+ txn->release(&io);
+ else
+ {
+ txn= get_txn(thd);
+ if (!(error= txn->acquire(share, lock_type == F_RDLCK, &io)) &&
+ (lock_type == F_WRLCK || !io->is_autocommit()))
+ {
+ if (!thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ {
+ txn->stmt_begin();
+ trans_register_ha(thd, FALSE, ht);
+ }
+ else
+ {
+ txn->txn_begin();
+ trans_register_ha(thd, TRUE, ht);
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv)
+{
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_set");
+
+ if (txn && txn->has_connections())
+ {
+ if (txn->txn_begin())
+ trans_register_ha(thd, TRUE, hton);
+
+ txn->sp_acquire((ulong *) sv);
+
+ DBUG_ASSERT(1 < *(ulong *) sv);
+ }
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv)
+ {
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_rollback");
+
+ if (txn)
+ error= txn->sp_rollback((ulong *) sv);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv)
+{
+ int error= 0;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::savepoint_release");
+
+ if (txn)
+ error= txn->sp_release((ulong *) sv);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_federatedx::commit(handlerton *hton, MYSQL_THD thd, bool all)
+{
+ int return_val;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::commit");
+
+ if (all)
+ return_val= txn->txn_commit();
+ else
+ return_val= txn->stmt_commit();
+
+ DBUG_PRINT("info", ("error val: %d", return_val));
+ DBUG_RETURN(return_val);
+}
+
+
+int ha_federatedx::rollback(handlerton *hton, MYSQL_THD thd, bool all)
+{
+ int return_val;
+ federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
+ DBUG_ENTER("ha_federatedx::rollback");
+
+ if (all)
+ return_val= txn->txn_rollback();
+ else
+ return_val= txn->stmt_rollback();
+
+ DBUG_PRINT("info", ("error val: %d", return_val));
+ DBUG_RETURN(return_val);
+}
+
+struct st_mysql_storage_engine federatedx_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federatedx_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith",
+ "FederatedX pluggable storage engine",
+ PLUGIN_LICENSE_GPL,
+ federatedx_db_init, /* Plugin Init */
+ federatedx_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
=== added file 'storage/federatedx/ha_federatedx.h'
--- a/storage/federatedx/ha_federatedx.h 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/ha_federatedx.h 2009-10-30 18:50:56 +0000
@@ -0,0 +1,446 @@
+/*
+Copyright (c) 2008, Patrick Galbraith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the name of Patrick Galbraith nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+class federatedx_io;
+
+/*
+ FEDERATEDX_SERVER will eventually be a structure that will be shared among
+ all FEDERATEDX_SHARE instances so that the federated server can minimise
+ the number of open connections. This will eventually lead to the support
+ of reliable XA federated tables.
+*/
+typedef struct st_fedrated_server {
+ MEM_ROOT mem_root;
+ uint use_count, io_count;
+
+ uchar *key;
+ uint key_length;
+
+ const char *scheme;
+ const char *hostname;
+ const char *username;
+ const char *password;
+ const char *database;
+ const char *socket;
+ ushort port;
+
+ const char *csname;
+
+ pthread_mutex_t mutex;
+ federatedx_io *idle_list;
+} FEDERATEDX_SERVER;
+
+/*
+ Please read ha_exmple.cc before reading this file.
+ Please keep in mind that the federatedx storage engine implements all methods
+ that are required to be implemented. handler.h has a full list of methods
+ that you can implement.
+*/
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+#include <mysql.h>
+
+/*
+ handler::print_error has a case statement for error numbers.
+ This value is (10000) is far out of range and will envoke the
+ default: case.
+ (Current error range is 120-159 from include/my_base.h)
+*/
+#define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000
+
+#define FEDERATEDX_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5
+#define FEDERATEDX_RECORDS_IN_RANGE 2
+#define FEDERATEDX_MAX_KEY_LENGTH 3500 // Same as innodb
+
+/*
+ FEDERATEDX_SHARE is a structure that will be shared amoung all open handlers
+ The example implements the minimum of what you will probably need.
+*/
+typedef struct st_federatedx_share {
+ MEM_ROOT mem_root;
+
+ bool parsed;
+ /* this key is unique db/tablename */
+ const char *share_key;
+ /*
+ the primary select query to be used in rnd_init
+ */
+ char *select_query;
+ /*
+ remote host info, parse_url supplies
+ */
+ char *server_name;
+ char *connection_string;
+ char *scheme;
+ char *hostname;
+ char *username;
+ char *password;
+ char *database;
+ char *table_name;
+ char *table;
+ char *socket;
+ char *sport;
+ int share_key_length;
+ ushort port;
+
+ uint table_name_length, server_name_length, connect_string_length;
+ uint use_count;
+ THR_LOCK lock;
+ FEDERATEDX_SERVER *s;
+} FEDERATEDX_SHARE;
+
+
+typedef struct st_federatedx_result FEDERATEDX_IO_RESULT;
+typedef struct st_federatedx_row FEDERATEDX_IO_ROW;
+typedef ptrdiff_t FEDERATEDX_IO_OFFSET;
+
+class federatedx_io
+{
+ friend class federatedx_txn;
+ FEDERATEDX_SERVER * const server;
+ federatedx_io **owner_ptr;
+ federatedx_io *txn_next;
+ federatedx_io *idle_next;
+ bool active; /* currently participating in a transaction */
+ bool busy; /* in use by a ha_federated instance */
+ bool readonly;/* indicates that no updates have occurred */
+
+protected:
+ void set_active(bool new_active)
+ { active= new_active; }
+public:
+ federatedx_io(FEDERATEDX_SERVER *);
+ virtual ~federatedx_io();
+
+ bool is_readonly() const { return readonly; }
+ bool is_active() const { return active; }
+
+ const char * get_charsetname() const
+ { return server->csname ? server->csname : "latin1"; }
+
+ const char * get_hostname() const { return server->hostname; }
+ const char * get_username() const { return server->username; }
+ const char * get_password() const { return server->password; }
+ const char * get_database() const { return server->database; }
+ ushort get_port() const { return server->port; }
+ const char * get_socket() const { return server->socket; }
+
+ static bool handles_scheme(const char *scheme);
+ static federatedx_io *construct(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+
+ static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
+ { return alloc_root(mem_root, size); }
+ static void operator delete(void *ptr, size_t size)
+ { TRASH(ptr, size); }
+
+ virtual int query(const char *buffer, uint length)=0;
+ virtual FEDERATEDX_IO_RESULT *store_result()=0;
+
+ virtual size_t max_query_size() const=0;
+
+ virtual my_ulonglong affected_rows() const=0;
+ virtual my_ulonglong last_insert_id() const=0;
+
+ virtual int error_code()=0;
+ virtual const char *error_str()=0;
+
+ virtual void reset()=0;
+ virtual int commit()=0;
+ virtual int rollback()=0;
+
+ virtual int savepoint_set(ulong sp)=0;
+ virtual ulong savepoint_release(ulong sp)=0;
+ virtual ulong savepoint_rollback(ulong sp)=0;
+ virtual void savepoint_restrict(ulong sp)=0;
+
+ virtual ulong last_savepoint() const=0;
+ virtual ulong actual_savepoint() const=0;
+ virtual bool is_autocommit() const=0;
+
+ virtual bool table_metadata(ha_statistics *stats, const char *table_name,
+ uint table_name_length, uint flag) = 0;
+
+ /* resultset operations */
+
+ virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result)=0;
+ virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
+ unsigned int column)=0;
+ virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
+ unsigned int column) const=0;
+};
+
+
+class federatedx_txn
+{
+ federatedx_io *txn_list;
+ ulong savepoint_level;
+ ulong savepoint_stmt;
+ ulong savepoint_next;
+
+ void release_scan();
+public:
+ federatedx_txn();
+ ~federatedx_txn();
+
+ bool has_connections() const { return txn_list != NULL; }
+ bool in_transaction() const { return savepoint_next != 0; }
+ int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io);
+ void release(federatedx_io **io);
+ void close(FEDERATEDX_SERVER *);
+
+ bool txn_begin();
+ int txn_commit();
+ int txn_rollback();
+
+ bool sp_acquire(ulong *save);
+ int sp_rollback(ulong *save);
+ int sp_release(ulong *save);
+
+ bool stmt_begin();
+ int stmt_commit();
+ int stmt_rollback();
+ void stmt_autocommit();
+};
+
+
+/*
+ Class definition for the storage engine
+*/
+class ha_federatedx: public handler
+{
+ friend int federatedx_db_init(void *p);
+
+ THR_LOCK_DATA lock; /* MySQL lock */
+ FEDERATEDX_SHARE *share; /* Shared lock info */
+ federatedx_txn *txn;
+ federatedx_io *io;
+ FEDERATEDX_IO_RESULT *stored_result;
+ uint fetch_num; // stores the fetch num
+ FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position()
+ int remote_error_number;
+ char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
+ bool ignore_duplicates, replace_duplicates;
+ bool insert_dup_update;
+ DYNAMIC_STRING bulk_insert;
+
+private:
+ /*
+ return 0 on success
+ return errorcode otherwise
+ */
+ uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row,
+ FEDERATEDX_IO_RESULT *result);
+ bool create_where_from_key(String *to, KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool records_in_range, bool eq_range);
+ int stash_remote_error();
+
+ federatedx_txn *get_txn(THD *thd, bool no_create= FALSE);
+
+ static int disconnect(handlerton *hton, MYSQL_THD thd);
+ static int savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv);
+ static int commit(handlerton *hton, MYSQL_THD thd, bool all);
+ static int rollback(handlerton *hton, MYSQL_THD thd, bool all);
+
+ bool append_stmt_insert(String *query);
+
+ int read_next(uchar *buf, FEDERATEDX_IO_RESULT *result);
+ int index_read_idx_with_result_set(uchar *buf, uint index,
+ const uchar *key,
+ uint key_len,
+ ha_rkey_function find_flag,
+ FEDERATEDX_IO_RESULT **result);
+ int real_query(const char *query, uint length);
+ int real_connect(FEDERATEDX_SHARE *my_share, uint create_flag);
+public:
+ ha_federatedx(handlerton *hton, TABLE_SHARE *table_arg);
+ ~ha_federatedx() {}
+ /* The name that will be used for display purposes */
+ const char *table_type() const { return "FEDERATED"; }
+ /*
+ The name of the index type that will be used for display
+ don't implement this method unless you really have indexes
+ */
+ // perhaps get index type
+ const char *index_type(uint inx) { return "REMOTE"; }
+ const char **bas_ext() const;
+ /*
+ This is a list of flags that says what the storage engine
+ implements. The current table flags are documented in
+ handler.h
+ */
+ ulonglong table_flags() const
+ {
+ /* fix server to be able to get remote server table flags */
+ return (HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED
+ | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS |
+ HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+ HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
+ HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
+ }
+ /*
+ This is a bitmap of flags that says how the storage engine
+ implements indexes. The current index flags are documented in
+ handler.h. If you do not implement indexes, just return zero
+ here.
+
+ part is the key part to check. First key part is 0
+ If all_parts it's set, MySQL want to know the flags for the combined
+ index up to and including 'part'.
+ */
+ /* fix server to be able to get remote server index flags */
+ ulong index_flags(uint inx, uint part, bool all_parts) const
+ {
+ return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
+ }
+ uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_parts() const { return MAX_REF_PARTS; }
+ uint max_supported_key_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
+ uint max_supported_key_part_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
+ /*
+ Called in test_quick_select to determine if indexes should be used.
+ Normally, we need to know number of blocks . For federatedx we need to
+ know number of blocks on remote side, and number of packets and blocks
+ on the network side (?)
+ Talk to Kostja about this - how to get the
+ number of rows * ...
+ disk scan time on other side (block size, size of the row) + network time ...
+ The reason for "records * 1000" is that such a large number forces
+ this to use indexes "
+ */
+ double scan_time()
+ {
+ DBUG_PRINT("info", ("records %lu", (ulong) stats.records));
+ return (double)(stats.records*1000);
+ }
+ /*
+ The next method will never be called if you do not implement indexes.
+ */
+ double read_time(uint index, uint ranges, ha_rows rows)
+ {
+ /*
+ Per Brian, this number is bugus, but this method must be implemented,
+ and at a later date, he intends to document this issue for handler code
+ */
+ return (double) rows / 20.0+1;
+ }
+
+ const key_map *keys_to_use_for_scanning() { return &key_map_full; }
+ /*
+ Everything below are methods that we implment in ha_federatedx.cc.
+
+ Most of these methods are not obligatory, skip them and
+ MySQL will treat them as not implemented
+ */
+ int open(const char *name, int mode, uint test_if_locked); // required
+ int close(void); // required
+
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert(bool abort);
+ int write_row(uchar *buf);
+ int update_row(const uchar *old_data, uchar *new_data);
+ int delete_row(const uchar *buf);
+ int index_init(uint keynr, bool sorted);
+ ha_rows estimate_rows_upper_bound();
+ int index_read(uchar *buf, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_idx(uchar *buf, uint idx, const uchar *key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_next(uchar *buf);
+ int index_end();
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
+ /*
+ unlike index_init(), rnd_init() can be called two times
+ without rnd_end() in between (it only makes sense if scan=1).
+ then the second call should prepare for the new table scan
+ (e.g if rnd_init allocates the cursor, second call should
+ position it to the start of the table, no need to deallocate
+ and allocate it again
+ */
+ int rnd_init(bool scan); //required
+ int rnd_end();
+ int rnd_next(uchar *buf); //required
+ int rnd_pos(uchar *buf, uchar *pos); //required
+ void position(const uchar *record); //required
+ int info(uint); //required
+ int extra(ha_extra_function operation);
+
+ void update_auto_increment(void);
+ int repair(THD* thd, HA_CHECK_OPT* check_opt);
+ int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+
+ int delete_all_rows(void);
+ int create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info); //required
+ ha_rows records_in_range(uint inx, key_range *start_key,
+ key_range *end_key);
+ uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type); //required
+ bool get_error_message(int error, String *buf);
+ int start_stmt(THD *thd, thr_lock_type lock_type);
+ int external_lock(THD *thd, int lock_type);
+ int reset(void);
+ int free_result(void);
+};
+
+extern const char ident_quote_char; // Character for quoting
+ // identifiers
+extern const char value_quote_char; // Character for quoting
+ // literals
+
+extern bool append_ident(String *string, const char *name, uint length,
+ const char quote_char);
+
+
+extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
+extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
+ FEDERATEDX_SERVER *server);
=== added file 'storage/federatedx/plug.in'
--- a/storage/federatedx/plug.in 1970-01-01 00:00:00 +0000
+++ b/storage/federatedx/plug.in 2009-10-30 18:50:56 +0000
@@ -0,0 +1,5 @@
+MYSQL_STORAGE_ENGINE(federated,,[FederatedX Storage Engine],
+ [FederatedX Storage Engine], [max,max-no-ndb])
+MYSQL_PLUGIN_DYNAMIC(federated, [ha_federatedx.la])
+MYSQL_PLUGIN_STATIC(federated, [libfederatedx.a])
+MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federatedx.cc])
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc 2009-10-06 14:53:46 +0000
+++ b/storage/maria/ha_maria.cc 2009-10-26 11:35:42 +0000
@@ -266,7 +266,7 @@ static void _ma_check_print_msg(HA_CHECK
if (!thd->vio_ok())
{
- sql_print_error(msgbuf);
+ sql_print_error(fmt, args);
return;
}
@@ -1619,7 +1619,7 @@ int ha_maria::preload_keys(THD * thd, HA
param.db_name= table->s->db.str;
param.table_name= table->s->table_name.str;
param.testflag= 0;
- _ma_check_print_error(¶m, errmsg);
+ _ma_check_print_error(¶m, "%s", errmsg);
DBUG_RETURN(HA_ADMIN_FAILED);
}
DBUG_RETURN(HA_ADMIN_OK);
=== modified file 'storage/maria/ma_extra.c'
--- a/storage/maria/ma_extra.c 2009-02-19 09:01:25 +0000
+++ b/storage/maria/ma_extra.c 2009-10-06 06:13:56 +0000
@@ -323,9 +323,16 @@ int maria_extra(MARIA_HA *info, enum ha_
error= my_errno;
info->lock_type= F_UNLCK;
}
- if (share->kfile.file >= 0)
- _ma_decrement_open_count(info);
+ /*
+ We don't need to call _mi_decrement_open_count() if we are
+ dropping the table, as the files will be removed anyway. If we
+ are aborted before the files is removed, it's better to not
+ call it as in that case the automatic repair on open will add
+ the missing index entries
+ */
pthread_mutex_lock(&share->intern_lock);
+ if (share->kfile.file >= 0 && function != HA_EXTRA_PREPARE_FOR_DROP)
+ _ma_decrement_open_count(info);
if (info->trn)
{
_ma_remove_table_from_trnman(share, info->trn);
=== modified file 'storage/maria/ma_locking.c'
--- a/storage/maria/ma_locking.c 2009-02-09 21:52:42 +0000
+++ b/storage/maria/ma_locking.c 2009-10-06 06:13:56 +0000
@@ -484,7 +484,7 @@ int _ma_decrement_open_count(MARIA_HA *i
{
uint old_lock=info->lock_type;
share->global_changed=0;
- lock_error=maria_lock_database(info,F_WRLCK);
+ lock_error= my_disable_locking ? 0 : maria_lock_database(info, F_WRLCK);
/* Its not fatal even if we couldn't get the lock ! */
if (share->state.open_count > 0)
{
@@ -499,7 +499,7 @@ int _ma_decrement_open_count(MARIA_HA *i
MYF(MY_NABP));
}
}
- if (!lock_error)
+ if (!lock_error && !my_disable_locking)
lock_error=maria_lock_database(info,old_lock);
}
return test(lock_error || write_error);
=== modified file 'storage/maria/ma_recovery.c'
--- a/storage/maria/ma_recovery.c 2009-03-05 16:47:31 +0000
+++ b/storage/maria/ma_recovery.c 2009-10-26 11:35:42 +0000
@@ -199,13 +199,17 @@ int maria_recovery_from_log(void)
int res= 1;
FILE *trace_file;
uint warnings_count;
+#ifdef EXTRA_DEBUG
+ char name_buff[FN_REFLEN];
+#endif
DBUG_ENTER("maria_recovery_from_log");
DBUG_ASSERT(!maria_in_recovery);
maria_in_recovery= TRUE;
#ifdef EXTRA_DEBUG
- trace_file= fopen("maria_recovery.trace", "a+");
+ fn_format(name_buff, "maria_recovery.trace", maria_data_root, "", MYF(0));
+ trace_file= my_fopen(name_buff, O_WRONLY|O_APPEND|O_CREAT, MYF(MY_WME));
#else
trace_file= NULL; /* no trace file for being fast */
#endif
@@ -222,7 +226,7 @@ int maria_recovery_from_log(void)
warnings_count);
}
if (trace_file)
- fclose(trace_file);
+ my_fclose(trace_file, MYF(0));
maria_in_recovery= FALSE;
DBUG_RETURN(res);
}
=== modified file 'storage/maria/unittest/ma_test_loghandler-t.c'
--- a/storage/maria/unittest/ma_test_loghandler-t.c 2008-08-04 16:57:41 +0000
+++ b/storage/maria/unittest/ma_test_loghandler-t.c 2009-10-26 11:35:42 +0000
@@ -113,10 +113,8 @@ static my_bool check_content(uchar *ptr,
void read_ok(TRANSLOG_HEADER_BUFFER *rec)
{
- char buff[80];
- my_snprintf(buff, sizeof(buff), "read record type: %u LSN: (%lu,0x%lx)",
- rec->type, LSN_IN_PARTS(rec->lsn));
- ok(1, buff);
+ ok(1, "read record type: %u LSN: (%lu,0x%lx)",
+ rec->type, LSN_IN_PARTS(rec->lsn));
}
/*
=== modified file 'storage/myisam/mi_extra.c'
--- a/storage/myisam/mi_extra.c 2009-09-03 14:05:38 +0000
+++ b/storage/myisam/mi_extra.c 2009-10-06 06:13:56 +0000
@@ -286,9 +286,19 @@ int mi_extra(MI_INFO *info, enum ha_extr
info->lock_type = F_UNLCK;
}
if (share->kfile >= 0)
+ {
+ /*
+ We don't need to call _mi_decrement_open_count() if we are
+ dropping the table, as the files will be removed anyway. If we
+ are aborted before the files is removed, it's better to not
+ call it as in that case the automatic repair on open will add
+ the missing index entries
+ */
+ if (function != HA_EXTRA_PREPARE_FOR_DROP)
_mi_decrement_open_count(info);
- if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
- error=my_errno;
+ if (my_close(share->kfile,MYF(0)))
+ error=my_errno;
+ }
{
LIST *list_element ;
for (list_element=myisam_open_list ;
=== modified file 'storage/pbxt/src/cache_xt.cc'
--- a/storage/pbxt/src/cache_xt.cc 2009-08-17 11:12:36 +0000
+++ b/storage/pbxt/src/cache_xt.cc 2009-10-30 18:50:56 +0000
@@ -374,7 +374,7 @@ xtPublic void xt_ind_release_handle(XTIn
{
DcHandleSlotPtr hs;
XTIndBlockPtr block = NULL;
- u_int hash_idx = NULL;
+ u_int hash_idx = 0;
DcSegmentPtr seg = NULL;
XTIndBlockPtr xblock;
@@ -1379,7 +1379,7 @@ xtPublic xtBool xt_ind_fetch(XTOpenTable
ASSERT_NS(iref->ir_xlock == 2);
#endif
if (!(block = ind_cac_fetch(ot, ind, address, &seg, TRUE)))
- return NULL;
+ return 0;
branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);
if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) {
=== modified file 'storage/pbxt/src/strutil_xt.cc'
--- a/storage/pbxt/src/strutil_xt.cc 2009-09-03 06:15:03 +0000
+++ b/storage/pbxt/src/strutil_xt.cc 2009-10-26 11:35:42 +0000
@@ -21,10 +21,8 @@
* H&G2JCtL
*/
+#include "mysql_priv.h"
#include "xt_config.h"
-
-#include <stdio.h>
-#include <string.h>
#include <ctype.h>
#include "strutil_xt.h"
@@ -109,6 +107,14 @@ xtPublic void xt_2nd_last_name_of_path(s
*dest = 0;
return;
}
+ /* If temporary file */
+ if (!is_prefix(path, mysql_data_home) &&
+ !is_prefix(path, mysql_real_data_home))
+ {
+ *dest= 0;
+ return;
+ }
+
ptr = path + len - 1;
while (ptr != path && !XT_IS_DIR_CHAR(*ptr))
ptr--;
=== modified file 'storage/xtradb/include/buf0buf.ic'
--- a/storage/xtradb/include/buf0buf.ic 2009-06-25 01:43:25 +0000
+++ b/storage/xtradb/include/buf0buf.ic 2009-10-30 18:50:56 +0000
@@ -1056,7 +1056,7 @@ buf_page_release(
buf_block_t* block, /* in: buffer block */
ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
- mtr_t* mtr) /* in: mtr */
+ mtr_t* mtr __attribute__((unused))) /* in: mtr */
{
ut_ad(block);
=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c 2009-09-07 20:50:10 +0000
+++ b/tests/mysql_client_test.c 2009-10-26 11:35:42 +0000
@@ -1157,7 +1157,7 @@ my_bool fetch_n(const char **query_list,
/* Separate thread query to test some cases */
-static my_bool thread_query(char *query)
+static my_bool thread_query(const char *query)
{
MYSQL *l_mysql;
my_bool error;
@@ -1179,7 +1179,7 @@ static my_bool thread_query(char *query)
goto end;
}
l_mysql->reconnect= 1;
- if (mysql_query(l_mysql, (char *)query))
+ if (mysql_query(l_mysql, query))
{
fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql));
error= 1;
@@ -5803,7 +5803,7 @@ static void test_prepare_alter()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- if (thread_query((char *)"ALTER TABLE test_prep_alter change id id_new varchar(20)"))
+ if (thread_query("ALTER TABLE test_prep_alter change id id_new varchar(20)"))
exit(1);
is_null= 1;
=== modified file 'unittest/mysys/base64-t.c'
--- a/unittest/mysys/base64-t.c 2007-08-01 19:59:05 +0000
+++ b/unittest/mysys/base64-t.c 2009-10-26 11:35:42 +0000
@@ -66,6 +66,7 @@ main(void)
ok(cmp == 0, "Comparing encode-decode result");
if (cmp != 0)
{
+ /* FIXME: This only prints last value of the compared strings */
char buf[80];
diag(" --------- src --------- --------- dst ---------");
for (k= 0; k<src_len; k+=8)
@@ -84,7 +85,7 @@ main(void)
unsigned char c= dst[k+l];
sprintf(buf, "%.2x ", (unsigned)c);
}
- diag(buf);
+ diag("%s", buf);
}
diag("src length: %.8x, dst length: %.8x\n",
(uint) src_len, (uint) dst_len);
1
0