~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to tests/randgen/lib/GenTest/Executor/MySQL.pm

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2012-06-19 10:46:49 UTC
  • mfrom: (1.2.11) (2.1.16 sid)
  • Revision ID: package-import@ubuntu.com-20120619104649-9ij634mxm4x8pp4l
Tags: 1:7.1.36-stable-1ubuntu1
* Merge from Debian unstable. (LP: #987575)
  Remaining changes:
  - Added upstart script.
* debian/drizzle.upstart: dropped logger since upstart logs job
  output now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008-2009 Sun Microsystems, Inc. All rights reserved.
 
2
# Use is subject to license terms.
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; version 2 of the License.
 
7
#
 
8
# This program is distributed in the hope that it will be useful, but
 
9
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
11
# General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 
16
# USA
 
17
 
 
18
package GenTest::Executor::MySQL;
 
19
 
 
20
require Exporter;
 
21
 
 
22
@ISA = qw(GenTest::Executor);
 
23
 
 
24
use strict;
 
25
use DBI;
 
26
use GenTest;
 
27
use GenTest::Constants;
 
28
use GenTest::Result;
 
29
use GenTest::Executor;
 
30
use Time::HiRes;
 
31
 
 
32
use constant RARE_QUERY_THRESHOLD       => 5;
 
33
 
 
34
my %reported_errors;
 
35
 
 
36
my @errors = (
 
37
        "The target table .*? of the .*? is",
 
38
        "Duplicate entry '.*?' for key '.*?'",
 
39
        "Can't DROP '.*?'",
 
40
        "Duplicate key name '.*?'",
 
41
        "Duplicate column name '.*?'",
 
42
        "Record has changed since last read in table '.*?'",
 
43
        "savepoint does not exist",
 
44
        "'.*?' doesn't exist",
 
45
        " .*? does not exist",
 
46
        "'.*?' already exists",
 
47
        "Unknown database '.*?'",
 
48
        "Unknown table '.*?'",
 
49
        "Unknown column '.*?'",
 
50
        "Unknown event '.*?'",
 
51
        "Column '.*?' specified twice",
 
52
        "Column '.*?' cannot be null",
 
53
        "Column '.*?' in .*? clause is ambiguous",
 
54
        "Duplicate partition name .*?",
 
55
        "Tablespace '.*?' not empty",
 
56
        "Tablespace '.*?' already exists",
 
57
        "Tablespace data file '.*?' already exists",
 
58
        "Can't find file: '.*?'",
 
59
        "Table '.*?' already exists",
 
60
        "You can't specify target table '.*?' for update",
 
61
        "Illegal mix of collations .*?, .*?, .*? for operation '.*?'",
 
62
        "Illegal mix of collations .*? and .*? for operation '.*?'",
 
63
        "Invalid .*? character string: '.*?'",
 
64
        "This version of MySQL doesn't yet support '.*?'",
 
65
        "PROCEDURE .*? already exists",
 
66
        "FUNCTION .*? already exists",
 
67
        "'.*?' isn't in GROUP BY",
 
68
        "non-grouping field '.*?' is used in HAVING clause",
 
69
        "Table has no partition for value .*?",
 
70
        "Unknown prepared statement handler (.*?) given to EXECUTE",
 
71
        "Unknown prepared statement handler (.*?) given to DEALLOCATE PREPARE",
 
72
        "Can't execute the query because you have a conflicting read lock",
 
73
        "Can't execute the given command because you have active locked tables or an active transaction",
 
74
        "Not unique table/alias: '.*?'",
 
75
        "View .* references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them",
 
76
        "Unknown thread id: .*?" ,
 
77
        "Unknown table '.*?' in .*?",
 
78
        "Table '.*?' is read only",
 
79
        "Duplicate condition: .*?",
 
80
        "Duplicate condition information item '.*?'",
 
81
        "Undefined CONDITION: .*?",
 
82
        "Incorrect .*? value '.*?'",
 
83
        "Recursive limit \d+ (as set by the max_sp_recursion_depth variable) was exceeded for routine .*?",
 
84
        "There is no such grant defined for user '.*?' on host '.*?' on table '.*?'",
 
85
        "There is no such grant defined for user '.*?' on host '.*?'",
 
86
        "'.*?' is not a .*?",
 
87
        "Incorrect usage of .*? and .*?",
 
88
        "Can't reopen table: '.*?'",
 
89
        "Trigger's '.*?' is view or temporary table",
 
90
        "Column '.*?' is not updatable"
 
91
);
 
92
 
 
93
my @patterns = map { qr{$_}i } @errors;
 
94
 
 
95
use constant EXECUTOR_MYSQL_AUTOCOMMIT => 20;
 
96
 
 
97
#
 
98
# Column positions for SHOW SLAVES
 
99
 
100
 
 
101
use constant SLAVE_INFO_HOST => 1;
 
102
use constant SLAVE_INFO_PORT => 2;
 
103
 
 
104
#
 
105
# MySQL status codes taken from errmsg.h
 
106
#
 
107
 
 
108
# Server has crashed
 
109
 
 
110
use constant    ER_CONNECTION_ERROR     => 2002;
 
111
use constant    ER_CONN_HOST_ERROR      => 2003;
 
112
use constant    ER_SERVER_GONE_ERROR    => 2006;
 
113
use constant    ER_SERVER_LOST_EXTENDED => 2055;
 
114
use constant    ER_SERVER_LOST          => 2013;
 
115
 
 
116
# Syntax error
 
117
 
 
118
use constant    ER_PARSE_ERROR          => 1064;
 
119
use constant    ER_SYNTAX_ERROR         => 1149;
 
120
 
 
121
# Semantic errors
 
122
 
 
123
use constant    ER_UPDATE_TABLE_USED    => 1093;
 
124
use constant    ER_BAD_FIELD_ERROR      => 1054;
 
125
use constant    ER_NO_SUCH_TABLE        => 1146;
 
126
use constant    ER_BAD_TABLE_ERROR      => 1051;
 
127
use constant    ER_CANT_DROP_FIELD_OR_KEY       => 1091;
 
128
use constant    ER_FIELD_SPECIFIED_TWICE        => 1110;
 
129
use constant    ER_MULTIPLE_PRI_KEY     => 1068;
 
130
use constant    ER_DUP_FIELDNAME        => 1060;
 
131
use constant    ER_DUP_KEYNAME          => 1061;
 
132
use constant    ER_SAME_NAME_PARTITION  => 1517;
 
133
use constant    ER_PARTITION_WRONG_VALUES_ERROR => 1480;
 
134
use constant    ER_CANT_LOCK            => 1015;
 
135
use constant    ER_TABLESPACE_EXIST     => 1683;
 
136
use constant    ER_NO_SUCH_TABLESPACE   => 1684;
 
137
use constant    ER_SP_DOES_NOT_EXIST    => 1305;
 
138
use constant    ER_TABLESPACE_NOT_EMPTY => 1721;
 
139
use constant    ER_TABLESPACE_DATAFILE_EXIST => 1726;
 
140
use constant    ER_BAD_DB_ERROR         => 1049;
 
141
use constant    ER_PARTITION_MGMT_ON_NONPARTITIONED     => 1505;
 
142
use constant    ER_UNKNOWN_SYSTEM_VARIABLE      => 1193;
 
143
use constant    ER_VAR_CANT_BE_READ     => 1233;
 
144
use constant    ER_TRG_DOES_NOT_EXIST   => 1360;
 
145
use constant    ER_NO_DB_ERROR          => 1046;
 
146
use constant    ER_KEY_COLUMN_DOES_NOT_EXIST => 1072;
 
147
use constant    ER_SP_DOES_NOT_EXIST    => 1305;
 
148
use constant    ER_BAD_NULL_ERROR       => 1048;
 
149
use constant    ER_SAME_NAME_PARTITION  => 1517;
 
150
use constant    ER_TABLE_EXISTS_ERROR   => 1050;
 
151
use constant    ER_MULTIPLE_PRI_KEY     => 1068;
 
152
use constant    ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG        => 1336;
 
153
use constant    ER_NOT_SUPPORTED_YET    => 1235;
 
154
use constant    ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT        => 1560;
 
155
use constant    ER_TRANS_CACHE_FULL     => 1197;
 
156
use constant    ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG       => 1542;
 
157
use constant    ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG => 1422;
 
158
use constant    ER_CANNOT_USER          => 1396;
 
159
use constant    ER_CHECK_NOT_IMPLEMENTED=> 1178;
 
160
use constant    ER_CANT_AGGREGATE_2COLLATIONS   => 1267;
 
161
use constant    ER_CANT_AGGREGATE_3COLLATIONS   => 1270;
 
162
use constant    ER_CANT_AGGREGATE_NCOLLATIONS   => 1271;
 
163
use constant    ER_INVALID_CHARACTER_STRING     => 1300;
 
164
use constant    ER_UNKNOWN_SYSTEM_VARIABLE      => 1193;
 
165
use constant    ER_SP_ALREADY_EXISTS            => 1304;
 
166
use constant    ER_EVENT_ALREADY_EXISTS         => 1537;
 
167
use constant    ER_TRG_ALREADY_EXISTS           => 1359;
 
168
use constant    ER_WRONG_FIELD_WITH_GROUP       => 1055;
 
169
use constant    ER_NON_GROUPING_FIELD_USED      => 1463;
 
170
use constant    ER_NON_UNIQ_ERROR               => 1052;
 
171
use constant    ER_EVENT_DOES_NOT_EXIST         => 1539;
 
172
use constant    ER_NONEXISTING_GRANT            => 1141;
 
173
use constant    ER_NONEXISTING_TABLE_GRANT      => 1147;
 
174
use constant    ER_WRONG_AUTO_KEY               => 1075;
 
175
use constant    ER_SP_DUP_PARAM                 => 1330;
 
176
use constant    ER_WRONG_OBJECT                 => 1347;
 
177
use constant    ER_WRONG_USAGE                  => 1221;
 
178
use constant    ER_VIEW_SELECT_DERIVED          => 1349;
 
179
use constant    ER_DB_CREATE_EXISTS             => 1007;
 
180
use constant    ER_CANT_REOPEN_TABLE            => 1137;
 
181
use constant    ER_TRG_ON_VIEW_OR_TEMP_TABLE    => 1361;
 
182
use constant    ER_VIEW_SELECT_TMPTABLE         => 1352;
 
183
use constant    ER_NONUPDATEABLE_COLUMN         => 1348;
 
184
use constant    ER_TOO_BIG_SELECT               => 1104;
 
185
use constant    ER_CANT_USE_OPTION_HERE         => 1234;
 
186
use constant    ER_TOO_LONG_KEY                 => 1071;
 
187
use constant    ER_TABLE_CANT_HANDLE_BLOB       => 1163;
 
188
use constant    ER_TOO_MANY_ROWS                => 1172;
 
189
 
 
190
use constant    ER_PARTITION_MGMT_ON_NONPARTITIONED     => 1505;
 
191
use constant    ER_DROP_PARTITION_NON_EXISTENT          => 1507;
 
192
use constant    ER_DROP_LAST_PARTITION                  => 1508;
 
193
use constant    ER_COALESCE_ONLY_ON_HASH_PARTITION      => 1509;
 
194
use constant    ER_REORG_HASH_ONLY_ON_SAME_NO           => 1510;
 
195
use constant    ER_REORG_NO_PARAM_ERROR                 => 1511;
 
196
use constant    ER_ONLY_ON_RANGE_LIST_PARTITION         => 1512;
 
197
use constant    ER_NO_PARTITION_FOR_GIVEN_VALUE         => 1526;
 
198
use constant    ER_PARTITION_MAXVALUE_ERROR             => 1481;
 
199
use constant    ER_WRONG_PARTITION_NAME                 => 1567;
 
200
use constant    ER_NO_PARTS_ERROR                       => 1504;
 
201
 
 
202
use constant    ER_NON_INSERTABLE_TABLE                 => 1471;
 
203
use constant    ER_NON_UPDATABLE_TABLE                  => 1288;
 
204
 
 
205
use constant    ER_UNKNOWN_KEY_CACHE                    => 1284;
 
206
 
 
207
use constant    ER_CANT_CHANGE_TX_ISOLATION             => 1568;
 
208
use constant    ER_MIX_OF_GROUP_FUNC_AND_FIELDS         => 1140;
 
209
 
 
210
# The PREPARE already failed
 
211
use constant    ER_UNKNOWN_STMT_HANDLER => 1243 ;
 
212
use constant    ER_NEED_REPREPARE       => 1615 ;
 
213
 
 
214
# Table mentioned more than once in statement processing a table list.
 
215
use constant    ER_NONUNIQ_TABLE        => 1066 ;
 
216
# Base table of a view was modified or dropped or ..
 
217
use constant    ER_VIEW_INVALID => 1356 ;
 
218
 
 
219
use constant    ER_NO_SUCH_THREAD                       => 1094;
 
220
use constant    ER_QUERY_INTERRUPTED                    => 1317;
 
221
 
 
222
use constant    ER_UNKNOWN_TABLE                        => 1109;
 
223
use constant    ER_FILE_NOT_FOUND                       => 1017;
 
224
use constant    ER_WRONG_MRG_TABLE                      => 1168;
 
225
 
 
226
use constant    ER_OPEN_AS_READONLY                     => 1036;
 
227
 
 
228
use constant    ER_SP_DUP_COND                          => 1332;
 
229
use constant    ER_SP_DUP_HANDLER                       => 1413;
 
230
use constant    ER_SIGNAL_BAD_CONDITION_TYPE            => 1646;
 
231
use constant    ER_SP_COND_MISMATCH                     => 1319;
 
232
use constant    ER_DUP_SIGNAL_SET                       => 1641;
 
233
use constant    ER_WRONG_VALUE                          => 1525;
 
234
use constant    ER_SP_NO_RECURSION                      => 1424;
 
235
use constant    ER_SIGNAL_EXCEPTION                     => 1644;
 
236
use constant    ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER      => 1645;
 
237
use constant    ER_WRONG_VALUE_FOR_VAR                  => 1231;
 
238
use constant    ER_SP_NO_RETSET                         => 1415;
 
239
use constant    ER_SP_NORETURNEND                       => 1321;
 
240
use constant    ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG  => 1442;
 
241
use constant    ER_SP_RECURSION_LIMIT                   => 1456;
 
242
 
 
243
# Transaction errors
 
244
 
 
245
use constant    ER_LOCK_DEADLOCK        => 1213;
 
246
use constant    ER_LOCK_WAIT_TIMEOUT    => 1205;
 
247
use constant    ER_CHECKREAD            => 1020;
 
248
use constant    ER_DUP_KEY              => 1022;
 
249
use constant    ER_DUP_ENTRY            => 1062;
 
250
use constant    ER_LOCK_OR_ACTIVE_TRANSACTION   => 1192;
 
251
# The table is already read locked by the same seeion.
 
252
use constant    ER_CANT_UPDATE_WITH_READLOCK => 1223 ;
 
253
 
 
254
# Storage engine failures
 
255
 
 
256
use constant    ER_GET_ERRNO                    => 1030;
 
257
use constant    ER_UNKNOWN_STORAGE_ENGINE       => 1286;
 
258
use constant    ER_KEY_NOT_FOUND                => 1032;
 
259
use constant    ER_ILLEGAL_HA                   => 1031;
 
260
 
 
261
# Database corruption
 
262
 
 
263
use constant    ER_CRASHED1             => 126;
 
264
use constant    ER_CRASHED2             => 145;
 
265
use constant    ER_CRASHED_ON_USAGE     => 1194;
 
266
use constant    ER_NOT_KEYFILE          => 1034;
 
267
use constant    ER_UNEXPECTED_EOF       => 1039;
 
268
use constant    ER_SP_PROC_TABLE_CORRUPT=> 1457;
 
269
# Backup
 
270
 
 
271
use constant    ER_BACKUP_NOT_ENABLED   => 1789;
 
272
use constant    ER_BACKUP_SEND_DATA1    => 1670;
 
273
use constant    ER_BACKUP_SEND_DATA2    => 1687;
 
274
use constant    ER_BACKUP_PROGRESS_TABLES => 1691;
 
275
use constant    ER_BACKUP_RUNNING       => 1651;
 
276
 
 
277
# Out of disk space, quotas, etc.
 
278
 
 
279
use constant    ER_RECORD_FILE_FULL     => 1114;
 
280
use constant    ER_DISK_FULL            => 1021;
 
281
use constant    ER_OUTOFMEMORY          => 1037;
 
282
use constant    ER_CON_COUNT_ERROR      => 1040;
 
283
use constant    ER_OUT_OF_RESOURCES     => 1041;
 
284
use constant    ER_CANT_CREATE_THREAD   => 1135;
 
285
use constant    ER_STACK_OVERRUN        => 1119;
 
286
 
 
287
use constant    ER_SERVER_SHUTDOWN      => 1053;
 
288
 
 
289
use constant    ER_FEATURE_DISABLED     => 1289;
 
290
use constant    ER_OPTION_PREVENTS_STATEMENT    => 1290;
 
291
 
 
292
my %err2type = (
 
293
 
 
294
        ER_GET_ERRNO()          => STATUS_DATABASE_CORRUPTION,
 
295
 
 
296
        ER_CONNECTION_ERROR()   => STATUS_SERVER_CRASHED,
 
297
        ER_CONN_HOST_ERROR()    => STATUS_SERVER_CRASHED,
 
298
        ER_SERVER_GONE_ERROR()  => STATUS_SERVER_CRASHED,
 
299
        ER_SERVER_LOST_EXTENDED()       => STATUS_SERVER_CRASHED,
 
300
        ER_SERVER_LOST()        => STATUS_SERVER_CRASHED,
 
301
 
 
302
        ER_PARSE_ERROR()        => STATUS_SYNTAX_ERROR,
 
303
        ER_SYNTAX_ERROR()       => STATUS_SYNTAX_ERROR,
 
304
 
 
305
        ER_UPDATE_TABLE_USED()  => STATUS_SEMANTIC_ERROR,
 
306
        ER_NO_SUCH_TABLE()      => STATUS_SEMANTIC_ERROR,
 
307
        ER_BAD_TABLE_ERROR()    => STATUS_SEMANTIC_ERROR,
 
308
        ER_BAD_FIELD_ERROR()    => STATUS_SEMANTIC_ERROR,
 
309
        ER_CANT_DROP_FIELD_OR_KEY()     => STATUS_SEMANTIC_ERROR,
 
310
        ER_FIELD_SPECIFIED_TWICE()      => STATUS_SEMANTIC_ERROR,
 
311
        ER_MULTIPLE_PRI_KEY()   => STATUS_SEMANTIC_ERROR,
 
312
        ER_DUP_FIELDNAME()      => STATUS_SEMANTIC_ERROR,
 
313
        ER_DUP_KEYNAME()        => STATUS_SEMANTIC_ERROR,
 
314
        ER_SAME_NAME_PARTITION()=> STATUS_SEMANTIC_ERROR,
 
315
        ER_PARTITION_WRONG_VALUES_ERROR() => STATUS_SEMANTIC_ERROR,
 
316
        ER_CANT_LOCK()          => STATUS_SEMANTIC_ERROR,
 
317
        ER_TABLESPACE_EXIST()   => STATUS_SEMANTIC_ERROR,
 
318
        ER_NO_SUCH_TABLESPACE() => STATUS_SEMANTIC_ERROR,
 
319
        ER_SP_DOES_NOT_EXIST()  => STATUS_SEMANTIC_ERROR,
 
320
        ER_TABLESPACE_NOT_EMPTY()       => STATUS_SEMANTIC_ERROR,
 
321
        ER_TABLESPACE_DATAFILE_EXIST()  => STATUS_SEMANTIC_ERROR,
 
322
        ER_BAD_DB_ERROR()       => STATUS_SEMANTIC_ERROR,
 
323
        ER_PARTITION_MGMT_ON_NONPARTITIONED()   => STATUS_SEMANTIC_ERROR,
 
324
        ER_UNKNOWN_SYSTEM_VARIABLE() => STATUS_SEMANTIC_ERROR,
 
325
        ER_VAR_CANT_BE_READ()   => STATUS_SEMANTIC_ERROR,
 
326
        ER_TRG_DOES_NOT_EXIST() => STATUS_SEMANTIC_ERROR,
 
327
        ER_NO_DB_ERROR()        => STATUS_SEMANTIC_ERROR,
 
328
        ER_KEY_COLUMN_DOES_NOT_EXIST()  => STATUS_SEMANTIC_ERROR,
 
329
        ER_SP_DOES_NOT_EXIST()  => STATUS_SEMANTIC_ERROR,
 
330
        ER_BAD_NULL_ERROR()     => STATUS_SEMANTIC_ERROR,
 
331
        ER_SAME_NAME_PARTITION() => STATUS_SEMANTIC_ERROR,
 
332
        ER_TABLE_EXISTS_ERROR() => STATUS_SEMANTIC_ERROR,
 
333
        ER_MULTIPLE_PRI_KEY()   => STATUS_SEMANTIC_ERROR,
 
334
        ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG() => STATUS_SEMANTIC_ERROR,
 
335
        ER_NOT_SUPPORTED_YET()  => STATUS_SEMANTIC_ERROR,
 
336
        ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT() => STATUS_SEMANTIC_ERROR,
 
337
        ER_TRANS_CACHE_FULL()   => STATUS_SEMANTIC_ERROR,
 
338
        ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG() => STATUS_SEMANTIC_ERROR,
 
339
        ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG() => STATUS_SEMANTIC_ERROR,
 
340
        ER_CANNOT_USER() => STATUS_SEMANTIC_ERROR,
 
341
        ER_CHECK_NOT_IMPLEMENTED() => STATUS_SEMANTIC_ERROR,
 
342
        ER_CANT_AGGREGATE_2COLLATIONS() => STATUS_SEMANTIC_ERROR,
 
343
        ER_CANT_AGGREGATE_3COLLATIONS() => STATUS_SEMANTIC_ERROR,
 
344
        ER_CANT_AGGREGATE_NCOLLATIONS() => STATUS_SEMANTIC_ERROR,
 
345
        ER_INVALID_CHARACTER_STRING()   => STATUS_SEMANTIC_ERROR,
 
346
        ER_UNKNOWN_SYSTEM_VARIABLE()    => STATUS_SEMANTIC_ERROR,
 
347
        ER_SP_ALREADY_EXISTS()          => STATUS_SEMANTIC_ERROR,
 
348
        ER_EVENT_ALREADY_EXISTS()       => STATUS_SEMANTIC_ERROR,
 
349
        ER_TRG_ALREADY_EXISTS()         => STATUS_SEMANTIC_ERROR,
 
350
        ER_WRONG_FIELD_WITH_GROUP()     => STATUS_SEMANTIC_ERROR,
 
351
        ER_NON_GROUPING_FIELD_USED()    => STATUS_SEMANTIC_ERROR,
 
352
        ER_NON_UNIQ_ERROR()             => STATUS_SEMANTIC_ERROR,
 
353
        ER_EVENT_DOES_NOT_EXIST()       => STATUS_SEMANTIC_ERROR,
 
354
        ER_NONEXISTING_GRANT()          => STATUS_SEMANTIC_ERROR,
 
355
        ER_NONEXISTING_TABLE_GRANT()    => STATUS_SEMANTIC_ERROR,
 
356
        ER_WRONG_AUTO_KEY()             => STATUS_SEMANTIC_ERROR,
 
357
        ER_SP_DUP_PARAM()               => STATUS_SEMANTIC_ERROR,
 
358
        ER_WRONG_OBJECT()               => STATUS_SEMANTIC_ERROR,
 
359
        ER_WRONG_USAGE()                => STATUS_SEMANTIC_ERROR,
 
360
        ER_VIEW_SELECT_DERIVED()        => STATUS_SEMANTIC_ERROR,
 
361
        ER_DB_CREATE_EXISTS()           => STATUS_SEMANTIC_ERROR,
 
362
        ER_CANT_REOPEN_TABLE()          => STATUS_SEMANTIC_ERROR,
 
363
        ER_TRG_ON_VIEW_OR_TEMP_TABLE()  => STATUS_SEMANTIC_ERROR,
 
364
        ER_VIEW_SELECT_TMPTABLE()       => STATUS_SEMANTIC_ERROR,
 
365
        ER_NONUPDATEABLE_COLUMN()       => STATUS_SEMANTIC_ERROR,
 
366
        ER_TOO_BIG_SELECT()             => STATUS_SEMANTIC_ERROR,
 
367
        ER_TABLE_CANT_HANDLE_BLOB()     => STATUS_SEMANTIC_ERROR,
 
368
        ER_TOO_MANY_ROWS()              => STATUS_SEMANTIC_ERROR,
 
369
 
 
370
        ER_PARTITION_MGMT_ON_NONPARTITIONED()   => STATUS_SEMANTIC_ERROR,
 
371
        ER_DROP_LAST_PARTITION()                => STATUS_SEMANTIC_ERROR,
 
372
        ER_COALESCE_ONLY_ON_HASH_PARTITION()    => STATUS_SEMANTIC_ERROR,
 
373
        ER_REORG_HASH_ONLY_ON_SAME_NO()         => STATUS_SEMANTIC_ERROR,
 
374
        ER_REORG_NO_PARAM_ERROR()               => STATUS_SEMANTIC_ERROR,
 
375
        ER_ONLY_ON_RANGE_LIST_PARTITION()       => STATUS_SEMANTIC_ERROR,
 
376
        ER_NO_PARTITION_FOR_GIVEN_VALUE()       => STATUS_SEMANTIC_ERROR,
 
377
        ER_DROP_PARTITION_NON_EXISTENT()        => STATUS_SEMANTIC_ERROR,
 
378
        ER_PARTITION_MAXVALUE_ERROR()           => STATUS_SEMANTIC_ERROR,
 
379
        ER_WRONG_PARTITION_NAME()               => STATUS_SEMANTIC_ERROR,
 
380
        ER_NO_PARTS_ERROR()                     => STATUS_SEMANTIC_ERROR,
 
381
 
 
382
        ER_NON_INSERTABLE_TABLE()               => STATUS_SEMANTIC_ERROR,
 
383
        ER_NON_UPDATABLE_TABLE()                => STATUS_SEMANTIC_ERROR,
 
384
 
 
385
        ER_UNKNOWN_KEY_CACHE()                  => STATUS_SEMANTIC_ERROR,
 
386
        
 
387
        ER_CANT_CHANGE_TX_ISOLATION()           => STATUS_SEMANTIC_ERROR,
 
388
        ER_MIX_OF_GROUP_FUNC_AND_FIELDS()       => STATUS_SEMANTIC_ERROR,
 
389
 
 
390
        ER_UNKNOWN_STMT_HANDLER()               => STATUS_SEMANTIC_ERROR,
 
391
        ER_NEED_REPREPARE()                     => STATUS_SEMANTIC_ERROR,
 
392
        ER_CANT_UPDATE_WITH_READLOCK()          => STATUS_SEMANTIC_ERROR,
 
393
        ER_NONUNIQ_TABLE()                      => STATUS_SEMANTIC_ERROR,
 
394
        ER_VIEW_INVALID()                       => STATUS_SEMANTIC_ERROR,
 
395
 
 
396
        ER_NO_SUCH_THREAD()                     => STATUS_SEMANTIC_ERROR,
 
397
        ER_QUERY_INTERRUPTED()                  => STATUS_SEMANTIC_ERROR,
 
398
 
 
399
        ER_UNKNOWN_TABLE()                      => STATUS_SEMANTIC_ERROR,
 
400
        ER_FILE_NOT_FOUND()                     => STATUS_SEMANTIC_ERROR,
 
401
        ER_WRONG_MRG_TABLE()                    => STATUS_SEMANTIC_ERROR,
 
402
        ER_OPEN_AS_READONLY()                   => STATUS_SEMANTIC_ERROR,
 
403
 
 
404
        ER_SP_DUP_COND()                        => STATUS_SEMANTIC_ERROR,
 
405
        ER_SP_DUP_HANDLER()                     => STATUS_SEMANTIC_ERROR,
 
406
        ER_SIGNAL_BAD_CONDITION_TYPE()          => STATUS_SEMANTIC_ERROR,
 
407
        ER_SP_COND_MISMATCH()                   => STATUS_SEMANTIC_ERROR,
 
408
        ER_DUP_SIGNAL_SET()                     => STATUS_SEMANTIC_ERROR,
 
409
        ER_WRONG_VALUE()                        => STATUS_SEMANTIC_ERROR,
 
410
        ER_SP_NO_RECURSION()                    => STATUS_SEMANTIC_ERROR,
 
411
        ER_SIGNAL_EXCEPTION()                   => STATUS_SEMANTIC_ERROR,
 
412
        ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER()    => STATUS_SEMANTIC_ERROR,
 
413
        ER_WRONG_VALUE_FOR_VAR()                => STATUS_SEMANTIC_ERROR,
 
414
        ER_SP_NO_RETSET()                       => STATUS_SEMANTIC_ERROR,
 
415
        ER_SP_NORETURNEND()                     => STATUS_SEMANTIC_ERROR,
 
416
        ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG()=> STATUS_SEMANTIC_ERROR,
 
417
        ER_SP_RECURSION_LIMIT()                 => STATUS_SEMANTIC_ERROR,
 
418
 
 
419
        ER_CANT_USE_OPTION_HERE()               => STATUS_SEMANTIC_ERROR,
 
420
        ER_TOO_LONG_KEY()                       => STATUS_SEMANTIC_ERROR,
 
421
 
 
422
        ER_LOCK_OR_ACTIVE_TRANSACTION => STATUS_TRANSACTION_ERROR,
 
423
 
 
424
        ER_LOCK_DEADLOCK()      => STATUS_TRANSACTION_ERROR,
 
425
        ER_LOCK_WAIT_TIMEOUT()  => STATUS_TRANSACTION_ERROR,
 
426
        ER_CHECKREAD()          => STATUS_TRANSACTION_ERROR,
 
427
        ER_DUP_KEY()            => STATUS_TRANSACTION_ERROR,
 
428
        ER_DUP_ENTRY()          => STATUS_TRANSACTION_ERROR,
 
429
        
 
430
        ER_NOT_KEYFILE()        => STATUS_DATABASE_CORRUPTION,
 
431
        ER_KEY_NOT_FOUND()      => STATUS_DATABASE_CORRUPTION,
 
432
        ER_CRASHED_ON_USAGE()   => STATUS_DATABASE_CORRUPTION,
 
433
        ER_CRASHED1()           => STATUS_DATABASE_CORRUPTION,
 
434
        ER_CRASHED2()           => STATUS_DATABASE_CORRUPTION,
 
435
        ER_UNEXPECTED_EOF()     => STATUS_DATABASE_CORRUPTION,
 
436
#       ER_SP_PROC_TABLE_CORRUPT() => STATUS_DATABASE_CORRUPTION,       # this error is bogus due to bug # 47870
 
437
        ER_ILLEGAL_HA()         => STATUS_SEMANTIC_ERROR,
 
438
 
 
439
        ER_BACKUP_SEND_DATA1()  => STATUS_BACKUP_FAILURE,
 
440
        ER_BACKUP_SEND_DATA2()  => STATUS_BACKUP_FAILURE,
 
441
        ER_BACKUP_PROGRESS_TABLES() => STATUS_BACKUP_FAILURE,
 
442
        ER_BACKUP_RUNNING()     => STATUS_SEMANTIC_ERROR,
 
443
 
 
444
        ER_CANT_CREATE_THREAD() => STATUS_ENVIRONMENT_FAILURE,
 
445
        ER_OUT_OF_RESOURCES()   => STATUS_ENVIRONMENT_FAILURE,
 
446
        ER_CON_COUNT_ERROR()    => STATUS_ENVIRONMENT_FAILURE,
 
447
        ER_RECORD_FILE_FULL()   => STATUS_ENVIRONMENT_FAILURE,
 
448
        ER_DISK_FULL()          => STATUS_ENVIRONMENT_FAILURE,
 
449
        ER_OUTOFMEMORY()        => STATUS_ENVIRONMENT_FAILURE,
 
450
        ER_STACK_OVERRUN()      => STATUS_ENVIRONMENT_FAILURE,
 
451
        ER_UNKNOWN_STORAGE_ENGINE() => STATUS_ENVIRONMENT_FAILURE,
 
452
        ER_BACKUP_NOT_ENABLED() => STATUS_ENVIRONMENT_FAILURE,
 
453
        ER_FEATURE_DISABLED()   => STATUS_ENVIRONMENT_FAILURE,
 
454
        ER_OPTION_PREVENTS_STATEMENT() => STATUS_ENVIRONMENT_FAILURE,
 
455
 
 
456
        ER_SERVER_SHUTDOWN()    => STATUS_SERVER_KILLED
 
457
);
 
458
 
 
459
sub init {
 
460
        my $executor = shift;
 
461
        my $dbh = DBI->connect($executor->dsn(), undef, undef, {
 
462
                PrintError => 0,
 
463
                RaiseError => 0,
 
464
                AutoCommit => 1,
 
465
                mysql_multi_statements => 1
 
466
        } );
 
467
 
 
468
        if (not defined $dbh) {
 
469
                say("connect() to dsn ".$executor->dsn()." failed: ".$DBI::errstr);
 
470
                return STATUS_ENVIRONMENT_FAILURE;
 
471
        }
 
472
 
 
473
        $executor->setDbh($dbh);
 
474
 
 
475
        # 
 
476
        # Hack around bug 35676, optiimzer_switch must be set sesson-wide in order to have effect
 
477
        # So we read it from the GLOBAL_VARIABLE table and set it locally to the session
 
478
        #
 
479
 
 
480
        $dbh->do("
 
481
                SET optimizer_switch = (
 
482
                        SELECT variable_value
 
483
                        FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
 
484
                        WHERE VARIABLE_NAME = 'optimizer_switch'
 
485
                )
 
486
        ");
 
487
 
 
488
        $executor->defaultSchema($executor->currentSchema());
 
489
 
 
490
#       say("Executor initialized. id: ".$executor->id()."; default schema: ".$executor->defaultSchema());
 
491
 
 
492
        return STATUS_OK;
 
493
}
 
494
 
 
495
sub reportError {
 
496
    my ($self, $query, $err, $errstr, $silent) = @_;
 
497
    
 
498
    my $msg = [$query,$err,$errstr];
 
499
    
 
500
    if (defined $self->channel) {
 
501
        $self->sendError($msg) if !$silent;
 
502
    } elsif (not defined $reported_errors{$errstr}) {
 
503
        say("Query: $query failed: $err $errstr. Further errors of this kind will be suppressed.") if !$silent;
 
504
        $reported_errors{$errstr}++;
 
505
    }
 
506
}
 
507
 
 
508
sub execute {
 
509
        my ($executor, $query, $silent) = @_;
 
510
 
 
511
        # Filter out any /*executor */ comments that do not pertain to this particular Executor/DBI
 
512
        my $executor_id = $executor->id();
 
513
        $query =~ s{/\*executor$executor_id (.*?) \*/}{$1}sg;
 
514
        $query =~ s{/\*executor.*?\*/}{}sgo;
 
515
    
 
516
    if ($executor->sqltrace) {
 
517
        print "$query;\n";
 
518
    }
 
519
 
 
520
        my $dbh = $executor->dbh();
 
521
 
 
522
        return GenTest::Result->new( query => $query, status => STATUS_UNKNOWN_ERROR ) if not defined $dbh;
 
523
 
 
524
    $query = $executor->preprocess($query);
 
525
 
 
526
        if (
 
527
                (not defined $executor->[EXECUTOR_MYSQL_AUTOCOMMIT]) &&
 
528
                (
 
529
                        ($query =~ m{^\s*start\s+transaction}io) ||
 
530
                        ($query =~ m{^\s*begin}io) 
 
531
                )
 
532
        ) {     
 
533
                $dbh->do("SET AUTOCOMMIT=OFF");
 
534
                $executor->[EXECUTOR_MYSQL_AUTOCOMMIT] = 0;
 
535
        }
 
536
 
 
537
        my $start_time = Time::HiRes::time();
 
538
        my $sth = $dbh->prepare($query);
 
539
 
 
540
        if (not defined $sth) {                 # Error on PREPARE
 
541
                my $errstr = $executor->normalizeError($sth->errstr());
 
542
                $executor->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
 
543
                return GenTest::Result->new(
 
544
                        query           => $query,
 
545
                        status          => $executor->getStatusFromErr($dbh->err()) || STATUS_UNKNOWN_ERROR,
 
546
                        err             => $dbh->err(),
 
547
                        errstr          => $dbh->errstr(),
 
548
                        sqlstate        => $dbh->state(),
 
549
                        start_time      => $start_time,
 
550
                        end_time        => Time::HiRes::time()
 
551
                );
 
552
        }
 
553
 
 
554
        my $affected_rows = $sth->execute();
 
555
 
 
556
        my $mysql_info = $dbh->{'mysql_info'};
 
557
        my ($matched_rows, $changed_rows) = $mysql_info =~ m{^Rows matched:\s+(\d+)\s+Changed:\s+(\d+)}sgio;
 
558
 
 
559
        my $column_names = $sth->{NAME} if $sth->{NUM_OF_FIELDS} > 0;
 
560
        my $column_types = $sth->{mysql_type_name} if $sth->{NUM_OF_FIELDS} > 0;
 
561
 
 
562
        my $end_time = Time::HiRes::time();
 
563
 
 
564
        my $err = $sth->err();
 
565
        my $err_type = $err2type{$err} || STATUS_OK;
 
566
        $executor->[EXECUTOR_STATUS_COUNTS]->{$err_type}++ if rqg_debug() && !$silent;
 
567
 
 
568
        my $result;
 
569
 
 
570
        if (defined $err) {                     # Error on EXECUTE
 
571
 
 
572
                if (
 
573
                        ($err_type == STATUS_SYNTAX_ERROR) ||
 
574
                        ($err_type == STATUS_SEMANTIC_ERROR) ||
 
575
                        ($err_type == STATUS_TRANSACTION_ERROR)
 
576
                ) {
 
577
                        my $errstr = $executor->normalizeError($sth->errstr());
 
578
                        $executor->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
 
579
                        $executor->reportError($query, $err, $errstr, $silent);
 
580
                } elsif (
 
581
                        ($err_type == STATUS_SERVER_CRASHED) ||
 
582
                        ($err_type == STATUS_SERVER_KILLED)
 
583
                ) {
 
584
                        $dbh = DBI->connect($executor->dsn(), undef, undef, {
 
585
                                PrintError => 0,
 
586
                                RaiseError => 0,
 
587
                                AutoCommit => 1,
 
588
                                mysql_multi_statements => 1
 
589
                        } );
 
590
 
 
591
                        # If server is still connectable, it is not a real crash, but most likely a KILL query
 
592
 
 
593
                        if (defined $dbh) {
 
594
                                $err_type = STATUS_SEMANTIC_ERROR;
 
595
                                $executor->setDbh($dbh);
 
596
                        }
 
597
 
 
598
                        say("Query: $query failed: $err ".$sth->errstr()) if !$silent;
 
599
                } else {
 
600
                        $executor->[EXECUTOR_ERROR_COUNTS]->{$sth->errstr()}++ if rqg_debug() && !$silent;
 
601
                        say("Query: $query failed: $err ".$sth->errstr()) if !$silent;
 
602
                }
 
603
 
 
604
                $result = GenTest::Result->new(
 
605
                        query           => $query,
 
606
                        status          => $err_type || STATUS_UNKNOWN_ERROR,
 
607
                        err             => $err,
 
608
                        errstr          => $sth->errstr(),
 
609
                        sqlstate        => $sth->state(),
 
610
                        start_time      => $start_time,
 
611
                        end_time        => $end_time
 
612
                );
 
613
        } elsif ((not defined $sth->{NUM_OF_FIELDS}) || ($sth->{NUM_OF_FIELDS} == 0)) {
 
614
                $result = GenTest::Result->new(
 
615
                        query           => $query,
 
616
                        status          => STATUS_OK,
 
617
                        affected_rows   => $affected_rows,
 
618
                        matched_rows    => $matched_rows,
 
619
                        changed_rows    => $changed_rows,
 
620
                        info            => $mysql_info,
 
621
                        start_time      => $start_time,
 
622
                        end_time        => $end_time
 
623
                );
 
624
                $executor->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
 
625
        } else {
 
626
                #
 
627
                # We do not use fetchall_arrayref() due to a memory leak
 
628
                # We also copy the row explicitly into a fresh array
 
629
                # otherwise the entire @data array ends up referencing row #1 only
 
630
                #
 
631
                my @data;
 
632
                while (my $row = $sth->fetchrow_arrayref()) {
 
633
                        my @row = @$row;
 
634
                        push @data, \@row;
 
635
                }       
 
636
 
 
637
                $result = GenTest::Result->new(
 
638
                        query           => $query,
 
639
                        status          => STATUS_OK,
 
640
                        affected_rows   => $affected_rows,
 
641
                        data            => \@data,
 
642
                        start_time      => $start_time,
 
643
                        end_time        => $end_time,
 
644
                        column_names    => $column_names,
 
645
                        column_types    => $column_types
 
646
                );
 
647
 
 
648
                $executor->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
 
649
        }
 
650
 
 
651
        $sth->finish();
 
652
 
 
653
        if ($sth->{mysql_warning_count} > 0) {
 
654
                my $warnings = $dbh->selectall_arrayref("SHOW WARNINGS");
 
655
                $result->setWarnings($warnings);
 
656
        }
 
657
 
 
658
        if ( (rqg_debug()) && (!$silent) ) {
 
659
                if ($query =~ m{^\s*select}sio) {
 
660
                        $executor->explain($query);
 
661
                        my $row_group = $sth->rows() > 100 ? '>100' : ($sth->rows() > 10 ? ">10" : sprintf("%5d",$sth->rows()) );
 
662
                        $executor->[EXECUTOR_RETURNED_ROW_COUNTS]->{$row_group}++;
 
663
                } elsif ($query =~ m{^\s*(update|delete|insert|replace)}sio) {
 
664
                        my $row_group = $affected_rows > 100 ? '>100' : ($affected_rows > 10 ? ">10" : sprintf("%5d",$affected_rows) );
 
665
                        $executor->[EXECUTOR_AFFECTED_ROW_COUNTS]->{$row_group}++;
 
666
                }
 
667
        }
 
668
 
 
669
        return $result;
 
670
}
 
671
 
 
672
sub version {
 
673
        my $executor = shift;
 
674
        my $dbh = $executor->dbh();
 
675
        return $dbh->selectrow_array("SELECT VERSION()");
 
676
}
 
677
 
 
678
sub slaveInfo {
 
679
        my $executor = shift;
 
680
        my $slave_info = $executor->dbh()->selectrow_arrayref("SHOW SLAVE HOSTS");
 
681
        return ($slave_info->[SLAVE_INFO_HOST], $slave_info->[SLAVE_INFO_PORT]);
 
682
}
 
683
 
 
684
sub masterStatus {
 
685
        my $executor = shift;
 
686
        return $executor->dbh()->selectrow_array("SHOW MASTER STATUS");
 
687
}
 
688
 
 
689
#
 
690
# Run EXPLAIN on the query in question, recording all notes in the EXPLAIN's Extra field into the statistics
 
691
#
 
692
 
 
693
sub explain {
 
694
        my ($executor, $query) = @_;
 
695
 
 
696
        my $sth_output = $executor->dbh()->prepare("EXPLAIN /*!50100 PARTITIONS */ $query");
 
697
 
 
698
        $sth_output->execute();
 
699
 
 
700
        my @explain_fragments;
 
701
 
 
702
        while (my $explain_row = $sth_output->fetchrow_hashref()) {
 
703
                push @explain_fragments, "select_type: ".($explain_row->{select_type} || '(empty)');
 
704
 
 
705
                push @explain_fragments, "type: ".($explain_row->{type} || '(empty)');
 
706
 
 
707
                push @explain_fragments, "partitions: ".$explain_row->{table}.":".$explain_row->{partitions} if defined $explain_row->{partitions};
 
708
 
 
709
                foreach my $extra_item (split('; ', ($explain_row->{Extra} || '(empty)')) ) {
 
710
                        $extra_item =~ s{0x.*?\)}{%d\)}sgio;
 
711
                        $extra_item =~ s{PRIMARY|[a-z_]+_key|i_l_[a-z_]+}{%s}sgio;
 
712
                        push @explain_fragments, "extra: ".$extra_item;
 
713
                }
 
714
        }
 
715
        
 
716
        foreach my $explain_fragment (@explain_fragments) {
 
717
                $executor->[EXECUTOR_EXPLAIN_COUNTS]->{$explain_fragment}++;
 
718
                if ($executor->[EXECUTOR_EXPLAIN_COUNTS]->{$explain_fragment} > RARE_QUERY_THRESHOLD) {
 
719
                        delete $executor->[EXECUTOR_EXPLAIN_QUERIES]->{$explain_fragment};
 
720
                } else {
 
721
                        push @{$executor->[EXECUTOR_EXPLAIN_QUERIES]->{$explain_fragment}}, $query;
 
722
                }
 
723
        }
 
724
 
 
725
}
 
726
 
 
727
 
 
728
 
 
729
sub disconnect {
 
730
        my $executor = shift;
 
731
        $executor->dbh()->disconnect() if defined $executor->dbh();
 
732
        $executor->setDbh(undef);
 
733
}
 
734
 
 
735
sub DESTROY {
 
736
        my $executor = shift;
 
737
        $executor->disconnect();
 
738
 
 
739
        if (
 
740
                (rqg_debug()) &&
 
741
                (defined $executor->[EXECUTOR_STATUS_COUNTS])
 
742
        ) {
 
743
                say("Statistics for Executor ".$executor->dsn());
 
744
                use Data::Dumper;
 
745
                $Data::Dumper::Sortkeys = 1;
 
746
                say("Rows returned:");
 
747
                print Dumper $executor->[EXECUTOR_RETURNED_ROW_COUNTS];
 
748
                say("Rows affected:");
 
749
                print Dumper $executor->[EXECUTOR_AFFECTED_ROW_COUNTS];
 
750
                say("Explain items:");
 
751
                print Dumper $executor->[EXECUTOR_EXPLAIN_COUNTS];
 
752
                say("Errors:");
 
753
                print Dumper $executor->[EXECUTOR_ERROR_COUNTS];
 
754
                say("Rare EXPLAIN items:");
 
755
                print Dumper $executor->[EXECUTOR_EXPLAIN_QUERIES];
 
756
                say("Statuses: ".join(', ', map { status2text($_).": ".$executor->[EXECUTOR_STATUS_COUNTS]->{$_}." queries" } keys %{$executor->[EXECUTOR_STATUS_COUNTS]}));
 
757
        }
 
758
}
 
759
 
 
760
sub currentSchema {
 
761
        my ($executor,$schema) = @_;
 
762
 
 
763
        return undef if not defined $executor->dbh();
 
764
 
 
765
    if (defined $schema) {
 
766
        $executor->execute("USE $schema");
 
767
    }
 
768
    
 
769
        return $executor->dbh()->selectrow_array("SELECT DATABASE()");
 
770
}
 
771
 
 
772
 
 
773
sub errorType {
 
774
        return undef if not defined $_[0];
 
775
        return $err2type{$_[0]} || STATUS_UNKNOWN_ERROR ;
 
776
}
 
777
 
 
778
sub normalizeError {
 
779
        my ($executor, $errstr) = @_;
 
780
 
 
781
        foreach my $i (0..$#errors) {
 
782
                last if $errstr =~ s{$patterns[$i]}{$errors[$i]}si;
 
783
        }
 
784
 
 
785
        $errstr =~ s{\d+}{%d}sgio if $errstr !~ m{from storage engine}sio; # Make all errors involving numbers the same, e.g. duplicate key errors
 
786
 
 
787
        $errstr =~ s{\.\*\?}{%s}sgio;
 
788
 
 
789
        return $errstr;
 
790
}
 
791
 
 
792
 
 
793
sub getSchemaMetaData {
 
794
    ## Return the result from a query with the following columns:
 
795
    ## 1. Schema (aka database) name
 
796
    ## 2. Table name
 
797
    ## 3. TABLE for tables VIEW for views and MISC for other stuff
 
798
    ## 4. Column name
 
799
    ## 5. PRIMARY for primary key, INDEXED for indexed column and "ORDINARY" for all other columns
 
800
    my ($self) = @_;
 
801
    my $query = 
 
802
        "SELECT CASE WHEN table_schema = 'information_schema' ".
 
803
                     "THEN 'INFORMATION_SCHEMA' ".  ## Hack due to
 
804
                                                    ## weird MySQL
 
805
                                                    ## behaviour on
 
806
                                                    ## schema names
 
807
                                                    ## (See Bug#49708)
 
808
                     "ELSE table_schema END, ".
 
809
               "table_name, ".
 
810
               "CASE WHEN table_type = 'BASE TABLE' THEN 'table' ".
 
811
                    "WHEN table_type = 'VIEW' THEN 'view' ".
 
812
                    "WHEN table_type = 'SYSTEM VIEW' then 'view' ".
 
813
                    "ELSE 'misc' END, ".
 
814
               "column_name, ".
 
815
               "CASE WHEN column_key = 'PRI' THEN 'primary' ".
 
816
                    "WHEN column_key = 'MUL' THEN 'indexed' ".
 
817
                    "WHEN column_key = 'UNI' THEN 'indexed' ".
 
818
                    "ELSE 'ordinary' END ".
 
819
         "FROM information_schema.tables INNER JOIN ".
 
820
              "information_schema.columns USING(table_schema, table_name) ".
 
821
          "WHERE table_name <> 'DUMMY'"; 
 
822
 
 
823
    return $self->dbh()->selectall_arrayref($query);
 
824
}
 
825
 
 
826
sub getCollationMetaData {
 
827
    ## Return the result from a query with the following columns:
 
828
    ## 1. Collation name
 
829
    ## 2. Character set
 
830
    my ($self) = @_;
 
831
    my $query = 
 
832
        "SELECT collation_name,character_set_name FROM information_schema.collations";
 
833
 
 
834
    return $self->dbh()->selectall_arrayref($query);
 
835
}
 
836
 
 
837
1;