1
package GenTest::Executor::MySQL;
5
@ISA = qw(GenTest::Executor);
10
use GenTest::Constants;
12
use GenTest::Executor;
18
"Duplicate entry '.*?' for key '.*?'",
20
"Duplicate key name '.*?'",
21
"Duplicate column name '.*?'",
22
"Record has changed since last read in table '.*?'",
23
"savepoint does not exist",
24
"'.*?' doesn't exist",
25
" .*? does not exist",
26
"'.*?' already exists",
27
"Unknown database '.*?'",
28
"Unknown table '.*?'",
29
"Unknown column '.*?'",
30
"Column '.*?' specified twice",
31
"Column '.*?' cannot be null",
32
"Duplicate partition name .*?",
33
"Tablespace '.*?' not empty",
34
"Tablespace '.*?' already exists",
35
"Tablespace data file '.*?' already exists",
36
"Can't find file: '.*?'",
37
"Table '.*?' already exists",
38
"You can't specify target table '.*?' for update",
39
"Illegal mix of collations .*?, .*?, .*? for operation '.*?'",
40
"Illegal mix of collations .*? and .*? for operation '.*?'",
41
"Invalid .*? character string: '.*?'",
42
"This version of MySQL doesn't yet support '.*?'",
43
"PROCEDURE .*? already exists",
44
"FUNCTION .*? already exists",
45
"'.*?' isn't in GROUP BY",
46
"non-grouping field '.*?' is used in HAVING clause",
47
"Table has no partition for value .*?"
50
my @patterns = map { qr{$_}i } @errors;
52
use constant EXECUTOR_MYSQL_AUTOCOMMIT => 10;
55
# Column positions for SHOW SLAVES
58
use constant SLAVE_INFO_HOST => 1;
59
use constant SLAVE_INFO_PORT => 2;
62
# MySQL status codes taken from errmsg.h
67
use constant ER_CONNECTION_ERROR => 2002;
68
use constant ER_CONN_HOST_ERROR => 2003;
69
use constant ER_SERVER_GONE_ERROR => 2006;
70
use constant ER_SERVER_LOST_EXTENDED => 2055;
71
use constant ER_SERVER_LOST => 2013;
75
use constant ER_PARSE_ERROR => 1064;
76
use constant ER_SYNTAX_ERROR => 1149;
80
use constant ER_UPDATE_TABLE_USED => 1093;
81
use constant ER_BAD_FIELD_ERROR => 1054;
82
use constant ER_NO_SUCH_TABLE => 1146;
83
use constant ER_BAD_TABLE_ERROR => 1051;
84
use constant ER_CANT_DROP_FIELD_OR_KEY => 1091;
85
use constant ER_FIELD_SPECIFIED_TWICE => 1110;
86
use constant ER_MULTIPLE_PRI_KEY => 1068;
87
use constant ER_DUP_FIELDNAME => 1060;
88
use constant ER_DUP_KEYNAME => 1061;
89
use constant ER_SAME_NAME_PARTITION => 1517;
90
use constant ER_PARTITION_WRONG_VALUES_ERROR => 1480;
91
use constant ER_CANT_LOCK => 1015;
92
use constant ER_TABLESPACE_EXIST => 1683;
93
use constant ER_NO_SUCH_TABLESPACE => 1684;
94
use constant ER_SP_DOES_NOT_EXIST => 1305;
95
use constant ER_TABLESPACE_NOT_EMPTY => 1721;
96
use constant ER_TABLESPACE_DATAFILE_EXIST => 1726;
97
use constant ER_BAD_DB_ERROR => 1049;
98
use constant ER_PARTITION_MGMT_ON_NONPARTITIONED => 1505;
99
use constant ER_UNKNOWN_SYSTEM_VARIABLE => 1193;
100
use constant ER_VAR_CANT_BE_READ => 1233;
101
use constant ER_TRG_DOES_NOT_EXIST => 1360;
102
use constant ER_NO_DB_ERROR => 1046;
103
use constant ER_KEY_COLUMN_DOES_NOT_EXIST => 1072;
104
use constant ER_SP_DOES_NOT_EXIST => 1305;
105
use constant ER_BAD_NULL_ERROR => 1048;
106
use constant ER_SAME_NAME_PARTITION => 1517;
107
use constant ER_TABLE_EXISTS_ERROR => 1050;
108
use constant ER_MULTIPLE_PRI_KEY => 1068;
109
use constant ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG => 1336;
110
use constant ER_NOT_SUPPORTED_YET => 1235;
111
use constant ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT => 1560;
112
use constant ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG => 1542;
113
use constant ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG => 1422;
114
use constant ER_CANNOT_USER => 1396;
115
use constant ER_CHECK_NOT_IMPLEMENTED=> 1178;
116
use constant ER_CANT_AGGREGATE_2COLLATIONS => 1267;
117
use constant ER_CANT_AGGREGATE_3COLLATIONS => 1270;
118
use constant ER_CANT_AGGREGATE_NCOLLATIONS => 1271;
119
use constant ER_INVALID_CHARACTER_STRING => 1300;
120
use constant ER_UNKNOWN_SYSTEM_VARIABLE => 1193;
121
use constant ER_SP_ALREADY_EXISTS => 1304;
122
use constant ER_EVENT_ALREADY_EXISTS => 1537;
123
use constant ER_TRG_ALREADY_EXISTS => 1359;
124
use constant ER_WRONG_FIELD_WITH_GROUP => 1055;
125
use constant ER_NON_GROUPING_FIELD_USED => 1463;
127
use constant ER_PARTITION_MGMT_ON_NONPARTITIONED => 1505;
128
use constant ER_DROP_LAST_PARTITION => 1508;
129
use constant ER_COALESCE_ONLY_ON_HASH_PARTITION => 1509;
130
use constant ER_REORG_HASH_ONLY_ON_SAME_NO => 1510;
131
use constant ER_REORG_NO_PARAM_ERROR => 1511;
132
use constant ER_ONLY_ON_RANGE_LIST_PARTITION => 1512;
133
use constant ER_NO_PARTITION_FOR_GIVEN_VALUE => 1526;
135
use constant ER_UNKNOWN_KEY_CACHE => 1284;
140
use constant ER_LOCK_DEADLOCK => 1213;
141
use constant ER_LOCK_WAIT_TIMEOUT => 1205;
142
use constant ER_CHECKREAD => 1020;
143
use constant ER_DUP_KEY => 1022;
144
use constant ER_DUP_ENTRY => 1062;
146
# Storage engine failures
148
use constant ER_GET_ERRNO => 1030;
150
# Database corruption
152
use constant ER_CRASHED1 => 126;
153
use constant ER_CRASHED2 => 145;
154
use constant ER_CRASHED_ON_USAGE => 1194;
155
use constant ER_NOT_KEYFILE => 1034;
156
use constant ER_UNEXPECTED_EOF => 1039;
157
use constant ER_SP_PROC_TABLE_CORRUPT=> 1457;
160
use constant ER_BACKUP_SEND_DATA => 1670;
162
# Out of disk space, quotas, etc.
164
use constant ER_RECORD_FILE_FULL => 1114;
165
use constant ER_DISK_FULL => 1021;
166
use constant ER_OUTOFMEMORY => 1037;
167
use constant ER_CON_COUNT_ERROR => 1040;
168
use constant ER_OUT_OF_RESOURCES => 1041;
169
use constant ER_CANT_CREATE_THREAD => 1135;
170
use constant ER_STACK_OVERRUN => 1119;
172
use constant ER_SERVER_SHUTDOWN => 1053;
175
ER_GET_ERRNO() => STATUS_SEMANTIC_ERROR,
177
ER_CONNECTION_ERROR() => STATUS_SERVER_CRASHED,
178
ER_CONN_HOST_ERROR() => STATUS_SERVER_CRASHED,
179
ER_SERVER_GONE_ERROR() => STATUS_SERVER_CRASHED,
180
ER_SERVER_LOST_EXTENDED() => STATUS_SERVER_CRASHED,
181
ER_SERVER_LOST() => STATUS_SERVER_CRASHED,
183
ER_PARSE_ERROR() => STATUS_SYNTAX_ERROR,
184
ER_SYNTAX_ERROR() => STATUS_SYNTAX_ERROR,
186
ER_UPDATE_TABLE_USED() => STATUS_SEMANTIC_ERROR,
187
ER_NO_SUCH_TABLE() => STATUS_SEMANTIC_ERROR,
188
ER_BAD_TABLE_ERROR() => STATUS_SEMANTIC_ERROR,
189
ER_BAD_FIELD_ERROR() => STATUS_SEMANTIC_ERROR,
190
ER_CANT_DROP_FIELD_OR_KEY() => STATUS_SEMANTIC_ERROR,
191
ER_FIELD_SPECIFIED_TWICE() => STATUS_SEMANTIC_ERROR,
192
ER_MULTIPLE_PRI_KEY() => STATUS_SEMANTIC_ERROR,
193
ER_DUP_FIELDNAME() => STATUS_SEMANTIC_ERROR,
194
ER_DUP_KEYNAME() => STATUS_SEMANTIC_ERROR,
195
ER_SAME_NAME_PARTITION()=> STATUS_SEMANTIC_ERROR,
196
ER_PARTITION_WRONG_VALUES_ERROR() => STATUS_SEMANTIC_ERROR,
197
ER_CANT_LOCK() => STATUS_SEMANTIC_ERROR,
198
ER_TABLESPACE_EXIST() => STATUS_SEMANTIC_ERROR,
199
ER_NO_SUCH_TABLESPACE() => STATUS_SEMANTIC_ERROR,
200
ER_SP_DOES_NOT_EXIST() => STATUS_SEMANTIC_ERROR,
201
ER_TABLESPACE_NOT_EMPTY() => STATUS_SEMANTIC_ERROR,
202
ER_TABLESPACE_DATAFILE_EXIST() => STATUS_SEMANTIC_ERROR,
203
ER_BAD_DB_ERROR() => STATUS_SEMANTIC_ERROR,
204
ER_PARTITION_MGMT_ON_NONPARTITIONED() => STATUS_SEMANTIC_ERROR,
205
ER_UNKNOWN_SYSTEM_VARIABLE() => STATUS_SEMANTIC_ERROR,
206
ER_VAR_CANT_BE_READ() => STATUS_SEMANTIC_ERROR,
207
ER_TRG_DOES_NOT_EXIST() => STATUS_SEMANTIC_ERROR,
208
ER_NO_DB_ERROR() => STATUS_SEMANTIC_ERROR,
209
ER_KEY_COLUMN_DOES_NOT_EXIST() => STATUS_SEMANTIC_ERROR,
210
ER_SP_DOES_NOT_EXIST() => STATUS_SEMANTIC_ERROR,
211
ER_BAD_NULL_ERROR() => STATUS_SEMANTIC_ERROR,
212
ER_SAME_NAME_PARTITION() => STATUS_SEMANTIC_ERROR,
213
ER_TABLE_EXISTS_ERROR() => STATUS_SEMANTIC_ERROR,
214
ER_MULTIPLE_PRI_KEY() => STATUS_SEMANTIC_ERROR,
215
ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG() => STATUS_SEMANTIC_ERROR,
216
ER_NOT_SUPPORTED_YET() => STATUS_SEMANTIC_ERROR,
217
ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT() => STATUS_SEMANTIC_ERROR,
218
ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG() => STATUS_SEMANTIC_ERROR,
219
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG() => STATUS_SEMANTIC_ERROR,
220
ER_CANNOT_USER() => STATUS_SEMANTIC_ERROR,
221
ER_CHECK_NOT_IMPLEMENTED() => STATUS_SEMANTIC_ERROR,
222
ER_CANT_AGGREGATE_2COLLATIONS() => STATUS_SEMANTIC_ERROR,
223
ER_CANT_AGGREGATE_3COLLATIONS() => STATUS_SEMANTIC_ERROR,
224
ER_CANT_AGGREGATE_NCOLLATIONS() => STATUS_SEMANTIC_ERROR,
225
ER_INVALID_CHARACTER_STRING() => STATUS_SEMANTIC_ERROR,
226
ER_UNKNOWN_SYSTEM_VARIABLE() => STATUS_SEMANTIC_ERROR,
227
ER_SP_ALREADY_EXISTS() => STATUS_SEMANTIC_ERROR,
228
ER_EVENT_ALREADY_EXISTS() => STATUS_SEMANTIC_ERROR,
229
ER_TRG_ALREADY_EXISTS() => STATUS_SEMANTIC_ERROR,
230
ER_WRONG_FIELD_WITH_GROUP() => STATUS_SEMANTIC_ERROR,
231
ER_NON_GROUPING_FIELD_USED() => STATUS_SEMANTIC_ERROR,
233
ER_PARTITION_MGMT_ON_NONPARTITIONED() => STATUS_SEMANTIC_ERROR,
234
ER_DROP_LAST_PARTITION() => STATUS_SEMANTIC_ERROR,
235
ER_COALESCE_ONLY_ON_HASH_PARTITION() => STATUS_SEMANTIC_ERROR,
236
ER_REORG_HASH_ONLY_ON_SAME_NO() => STATUS_SEMANTIC_ERROR,
237
ER_REORG_NO_PARAM_ERROR() => STATUS_SEMANTIC_ERROR,
238
ER_ONLY_ON_RANGE_LIST_PARTITION() => STATUS_SEMANTIC_ERROR,
239
ER_NO_PARTITION_FOR_GIVEN_VALUE() => STATUS_SEMANTIC_ERROR,
241
ER_UNKNOWN_KEY_CACHE() => STATUS_SEMANTIC_ERROR,
243
ER_LOCK_DEADLOCK() => STATUS_TRANSACTION_ERROR,
244
ER_LOCK_WAIT_TIMEOUT() => STATUS_TRANSACTION_ERROR,
245
ER_CHECKREAD() => STATUS_TRANSACTION_ERROR,
246
ER_DUP_KEY() => STATUS_TRANSACTION_ERROR,
247
ER_DUP_ENTRY() => STATUS_TRANSACTION_ERROR,
249
ER_NOT_KEYFILE() => STATUS_DATABASE_CORRUPTION,
250
ER_CRASHED_ON_USAGE() => STATUS_DATABASE_CORRUPTION,
251
ER_CRASHED1() => STATUS_DATABASE_CORRUPTION,
252
ER_CRASHED2() => STATUS_DATABASE_CORRUPTION,
253
ER_UNEXPECTED_EOF() => STATUS_DATABASE_CORRUPTION,
254
ER_SP_PROC_TABLE_CORRUPT() => STATUS_DATABASE_CORRUPTION,
256
ER_BACKUP_SEND_DATA() => STATUS_BACKUP_FAILURE,
258
ER_CANT_CREATE_THREAD() => STATUS_ENVIRONMENT_FAILURE,
259
ER_OUT_OF_RESOURCES() => STATUS_ENVIRONMENT_FAILURE,
260
ER_CON_COUNT_ERROR() => STATUS_ENVIRONMENT_FAILURE,
261
ER_RECORD_FILE_FULL() => STATUS_ENVIRONMENT_FAILURE,
262
ER_DISK_FULL() => STATUS_ENVIRONMENT_FAILURE,
263
ER_OUTOFMEMORY() => STATUS_ENVIRONMENT_FAILURE,
264
ER_STACK_OVERRUN() => STATUS_ENVIRONMENT_FAILURE,
266
ER_SERVER_SHUTDOWN() => STATUS_SERVER_KILLED
272
my $executor = shift;
273
my $dbh = DBI->connect($executor->dsn(), undef, undef, {
277
mysql_multi_statements => 1
280
if (not defined $dbh) {
281
say("connect() to dsn ".$executor->dsn()." failed: ".$DBI::errstr);
282
return STATUS_ENVIRONMENT_FAILURE;
285
$executor->setDbh($dbh);
288
# Hack around bug 35676, optiimzer_switch must be set sesson-wide in order to have effect
289
# So we read it from the GLOBAL_VARIABLE table and set it locally to the session
293
SET optimizer_switch = (
294
SELECT variable_value
295
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
296
WHERE VARIABLE_NAME = 'optimizer_switch'
300
# say("Executor initialized, id ".$executor->id());
306
my ($executor, $query, $silent) = @_;
308
my $dbh = $executor->dbh();
310
return GenTest::Result->new( query => $query, status => STATUS_UNKNOWN_ERROR ) if not defined $dbh;
313
(not defined $executor->[EXECUTOR_MYSQL_AUTOCOMMIT]) &&
315
($query =~ m{^\s*start transaction}io) ||
316
($query =~ m{^\s*begin}io)
319
$dbh->do("SET AUTOCOMMIT=OFF");
320
$executor->[EXECUTOR_MYSQL_AUTOCOMMIT] = 0;
323
my $start_time = Time::HiRes::time();
324
my $sth = $dbh->prepare($query);
326
if (not defined $sth) { # Error on PREPARE
327
my $errstr = $executor->normalizeError($sth->errstr());
328
$executor->[EXECUTOR_ERROR_STATS]->{$errstr}++ if $executor->debug();
329
return GenTest::Result->new(
331
status => $executor->getStatusFromErr($dbh->err()) || STATUS_UNKNOWN_ERROR,
333
errstr => $dbh->errstr(),
334
sqlstate => $dbh->state(),
335
start_time => $start_time,
336
end_time => Time::HiRes::time()
340
my $affected_rows = $sth->execute();
341
my $end_time = Time::HiRes::time();
343
my $err = $sth->err();
346
if (defined $err) { # Error on EXECUTE
347
my $err_type = $err2type{$err};
350
($err_type == STATUS_SYNTAX_ERROR) ||
351
($err_type == STATUS_SEMANTIC_ERROR) ||
352
($err_type == STATUS_TRANSACTION_ERROR)
354
my $errstr = $executor->normalizeError($sth->errstr());
355
$executor->[EXECUTOR_ERROR_STATS]->{$errstr}++ if $executor->debug();
356
if (not defined $reported_errors{$errstr}) {
357
say("Query: $query failed: $err $errstr. Further errors of this kind will be suppressed.") if !$silent;
358
$reported_errors{$errstr}++;
361
$executor->[EXECUTOR_ERROR_STATS]->{$sth->errstr()}++ if $executor->debug();
362
say("Query: $query failed: $err ".$sth->errstr()) if !$silent;
365
$result = GenTest::Result->new(
367
status => $err2type{$err} || STATUS_UNKNOWN_ERROR,
369
errstr => $sth->errstr(),
370
sqlstate => $sth->state(),
371
start_time => $start_time,
372
end_time => $end_time
374
} elsif ((not defined $sth->{NUM_OF_FIELDS}) || ($sth->{NUM_OF_FIELDS} == 0)) {
375
$result = GenTest::Result->new(
378
affected_rows => $affected_rows,
379
start_time => $start_time,
380
end_time => $end_time
382
$executor->[EXECUTOR_ERROR_STATS]->{'(no error)'}++ if $executor->debug();
385
# We do not use fetchall_arrayref() due to a memory leak
386
# We also copy the row explicitly into a fresh array
387
# otherwise the entire @data array ends up referencing row #1 only
390
while (my $row = $sth->fetchrow_arrayref()) {
395
$result = GenTest::Result->new(
398
affected_rows => $affected_rows,
400
start_time => $start_time,
401
end_time => $end_time
404
$executor->[EXECUTOR_ERROR_STATS]->{'(no error)'}++ if $executor->debug();
409
if ($sth->{mysql_warning_count} > 0) {
410
my $warnings = $dbh->selectcol_arrayref("SHOW WARNINGS");
411
$result->setWarnings($warnings);
415
($executor->debug()) &&
416
($query =~ m{^\s*select}sio)
418
$executor->explain($query);
419
$executor->[EXECUTOR_ROW_STATS]->{sprintf("%5d",$sth->rows())}++;
426
# Run EXPLAIN on the query in question, recording all notes in the EXPLAIN's Extra field into the statistics
430
my $executor = shift;
432
# if no ID string has been defined yet, define one.
434
if ($executor->SUPER::id() eq '') {
435
my $dbh = $executor->dbh();
436
my $version = $dbh->selectrow_array("SELECT VERSION()");
440
push @capabilities, "master" if $dbh->selectrow_array("SHOW SLAVE HOSTS");
441
push @capabilities, "slave" if $dbh->selectrow_array("SHOW SLAVE STATUS");
442
push @capabilities, "no_semijoin" if $dbh->selectrow_array('SELECT @@optimizer_switch') =~ m{no_semijoin}sio;
443
push @capabilities, "no_materialization" if $dbh->selectrow_array('SELECT @@optimizer_switch') =~ m{no_materialization}sio;
444
push @capabilities, "mo_mrr" if $dbh->selectrow_array('SELECT @@optimizer_use_mrr') eq '0';
445
push @capabilities, "no_condition_pushdown" if $dbh->selectrow_array('SELECT @@engine_condition_pushdown') eq '0';
446
$executor->setId(ref($executor)." ".$version." (".join('; ', @capabilities).")");
449
# Pass the call back to the parent class. It will respond with the id that was (just) defined.
451
return $executor->SUPER::id();
455
my $executor = shift;
456
my $dbh = $executor->dbh();
457
return $dbh->selectrow_array("SELECT VERSION()");
461
my $executor = shift;
462
my $slave_info = $executor->dbh()->selectrow_arrayref("SHOW SLAVE HOSTS");
463
return ($slave_info->[SLAVE_INFO_HOST], $slave_info->[SLAVE_INFO_PORT]);
467
my $executor = shift;
468
return $executor->dbh()->selectrow_array("SHOW MASTER STATUS");
472
my ($executor, $query) = @_;
473
my $explain_output = $executor->dbh()->selectall_arrayref("EXPLAIN $query");
474
foreach my $explain_row (@$explain_output) {
475
my $explain_string = $explain_row->[9];
476
my @explain_items = split('; ', $explain_string);
477
foreach my $explain_item (@explain_items) {
478
$explain_item =~ s{0x.*?\)}{%d\)}sgio;
479
$executor->[EXECUTOR_EXPLAIN_STATS]->{$explain_item}++;
485
my $executor = shift;
486
if ($executor->debug()) {
487
say("Statistics for Executor ".$executor->dsn());
489
$Data::Dumper::Sortkeys = 1;
490
print Dumper $executor->[EXECUTOR_ROW_STATS];
491
print Dumper $executor->[EXECUTOR_EXPLAIN_STATS];
492
print Dumper $executor->[EXECUTOR_ERROR_STATS];
494
$executor->dbh()->disconnect();
498
my $executor = shift;
499
return [] if not defined $executor->dbh();
500
$caches{tables} = $executor->dbh()->selectcol_arrayref("SHOW TABLES") if not exists $caches{tables};
501
return $caches{tables};
505
my $executor = shift;
506
if (defined $executor->dbh()) {
507
$caches{fields} = $executor->dbh()->selectcol_arrayref("
508
SHOW FIELDS FROM ".$executor->tables()->[0]
509
) if not defined $caches{fields};
510
return $caches{fields};
517
my $executor = shift;
518
$caches{fieldsNoPK} = $executor->dbh()->selectcol_arrayref("
520
FROM INFORMATION_SCHEMA.COLUMNS
521
WHERE TABLE_SCHEMA = DATABASE() AND
522
TABLE_NAME = '".$executor->tables()->[0]."'
523
AND COLUMN_KEY != 'PRI'
524
") if not defined $caches{fieldsNoPK};
526
return $caches{fieldsNoPK};
530
my $executor = shift;
531
$caches{fields_indexed} = $executor->dbh()->selectcol_arrayref("
532
SHOW INDEX FROM ".$executor->tables()->[0]
533
, { Columns=>[5] }) if not defined $caches{fields_indexed};
535
return $caches{fields_indexed};
539
my $executor = shift;
540
$caches{fields_indexed} = $executor->dbh()->selectcol_arrayref("
541
SHOW INDEX FROM ".$executor->tables()->[0]
542
, { Columns=>[5] } ) if not defined $caches{fields_indexed};
544
return $caches{fields_indexed};
549
my $executor = shift;
550
return $executor->dbh()->selectcol_arrayref("
551
SELECT COLLATION_NAME
552
FROM INFORMATION_SCHEMA.COLLATIONS
557
my $executor = shift;
558
return $executor->dbh()->selectcol_arrayref("
559
SELECT DISTINCT CHARACTER_SET_NAME
560
FROM INFORMATION_SCHEMA.COLLATIONS
565
my $executor = shift;
566
return $executor->dbh()->selectrow_array("SELECT DATABASE()");
570
return undef if not defined $_[0];
571
return $err2type{$_[0]} || STATUS_UNKNOWN_ERROR ;
575
my ($executor, $errstr) = @_;
577
$errstr =~ s{\d+}{%d}sgio if $errstr !~ m{from storage engine}sio; # Make all errors involving numbers the same, e.g. duplicate key errors
579
foreach my $i (0..$#errors) {
580
last if $errstr =~ s{$patterns[$i]}{$errors[$i]}si;
583
$errstr =~ s{\.\*\?}{%s}sgio;