1
by brian
clean slate |
1 |
# ==== Purpose ==== |
2 |
#
|
|
3 |
# Check if the two given tables (possibly residing on different |
|
4 |
# master/slave servers) are equal. |
|
5 |
#
|
|
6 |
# ==== Usage ==== |
|
7 |
#
|
|
8 |
# The tables to check are given by the test language variables |
|
9 |
# $diff_table_1 and $diff_table_2. They must be of the |
|
10 |
# following form: |
|
11 |
#
|
|
12 |
# [master:|slave:]database.table |
|
13 |
#
|
|
14 |
# I.e., both database and table must be speicified. Optionally, you |
|
15 |
# can prefix the name with 'master:' (to read the table on master) or |
|
16 |
# with 'slave:' (to read the table on slave). If no prefix is given, |
|
17 |
# reads the table from the current connection. If one of these |
|
18 |
# variables has a prefix, both should have a prefix. |
|
19 |
#
|
|
20 |
# ==== Side effects ==== |
|
21 |
#
|
|
22 |
# - Prints "Comparing tables $diff_table_1 and $diff_tables_2". |
|
23 |
#
|
|
24 |
# - If the tables are different, prints the difference in a |
|
25 |
# system-specific format (unified diff if supported) and generates |
|
26 |
# an error. |
|
27 |
#
|
|
28 |
# - If $diff_table_1 or $diff_table_2 begins with 'master:' or |
|
29 |
# 'slave:', it will stay connected to one of those hosts after |
|
30 |
# execution. The host is only guaranteed to remain unchanged if |
|
31 |
# none of $diff_table_1 or $diff_table_2 begins with 'master:' or |
|
32 |
# 'slave:'. |
|
33 |
#
|
|
34 |
# ==== Bugs ==== |
|
35 |
#
|
|
36 |
# - It is currently not possible to use this for tables that are |
|
37 |
# supposed to be different, because if the files are different: |
|
38 |
# - 'diff' produces system-dependent output, |
|
39 |
# - the output includes the absolute path of the compared files, |
|
40 |
# - the output includes a timestamp. |
|
41 |
# To fix that, we'd probably have to use SQL to compute the |
|
42 |
# symmetric difference between the tables. I'm not sure how to do |
|
43 |
# that efficiently. If we implement this, it would be nice to |
|
44 |
# compare the table definitions too. |
|
45 |
#
|
|
46 |
# - It actually compares the result of "SELECT * FROM table ORDER BY |
|
47 |
# col1, col2, ..., colN INTO OUTFILE 'file'". Hence, it is assumed |
|
48 |
# that the comparison orders for both tables are equal and that two |
|
49 |
# rows that are equal in the comparison order cannot differ, e.g., |
|
50 |
# by character case. |
|
51 |
||
52 |
||
53 |
# ==== Save both tables to file ==== |
|
54 |
||
55 |
--echo Comparing tables $diff_table_1 and $diff_table_2 |
|
56 |
disable_query_log; |
|
57 |
||
58 |
--error 0,1 |
|
59 |
--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1 |
|
60 |
--error 0,1 |
|
61 |
--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2 |
|
62 |
||
63 |
let $_diff_table=$diff_table_2; |
|
64 |
let $_diff_i=2; |
|
65 |
while ($_diff_i) { |
|
66 |
||
67 |
# Parse out any leading "master:" or "slave:" from the table |
|
68 |
# specification and connect the appropriate server. |
|
69 |
let $_diff_conn_master=`SELECT SUBSTR('$_diff_table', 1, 7) = 'master:'`; |
|
70 |
if ($_diff_conn_master) { |
|
71 |
let $_diff_table=`SELECT SUBSTR('$_diff_table', 8)`; |
|
72 |
connection master; |
|
73 |
}
|
|
74 |
let $_diff_conn_slave=`SELECT SUBSTR('$_diff_table', 1, 6) = 'slave:'`; |
|
75 |
if ($_diff_conn_slave) { |
|
76 |
let $_diff_table=`SELECT SUBSTR('$_diff_table', 7)`; |
|
77 |
connection slave; |
|
78 |
}
|
|
79 |
||
80 |
# Sanity-check the input. |
|
81 |
let $_diff_error= `SELECT '$_diff_table' NOT LIKE '_%._%'`; |
|
82 |
if ($_diff_error) { |
|
83 |
--echo !!!ERROR IN TEST: \$diff_table_$_diff_i='$_diff_table' is not in the form database.table |
|
84 |
exit; |
|
85 |
}
|
|
86 |
||
87 |
# We need the output files to be sorted (so that diff_files does not |
|
88 |
# think the files are different just because they are differently |
|
89 |
# ordered). To this end, we first generate a query that sorts the |
|
90 |
# table by all columns. Since ORDER BY accept column indices, we |
|
91 |
# just generate a comma-separated list of all numbers from 1 to the |
|
92 |
# number of columns in the table. |
|
93 |
let $_diff_column_index=`SELECT MAX(ordinal_position) |
|
94 |
FROM information_schema.columns |
|
95 |
WHERE CONCAT(table_schema, '.', table_name) = |
|
96 |
'$_diff_table'`; |
|
97 |
let $_diff_column_list=$_diff_column_index; |
|
98 |
dec $_diff_column_index; |
|
99 |
while ($_diff_column_index) { |
|
100 |
let $_diff_column_list=$_diff_column_index, $_diff_column_list; |
|
101 |
dec $_diff_column_index; |
|
102 |
}
|
|
103 |
||
104 |
# Now that we have the comma-separated list of columns, we can write |
|
105 |
# the table to a file. |
|
106 |
eval SELECT * FROM $_diff_table ORDER BY $_diff_column_list |
|
107 |
INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/diff_table_$_diff_i'; |
|
108 |
||
109 |
# Do the same for $diff_table_1. |
|
110 |
dec $_diff_i; |
|
111 |
let $_diff_table=$diff_table_1; |
|
112 |
}
|
|
113 |
||
114 |
||
115 |
# ==== Compare the generated files ==== |
|
116 |
||
117 |
diff_files $MYSQLTEST_VARDIR/tmp/diff_table_1 $MYSQLTEST_VARDIR/tmp/diff_table_2; |
|
118 |
||
119 |
--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1 |
|
120 |
--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2 |
|
121 |
||
122 |
enable_query_log; |