3 # Check if all tables in the given list are equal. The tables may have
4 # different names, exist in different connections, and/or reside in
10 # --let $diff_tables= [con1:][db1.]t1, [con2:][db2.]t2, ... , [conN:][dbN.]tN
11 # [--let $rpl_debug= 1]
12 # [--let $diff_tables_silent= 1]
13 # --source include/diff_tables.inc
17 # Comma-separated list of tables to compare. Each table has the form
19 # [CONNECTION:][DATABASE.]table
21 # If CONNECTION is given, then that connection is used. If
22 # CONNECTION is not given, then the connection of the previous
23 # table is used (or the current connection, if this is the first
24 # table). If DATABASE is given, the table is read in that
25 # database. If DATABASE is not given, the table is read in the
26 # connection's current database.
29 # Do not print table names to result log.
32 # See include/rpl_init.inc
35 # ==== Side effects ====
37 # - Prints "include/diff_tables.inc [$diff_tables]".
39 # - If the tables are different, prints the difference in a
40 # system-specific format (unified diff if supported) and generates
46 # - It is currently not possible to use this for tables that are
47 # supposed to be different, because if the files are different:
48 # - 'diff' produces system-dependent output,
49 # - the output includes the absolute path of the compared files,
50 # - the output includes a timestamp.
51 # To fix that, we'd probably have to use SQL to compute the
52 # symmetric difference between the tables. I'm not sure how to do
53 # that efficiently. If we implement this, it would be nice to
54 # compare the table definitions too.
56 # - It actually compares the result of "SELECT * FROM table ORDER BY
57 # col1, col2, ..., colN INTO OUTFILE 'file'". Hence, it is assumed
58 # that the comparison orders for both tables are equal and that two
59 # rows that are equal in the comparison order cannot differ, e.g.,
63 --let $include_filename= diff_tables.inc
64 if (!$diff_tables_silent)
66 --let $include_filename= diff_tables.inc [$diff_tables]
68 --source include/begin_include_file.inc
78 if (`SELECT LOCATE(
',',
'$diff_tables') = 0`)
80 --die ERROR IN TEST: $diff_tables must contain at least two tables (separated by comma)
84 # ==== Save both tables to file ====
87 --let $_dt_tables= `SELECT
REPLACE(
'$diff_tables',
' ',
'')`
89 # Iterate over all tables
91 --let $_dt_prev_outfile=
94 --let $_dt_table= `SELECT SUBSTRING_INDEX(
'$_dt_tables',
',', 1)`
95 --let $_dt_tables= `SELECT SUBSTRING(
'$_dt_tables', LENGTH(
'$_dt_table') + 2)`
97 # Parse connection, if any
98 --let $_dt_colon_index= `SELECT LOCATE(
':',
'$_dt_table')`
101 --let $_dt_connection= `SELECT SUBSTRING(
'$_dt_table', 1, $_dt_colon_index - 1)`
102 --let $_dt_table= `SELECT SUBSTRING(
'$_dt_table', $_dt_colon_index + 1)`
103 --let $rpl_connection_name= $_dt_connection
104 --source include/rpl_connection.inc
107 # Parse database name, if any
108 --let $_dt_database_index= `SELECT LOCATE(
'.',
'$_dt_table')`
109 if ($_dt_database_index)
111 --let $_dt_database= `SELECT SUBSTRING(
'$_dt_table', 1, $_dt_database_index - 1)`
112 --let $_dt_table= `SELECT SUBSTRING(
'$_dt_table', $_dt_database_index + 1)`
114 if (!$_dt_database_index)
116 --let $_dt_database= `SELECT DATABASE()`
121 --echo con=
'$_dt_connection' db=
'$_dt_database' table=
'$_dt_table'
122 --echo rest of tables=
'$_dt_tables'
125 # We need to sort the output files so that diff_files does not think
126 # the tables are different just because the rows are differently
127 # ordered. To this end, we first generate a string containing a
128 # comma-separated list of all column names. This is used in the
129 # ORDER BY clause of the following SELECT statement. We get the
130 # column names from INFORMATION_SCHEMA.COLUMNS, and we concatenate
131 # them with GROUP_CONCAT. Since GROUP_CONCAT is limited by the
132 # @@SESSION.group_concat_max_len, which is only 1024 by default, we
133 # first compute the total size of all columns and then increase this
134 # limit if needed. We restore the limit afterwards so as not to
135 # interfere with the test case.
137 # Compute length of ORDER BY clause.
138 let $_dt_order_by_length=
139 `SELECT SUM(LENGTH(column_name) + 3) FROM information_schema.columns
140 WHERE table_schema = '$_dt_database' AND
table_name = '$_dt_table'`;
141 if (!$_dt_order_by_length)
143 --echo ERROR IN TEST:
table $_dt_database.$_dt_table not found in INFORMATION_SCHEMA.COLUMNS. Did you misspell it?
144 --die ERROR IN TEST:
table not found in INFORMATION_SCHEMA. Did you misspell it?
146 --let $_dt_old_group_concat_max_len=
147 # Increase group_concat_max_len if needed.
148 if (`SELECT $_dt_order_by_length > @@SESSION.group_concat_max_len`)
150 --let $_dt_old_group_concat_max_len= `SELECT @@SESSION.group_concat_max_len`
151 --eval SET SESSION group_concat_max_len = $_dt_order_by_length;
154 --echo # increasing group_concat_max_len from $_dt_old_group_concat_max_len
to $_dt_order_by_length
157 # Generate ORDER BY clause.
158 # It would be better to do GROUP_CONCAT(CONCAT('`', column_name, '`')) but
159 # BUG#58087 prevents us from returning strings that begin with backticks.
160 let $_dt_column_list=
161 `SELECT GROUP_CONCAT(column_name
ORDER BY ORDINAL_POSITION SEPARATOR
'`,`')
162 FROM information_schema.columns
163 WHERE table_schema =
'$_dt_database' AND
table_name =
'$_dt_table'`;
164 # Restore group_concat_max_len.
165 if ($_dt_old_group_concat_max_len)
167 --let $_dt_dummy= `SET SESSION group_concat_max_len = $_dt_old_group_concat_max_len
171 --echo
using ORDER BY clause
'`$_dt_column_list`'
174 # Now that we have the comma-separated list of columns, we can write
175 # the table to a file.
176 --let $_dt_outfile= `SELECT @@datadir`
177 --let $_dt_outfile= $_dt_outfile/diff_table-$_dt_connection-$_dt_database-$_dt_table
178 eval SELECT * FROM $_dt_database.$_dt_table
ORDER BY `$_dt_column_list` INTO OUTFILE
'$_dt_outfile';
181 if ($_dt_prev_outfile)
185 --echo # diffing $_dt_prev_outfile vs $_dt_outfile
187 --diff_files $_dt_prev_outfile $_dt_outfile
188 # Remove previous outfile. Keep current file for comparison with next table.
189 --remove_file $_dt_prev_outfile
191 --let $_dt_prev_outfile= $_dt_outfile
194 --remove_file $_dt_prev_outfile
197 --let $include_filename= diff_tables.inc [$diff_tables]
198 --source include/end_include_file.inc