- Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathmysqlx-protocol-expect.dox
260 lines (187 loc) · 7.68 KB
/
mysqlx-protocol-expect.dox
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.0,
* as published by the Free Software Foundation.
*
* This program is designed to work with certain software (including
* but not limited to OpenSSL) that is licensed under separate terms,
* as designated in a particular file or component or in included license
* documentation. The authors of MySQL hereby grant you an additional
* permission to link the program and your derivative works with the
* separately licensed software that they have either included with
* the program or referenced in the documentation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @page mysqlx_protocol_expectations Expectations
Topics in this section:
- @ref expectations_Setting_Expectations
- @ref expectations_Behavior
- @ref expectations_Conditions
With the use of pipelining in the X %Protocol (sending messages
without waiting for successful response) only so many messages can be
pipelined without causing havoc if one of the pipelined, dependent
messages fails:
@code{unparsed}
Mysqlx.Crud::PrepareFind(stmt_id=1, ...) // may fail
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // would fail implicitly as stmt_id=1 doesn't exist
Mysqlx.PreparedStmt::Close(stmt_id=1) // would fail implicitly as stmt_id=1 doesn't exist
@endcode
While implicitly failing is one thing, there are situations where it
isn't that obvious what will happen:
@code{unparsed}
Mysqlx.Crud::PrepareInsert(stmt_id=1, ...) // ok
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // ok
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // duplicate key error
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // what now? abort the insert? ignore?
Mysqlx.PreparedStmt::Close(stmt_id=1) // close the stmt_id
@endcode
Setting Expectations {#expectations_Setting_Expectations}
====================
Expectations let statements fail reliably until the end of the block.
Assume the ``PrepareFind`` fails:
- don't execute the ``Execute``
- don't try to close the stmt
@code{unparsed}
Mysqlx.Expect::Open([+no_error])
Mysqlx.Crud::PrepareFind(stmt_id=1, ...) // may fail
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // expectation(no_error) failed
Mysqlx.PreparedStmt::Close(stmt_id=1) // expectation(no_error) failed
Mysqlx.Expect::Close()
@endcode
But this would also skip the close if execute fails. Not what we want.
Adding another expect-block handles it:
@code{unparsed}
Mysqlx.Expect::Open([+no_error])
Mysqlx.Crud::PrepareFind(stmt_id=1, ...) // may fail
Mysqlx.Expect::Open([+no_error])
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // expectation(no_error) failed
Mysqlx.Expect::Close()
Mysqlx.PreparedStmt::Close(stmt_id=1) // expectation(no_error) failed
Mysqlx.Expect::Close()
@endcode
With these expectations pipelined, the server will handle errors in a
consistent, reliable way.
It also allows to express how a streaming insert would behave if one of
the inserts fails (for example: duplicate key error, disk full, and so
on):
Either fail at first error:
@code{unparsed}
Mysqlx.Expect::Open([+no_error])
Mysqlx.Crud::PrepareInsert(stmt_id=1, ...) // ok
Mysqlx.Expect::Open([+no_error])
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // ok
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // duplicate_key error
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // expectation(no_error) failed
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // expectation(no_error) failed
Mysqlx.Expect::Close()
Mysqlx.PreparedStmt::Close(stmt_id=1) // ok
Mysqlx.Expect::Close()
@endcode
Or ignore error and continue:
@code{unparsed}
Mysqlx.Expect::Open([+no_error])
Mysqlx.Crud::PrepareInsert(stmt_id=1, ...) // ok
Mysqlx.Expect::Open([-no_error])
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // ok
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // duplicate_key error
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // ok
Mysqlx.PreparedStmt::Execute(stmt_id=1, ...) // ok
Mysqlx.Expect::Close()
Mysqlx.PreparedStmt::Close(stmt_id=1) // expectation(no_error) failed
Mysqlx.Expect::Close()
@endcode
Behavior {#expectations_Behavior}
========
An Expectation Block:
- encloses client messages
- has a Condition Set
- has a parent Expectation Block
- can inherit a Condition Set from the parent Expectation Block or
start with a empty Condition Set
- fails if one of the Conditions fails while the Block is started or
active
- fails if one of the Conditions isn't recognized or not valid
A Condition Set:
- has a set of Conditions
- allows to set/unset Conditions
A Condition:
- has a key and value
- key is integer
- value format depends on the key
If a Expectation Block fails, all following messages of the Expectation
block are failing with:
- error-msg: ``Expectation failed: %%s``
- error-code: ...
Conditions {#expectations_Conditions}
==========
@warning
The layout of conditions are subject to change:
- not all may be implemented yet
- more conditions may be added
| Condition | Key |
|------------------------------------------|-----|
| @ref expectations_no_error | 1 |
| @ref expectations_schema_version | 2 |
| @ref expectations_gtid_executed_contains | 3 |
| @ref expectations_gtid_wait_less_than_ms | 4 |
## no_error {#expectations_no_error}
Fail all messages of the block after the first message returning an
error.
Example:
@code{unparsed}
Mysqlx.Expect::Open([+no_error])
Mysqlx.Expect::Close()
@endcode
## schema_version {#expectations_schema_version}
Fail all messages of the block if the schema version for the collection
doesn't match. (_not implemented_)
@note
This is a used by the JSON schema support of the server to ensure
client and server are in agreement of what schema version is
*current* as it is currently planned to enforce the checks on the
client-side.
Example:
@code{unparsed}
Mysqlx.Expect::Open([+schema_version::`schema`.`collection` = 1])
Mysqlx.Expect::Close()
@endcode
## gtid_executed_contains {#expectations_gtid_executed_contains}
Fail all messages until the end of the block if the ``@@gtid_executed``
doesn't contain the set GTID. (_not implemented_)
@note
Used by the *read-your-writes* to ensure another node is already up
to date.
Example:
@code{unparsed}
Mysqlx.Expect::Open([+gtid_executed_contains = "..."])
Mysqlx.Expect::Close()
@endcode
## gtid_wait_less_than_ms {#expectations_gtid_wait_less_than_ms}
Used in combination with @ref expectations_gtid_executed_contains
to wait that the node caught up. (_not implemented_)
Example:
@code{unparsed}
Mysqlx.Expect::Open([+gtid_wait_less_than_ms = 1000])
Mysqlx.Expect::Close()
@endcode
## sql_stateless {#expectations_sql_stateless}
Fail any message that executes stateful statements like:
- temporary tables
- user variables
- session variables
- stateful functions (``INSERT_ID()``, ``GET_LOCK()``)
- stateful language features (``SQL_CALC_FOUND_ROWS``)
@note
Depending on the implementation stored procedures may be not allowed
as they may through levels of indirection use stateful SQL features.
*/