1
/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
// First include (the generated) my_config.h, to get correct platform defines.
17
#include "my_config.h"
18
#include <gtest/gtest.h>
20
#include "test_utils.h"
23
#include "sql_get_diagnostics.h"
25
namespace get_diagnostics_unittest {
27
using my_testing::Server_initializer;
28
using my_testing::Mock_error_handler;
30
class GetDiagnosticsTest : public ::testing::Test
33
virtual void SetUp() { initializer.SetUp(); }
34
virtual void TearDown() { initializer.TearDown(); }
36
THD *thd() { return initializer.thd(); }
38
Server_initializer initializer;
45
void fail(const char *message)
52
LEX_STRING var_name1= {C_STRING_WITH_LEN("var1")};
53
LEX_STRING var_name2= {C_STRING_WITH_LEN("var2")};
56
class MockDiagInfoItem : public Diagnostics_information_item
59
MockDiagInfoItem(Item *target, int value)
60
: Diagnostics_information_item(target), m_value(value)
63
Item *get_value(THD *thd, const Diagnostics_area *da)
65
return new (thd->mem_root) Item_int(m_value);
73
class MockDiagInfo : public Diagnostics_information,
77
MockDiagInfo(List<MockDiagInfoItem> *items)
82
bool aggregate(THD *thd, const Diagnostics_area *da)
85
MockDiagInfoItem *diag_info_item;
86
List_iterator<MockDiagInfoItem> it(*m_items);
88
while ((diag_info_item= it++))
90
if ((rv= evaluate(thd, diag_info_item, da)))
99
fail("MockDiagInfo destructor invoked.");
103
List<MockDiagInfoItem> *m_items;
107
// GET [CURRENT] DIAGNOSTICS @var1 = 1, @var2 = 2;
108
TEST_F(GetDiagnosticsTest, Cmd)
113
MockDiagInfoItem *diag_info_item;
114
List<MockDiagInfoItem> items;
115
MEM_ROOT *mem_root= thd()->mem_root;
118
var= new (mem_root) Item_func_get_user_var(var_name1);
119
diag_info_item= new (mem_root) MockDiagInfoItem(var, 1);
120
EXPECT_FALSE(items.push_back(diag_info_item));
123
var= new (mem_root) Item_func_get_user_var(var_name2);
124
diag_info_item= new (mem_root) MockDiagInfoItem(var, 2);
125
EXPECT_FALSE(items.push_back(diag_info_item));
127
// Information list and command
128
info= new (mem_root) MockDiagInfo(&items);
129
info->set_which_da(Diagnostics_information::CURRENT_AREA);
130
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
132
EXPECT_FALSE(cmd->execute(thd()));
133
EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
136
var= new (mem_root) Item_func_get_user_var(var_name1);
137
EXPECT_FALSE(var->fix_fields(thd(), &var));
138
EXPECT_EQ(1, var->val_int());
141
var= new (mem_root) Item_func_get_user_var(var_name2);
142
EXPECT_FALSE(var->fix_fields(thd(), &var));
143
EXPECT_EQ(2, var->val_int());
147
// Verifies death with a DBUG_ASSERT if target item is not settable.
148
// Google Test recommends DeathTest suffix for classes used in death tests.
149
typedef GetDiagnosticsTest GetDiagnosticsTestDeathTest;
151
#if GTEST_HAS_DEATH_TEST && !defined(DBUG_OFF)
152
TEST_F(GetDiagnosticsTestDeathTest, DieWhenUnsettableItem)
157
MockDiagInfoItem *diag_info_item;
158
List<MockDiagInfoItem> items;
159
MEM_ROOT *mem_root= thd()->mem_root;
161
::testing::FLAGS_gtest_death_test_style= "threadsafe";
164
var= new (mem_root) Item_int(1);
165
diag_info_item= new (mem_root) MockDiagInfoItem(var, 1);
166
EXPECT_FALSE(items.push_back(diag_info_item));
168
// Information list and command
169
info= new (mem_root) MockDiagInfo(&items);
170
info->set_which_da(Diagnostics_information::CURRENT_AREA);
171
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
173
EXPECT_DEATH(cmd->execute(thd()), ".*Assertion.*srp.*");
175
#endif // GTEST_HAS_DEATH_TEST && !defined(DBUG_OFF)
178
class MockDiagInfoError : public Diagnostics_information
181
MockDiagInfoError(bool fatal_error)
182
: m_fatal_error(fatal_error)
186
bool aggregate(THD *thd, const Diagnostics_area *)
188
myf flag= m_fatal_error ? MYF(ME_FATALERROR) : MYF(0);
189
my_message_sql(ER_UNKNOWN_ERROR, "Unknown error", flag);
190
return thd->is_error();
198
// GET DIAGNOSTICS itself causes an error.
199
TEST_F(GetDiagnosticsTest, Error)
202
MockDiagInfoError *info;
203
MEM_ROOT *mem_root= thd()->mem_root;
205
// Pre-existing warning
206
push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
207
WARN_DATA_TRUNCATED, "Data truncated");
209
// Simulate GET DIAGNOSTICS as a new command separated
210
// from the one that generated the warning
211
thd()->reset_for_next_command();
213
// Error bound "information" and command
214
info= new (mem_root) MockDiagInfoError(false);
215
info->set_which_da(Diagnostics_information::CURRENT_AREA);
216
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
218
initializer.set_expected_error(ER_UNKNOWN_ERROR);
220
// Should succeed, not a fatal error
221
EXPECT_FALSE(cmd->execute(thd()));
222
EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
224
// New condition for the error
225
EXPECT_EQ(1U, thd()->get_stmt_da()->statement_warn_count());
227
// Counted as a error
228
EXPECT_EQ(1U, thd()->get_stmt_da()->error_count());
231
EXPECT_EQ(2U, thd()->get_stmt_da()->warn_count());
235
// GET DIAGNOSTICS itself causes a fatal error.
236
TEST_F(GetDiagnosticsTest, FatalError)
239
MockDiagInfoError *info;
240
MEM_ROOT *mem_root= thd()->mem_root;
242
// Pre-existing warning
243
push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
244
WARN_DATA_TRUNCATED, "Data truncated");
246
// Simulate GET DIAGNOSTICS as a new command separated
247
// from the one that generated the warning
248
thd()->reset_for_next_command();
250
// Error bound "information" and command
251
info= new (mem_root) MockDiagInfoError(true);
252
info->set_which_da(Diagnostics_information::CURRENT_AREA);
253
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
255
initializer.set_expected_error(ER_UNKNOWN_ERROR);
257
// Should not succeed due to a fatal error
258
EXPECT_TRUE(cmd->execute(thd()));
259
EXPECT_TRUE(thd()->get_stmt_da()->is_error());
261
// No new condition for the error
262
EXPECT_EQ(0U, thd()->get_stmt_da()->error_count());
264
// Fatal error is set, not appended
265
EXPECT_EQ(1U, thd()->get_stmt_da()->warn_count());
269
// GET [CURRENT] DIAGNOSTICS @var1 = NUMBER, @var2 = ROW_COUNT;
270
TEST_F(GetDiagnosticsTest, StatementInformation)
274
Statement_information *info;
275
Statement_information_item *diag_info_item;
276
List<Statement_information_item> items;
277
MEM_ROOT *mem_root= thd()->mem_root;
279
// NUMBER = 1 warning
280
thd()->raise_warning(ER_UNKNOWN_ERROR);
282
thd()->set_row_count_func(5U);
284
// var1 will receive the value of NUMBER
285
var= new (mem_root) Item_func_get_user_var(var_name1);
286
diag_info_item= new (mem_root)
287
Statement_information_item(Statement_information_item::NUMBER, var);
288
EXPECT_FALSE(items.push_back(diag_info_item));
290
// var2 will receive the value of ROW_COUNT
291
var= new (mem_root) Item_func_get_user_var(var_name2);
292
diag_info_item= new (mem_root)
293
Statement_information_item(Statement_information_item::ROW_COUNT, var);
294
EXPECT_FALSE(items.push_back(diag_info_item));
296
// Information list and command
297
info= new (mem_root) Statement_information(&items);
298
info->set_which_da(Diagnostics_information::CURRENT_AREA);
299
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
301
EXPECT_FALSE(cmd->execute(thd()));
302
EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
305
var= new (mem_root) Item_func_get_user_var(var_name1);
306
EXPECT_FALSE(var->fix_fields(thd(), &var));
307
EXPECT_EQ(1U, var->val_uint());
310
var= new (mem_root) Item_func_get_user_var(var_name2);
311
EXPECT_FALSE(var->fix_fields(thd(), &var));
312
EXPECT_EQ(5U, var->val_int());
316
// GET DIAGNOSTICS CONDITION 1 @var1 = MYSQL_ERRNO, @var2 = MESSAGE_TEXT;
317
TEST_F(GetDiagnosticsTest, ConditionInformation)
322
Condition_information *info;
323
Condition_information_item *diag_info_item;
324
List<Condition_information_item> items;
325
MEM_ROOT *mem_root= thd()->mem_root;
327
// Pre-existing error
328
my_message_sql(ER_UNKNOWN_ERROR, "Unknown error", MYF(0));
330
// Simulate GET DIAGNOSTICS as a new command separated
331
// from the one that generated the error
332
thd()->reset_for_next_command();
334
// var1 will receive the value of MYSQL_ERRNO
335
var= new (mem_root) Item_func_get_user_var(var_name1);
336
diag_info_item= new (mem_root)
337
Condition_information_item(Condition_information_item::MYSQL_ERRNO, var);
338
EXPECT_FALSE(items.push_back(diag_info_item));
340
// var2 will receive the value of MESSAGE_TEXT
341
var= new (mem_root) Item_func_get_user_var(var_name2);
342
diag_info_item= new (mem_root)
343
Condition_information_item(Condition_information_item::MESSAGE_TEXT, var);
344
EXPECT_FALSE(items.push_back(diag_info_item));
346
// condition number (1)
347
var= new (mem_root) Item_uint(1);
349
// Information list and command
350
info= new (mem_root) Condition_information(var, &items);
351
info->set_which_da(Diagnostics_information::CURRENT_AREA);
352
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
354
EXPECT_FALSE(cmd->execute(thd()));
355
EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
358
var= new (mem_root) Item_func_get_user_var(var_name1);
359
EXPECT_FALSE(var->fix_fields(thd(), &var));
360
EXPECT_EQ(ulonglong (ER_UNKNOWN_ERROR), var->val_uint());
363
var= new (mem_root) Item_func_get_user_var(var_name2);
364
EXPECT_FALSE(var->fix_fields(thd(), &var));
365
EXPECT_EQ(&str, var->val_str(&str));
366
EXPECT_STREQ("Unknown error", str.c_ptr_safe());
370
Item *get_cond_info_item(THD *thd,
372
Condition_information_item::Name name)
376
Condition_information *info;
377
Condition_information_item *diag_info_item;
378
List<Condition_information_item> items;
379
MEM_ROOT *mem_root= thd->mem_root;
380
LEX_STRING var_name= {C_STRING_WITH_LEN("get_cond_info_item")};
382
// Simulate GET DIAGNOSTICS as a new command
383
thd->reset_for_next_command();
385
// var1 will receive the value of MYSQL_ERRNO
386
var= new (mem_root) Item_func_get_user_var(var_name);
387
diag_info_item= new (mem_root) Condition_information_item(name, var);
388
EXPECT_FALSE(items.push_back(diag_info_item));
391
var= new (mem_root) Item_uint(number);
393
// Information list and command
394
info= new (mem_root) Condition_information(var, &items);
395
info->set_which_da(Diagnostics_information::CURRENT_AREA);
396
cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
398
EXPECT_FALSE(cmd->execute(thd));
399
EXPECT_TRUE(thd->get_stmt_da()->is_ok());
401
// make a user var item
402
var= new (mem_root) Item_func_get_user_var(var_name);
403
EXPECT_FALSE(var->fix_fields(thd, &var));
409
// GET DIAGNOSTICS CONDITION 1 @var = CLASS_ORIGIN;
410
// GET DIAGNOSTICS CONDITION 1 @var = SUBCLASS_ORIGIN;
411
TEST_F(GetDiagnosticsTest, ConditionInformationClassOrigin)
417
push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
418
ER_XAER_NOTA, "Unknown XID");
421
push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
422
ER_UNKNOWN_ERROR, "Unknown error");
424
// Condition 1 CLASS_ORIGIN
425
var= get_cond_info_item(thd(), 1, Condition_information_item::CLASS_ORIGIN);
426
EXPECT_EQ(&str, var->val_str(&str));
427
EXPECT_STREQ("MySQL", str.c_ptr_safe());
429
// Condition 1 SUBCLASS_ORIGIN
430
var= get_cond_info_item(thd(), 1, Condition_information_item::SUBCLASS_ORIGIN);
431
EXPECT_EQ(&str, var->val_str(&str));
432
EXPECT_STREQ("MySQL", str.c_ptr_safe());
434
// Condition 2 CLASS_ORIGIN
435
var= get_cond_info_item(thd(), 2, Condition_information_item::CLASS_ORIGIN);
436
EXPECT_EQ(&str, var->val_str(&str));
437
EXPECT_STREQ("ISO 9075", str.c_ptr_safe());
439
// Condition 2 CLASS_ORIGIN
440
var= get_cond_info_item(thd(), 2, Condition_information_item::SUBCLASS_ORIGIN);
441
EXPECT_EQ(&str, var->val_str(&str));
442
EXPECT_STREQ("ISO 9075", str.c_ptr_safe());