MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eval.inc
1 # ==== Purpose ====
2 #
3 # Evaluate an expression, possibly containing arbitrary
4 # sub-expressions from different connections.
5 #
6 # The expression is parsed before executed. The following constructs
7 # are supported:
8 #
9 # [SQL_STATEMENT, COLUMN, ROW]
10 # The square bracket is replaced by the result from SQL_STATEMENT,
11 # in the given COLUMN and ROW.
12 #
13 # Optionally, SQL_STATEMENT may have the form:
14 # connection:SQL_STATEMENT
15 # In this case, SQL_STATEMENT is executed on the named connection.
16 # All other queries executed by this script will be executed on
17 # the connection that was in use when this script was started.
18 # The current connection will also be restored at the end of this
19 # script.
20 #
21 # It is also possible to nest sub-statements on this form, like:
22 # [master:SHOW BINLOG EVENTS FROM
23 # [slave:SHOW SLAVE STATUS, Master_Log_Pos, 1],
24 # 1, Position]
25 #
26 # [SQL_STATEMENT]
27 # Shortcut to the above form, usable when the result has only one
28 # row and one column.
29 #
30 # <1>
31 # This is a shorthand for the result of the first executed square
32 # bracket. <2> is a shorthand for the second executed square
33 # bracket, and so on.
34 #
35 # ==== Usage ====
36 #
37 # --let $eval_expr= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] + 47
38 # [--let $eval_no_result= 1]
39 # [--let $eval_quiet= 1]
40 # [--let $rpl_debug= 1]
41 # --source include/eval.inc
42 # --echo Result was '$eval_result'
43 #
44 # Parameters:
45 #
46 # $eval_expr
47 # Expression to evaluate. See above for details about the format. The
48 # expression will be executed as `SELECT $eval_expr`.
49 #
50 # Both $eval_expr and the result from any substatement on the
51 # form [SQL_STATEMENT, COLUMN, ROW] will be used in SQL statements,
52 # inside single quotes (as in '$eval_expr'). So any single quotes
53 # in these texts must be escaped or replaced by double quotes.
54 #
55 # $eval_no_result
56 # By default, the expression is evaluated inside 'SELECT' and the
57 # result is stored in $eval_result. If this variable is set, the
58 # expression is instead evaluated as it is and the result is not
59 # stored anywhere.
60 #
61 # $rpl_debug
62 # Print extra debug info.
63 #
64 # Return value:
65 # The result is stored in $eval_result.
66 
67 --let $include_filename= eval.inc
68 --source include/begin_include_file.inc
69 
70 if ($rpl_debug)
71 {
72  --echo # debug: eval_expr='$eval_expr' eval_no_result='$eval_no_result'
73 }
74 
75 --let $_eval_old_connection= $CURRENT_CONNECTION
76 
77 # Evaluate square brackets in expr.
78 --let $_eval_substmt_number= 1
79 --let $_eval_expr_interp= '$eval_expr'
80 --let $_eval_rbracket= `SELECT LOCATE(']', $_eval_expr_interp)`
81 while ($_eval_rbracket)
82 {
83  # Get position of right bracket
84  --let $_eval_lbracket= `SELECT $_eval_rbracket - LENGTH(SUBSTRING_INDEX(SUBSTR($_eval_expr_interp, 1, $_eval_rbracket), '[', -1))`
85  if ($_eval_lbracket == 0)
86  {
87  --echo BUG IN TEST: Mismatching square brackets in eval_expr.
88  --echo Original eval_expr='$eval_expr'
89  --echo Interpolated eval_expr=$_eval_expr_interp
90  --die BUG IN TEST: Mismatching square brackets in $eval_expr
91  }
92 
93  # Get sub-statement from statement. Preserve escapes for single quotes.
94  --let $_eval_full_substmt= `SELECT QUOTE(SUBSTRING($_eval_expr_interp, $_eval_lbracket + 1, $_eval_rbracket - $_eval_lbracket - 1))`
95 
96  # Get connection from sub-statement
97  --let $_eval_colon= `SELECT IF($_eval_full_substmt REGEXP '^[a-zA-Z_][a-zA-Z_0-9]*:', LOCATE(':', $_eval_full_substmt), 0)`
98  --let $_eval_connection=
99  --let $_eval_substmt= $_eval_full_substmt
100  if ($_eval_colon)
101  {
102  --let $_eval_connection= `SELECT SUBSTRING($_eval_substmt, 1, $_eval_colon - 1)`
103  # Preserve escapes for single quotes.
104  --let $_eval_substmt= `SELECT QUOTE(SUBSTRING($_eval_substmt, $_eval_colon + 1))`
105  }
106 
107  # Interpolate escapes before using expression outside string context.
108  --let $_eval_substmt_interp= `SELECT $_eval_substmt`
109 
110  # Change connection
111  if ($_eval_connection)
112  {
113  if ($rpl_debug)
114  {
115  --echo # debug: connection='$_eval_connection' sub-statement=$_eval_substmt
116  }
117  --let $rpl_connection_name= $_eval_connection
118  --source include/rpl_connection.inc
119  }
120  if (!$_eval_connection)
121  {
122  if ($rpl_debug)
123  {
124  --echo # debug: old connection, sub-statement=$_eval_substmt
125  }
126  }
127 
128  # Execute and get result from sub-statement.
129  # Can't use dollar to denote end of string because mtr will try to
130  # interpolate it.
131  --let $selected_row_col= `SELECT CONCAT($_eval_substmt, 'ZZENDZZ') REGEXP '[a-zA-Z_][a-zA-Z0-9_]* *, *[0-9][0-9]* *ZZENDZZ'`
132 
133  if ($selected_row_col)
134  {
135  --let $_eval_substmt_result= query_get_value($_eval_substmt_interp)
136  }
137  if (!$selected_row_col)
138  {
139  --let $_eval_substmt_result= `$_eval_substmt_interp`
140  }
141 
142  # Change back connection
143  if ($_eval_connection)
144  {
145  --let $rpl_connection_name= $_eval_old_connection
146  --source include/rpl_connection.inc
147  }
148 
149  if ($rpl_debug)
150  {
151  --echo # debug: result of sub-statement='$_eval_substmt_result'
152  }
153 
154  # Replace sub-statement by its result
155  --let $_eval_expr_interp= `SELECT QUOTE(REPLACE($_eval_expr_interp, CONCAT('[', $_eval_full_substmt, ']'), '$_eval_substmt_result'))`
156  # Replace result references by result
157  --let $_eval_expr_interp= `SELECT QUOTE(REPLACE($_eval_expr_interp, '<$_eval_substmt_number>', '$_eval_substmt_result'))`
158 
159  --let $_eval_rbracket= `SELECT LOCATE(']', $_eval_expr_interp)`
160 
161  --inc $_eval_substmt_number
162 }
163 
164 # Interpolate escapes before using expression outside string context.
165 --let $_eval_expr_interp= `SELECT $_eval_expr_interp`
166 
167 if ($rpl_debug)
168 {
169  --echo # debug: interpolated_expr='$_eval_expr_interp'
170 }
171 
172 # Execute.
173 if ($eval_no_result)
174 {
175  --eval $_eval_expr_interp
176 }
177 if (!$eval_no_result)
178 {
179  --let $eval_result= `SELECT $_eval_expr_interp`
180 }
181 
182 if ($rpl_debug)
183 {
184  --echo # debug: result='$eval_result'
185 }
186 
187 --let $include_filename= eval.inc
188 --source include/end_include_file.inc