62
62
. q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), }
63
63
. '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, '
64
64
. '@@SQL_QUOTE_SHOW_CREATE := 1 */';
66
66
eval { $dbh->do($sql); };
67
MKDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
67
PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
69
69
# Must USE the tbl's db because some bug with SHOW CREATE TABLE on a
70
70
# view when the current db isn't the view's db causes MySQL to crash.
71
71
$sql = 'USE ' . $q->quote($db);
72
MKDEBUG && _d($dbh, $sql);
72
PTDEBUG && _d($dbh, $sql);
75
75
$sql = "SHOW CREATE TABLE " . $q->quote($db, $tbl);
78
78
eval { $href = $dbh->selectrow_hashref($sql); };
79
79
if ( $EVAL_ERROR ) {
80
MKDEBUG && _d($EVAL_ERROR);
80
PTDEBUG && _d($EVAL_ERROR);
84
84
$sql = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, '
85
85
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */';
89
89
my ($key) = grep { m/create table/i } keys %$href;
91
MKDEBUG && _d('This table is a base table');
91
PTDEBUG && _d('This table is a base table');
92
92
$href->{$key} =~ s/\b[ ]{2,}/ /g;
93
93
$href->{$key} .= "\n";
96
MKDEBUG && _d('This table is a view');
96
PTDEBUG && _d('This table is a view');
97
97
($key) = grep { m/create view/i } keys %$href;
126
126
my @defs = $ddl =~ m/^(\s+`.*?),?$/gm;
127
127
my @cols = map { $_ =~ m/`([^`]+)`/ } @defs;
128
MKDEBUG && _d('Table cols:', join(', ', map { "`$_`" } @cols));
128
PTDEBUG && _d('Table cols:', join(', ', map { "`$_`" } @cols));
130
130
# Save the column definitions *exactly*
232
232
return () unless $where;
233
233
my $sql = 'EXPLAIN SELECT * FROM ' . $quoter->quote($database, $table)
234
234
. ' WHERE ' . $where;
236
236
my $expl = $dbh->selectrow_hashref($sql);
237
237
# Normalize columns to lowercase
238
238
$expl = { map { lc($_) => $expl->{$_} } keys %$expl };
239
239
if ( $expl->{possible_keys} ) {
240
MKDEBUG && _d('possible_keys =', $expl->{possible_keys});
240
PTDEBUG && _d('possible_keys =', $expl->{possible_keys});
241
241
my @candidates = split(',', $expl->{possible_keys});
242
242
my %possible = map { $_ => 1 } @candidates;
243
243
if ( $expl->{key} ) {
244
MKDEBUG && _d('MySQL chose', $expl->{key});
244
PTDEBUG && _d('MySQL chose', $expl->{key});
245
245
unshift @candidates, grep { $possible{$_} } split(',', $expl->{key});
246
MKDEBUG && _d('Before deduping:', join(', ', @candidates));
246
PTDEBUG && _d('Before deduping:', join(', ', @candidates));
248
248
@candidates = grep { !$seen{$_}++ } @candidates;
250
MKDEBUG && _d('Final list:', join(', ', @candidates));
250
PTDEBUG && _d('Final list:', join(', ', @candidates));
251
251
return @candidates;
254
MKDEBUG && _d('No keys in possible_keys');
254
PTDEBUG && _d('No keys in possible_keys');
278
278
my ($dbh, $db, $tbl) = @args{@required_args};
279
279
my $q = $self->{Quoter};
280
280
my $db_tbl = $q->quote($db, $tbl);
281
MKDEBUG && _d('Checking', $db_tbl);
281
PTDEBUG && _d('Checking', $db_tbl);
283
283
my $sql = "SHOW TABLES FROM " . $q->quote($db)
284
284
. ' LIKE ' . $q->literal_like($tbl);
288
288
$row = $dbh->selectrow_arrayref($sql);
290
290
if ( $EVAL_ERROR ) {
291
MKDEBUG && _d($EVAL_ERROR);
291
PTDEBUG && _d($EVAL_ERROR);
294
294
if ( !$row->[0] || $row->[0] ne $tbl ) {
295
MKDEBUG && _d('Table does not exist');
295
PTDEBUG && _d('Table does not exist');
299
299
# Table exists, return true unless we have privs to check.
300
MKDEBUG && _d('Table exists; no privs to check');
300
PTDEBUG && _d('Table exists; no privs to check');
301
301
return 1 unless $args{all_privs};
303
303
# Get privs select,insert,update.
304
304
$sql = "SHOW FULL COLUMNS FROM $db_tbl";
307
307
$row = $dbh->selectrow_hashref($sql);
309
309
if ( $EVAL_ERROR ) {
310
MKDEBUG && _d($EVAL_ERROR);
310
PTDEBUG && _d($EVAL_ERROR);
313
313
if ( !scalar keys %$row ) {
314
314
# This should never happen.
315
MKDEBUG && _d('Table has no columns:', Dumper($row));
315
PTDEBUG && _d('Table has no columns:', Dumper($row));
318
318
my $privs = $row->{privileges} || $row->{Privileges};
320
320
# Get delete priv since FULL COLUMNS doesn't show it.
321
321
$sql = "DELETE FROM $db_tbl LIMIT 0";
326
326
my $can_delete = $EVAL_ERROR ? 0 : 1;
328
MKDEBUG && _d('User privs on', $db_tbl, ':', $privs,
328
PTDEBUG && _d('User privs on', $db_tbl, ':', $privs,
329
329
($can_delete ? 'delete' : ''));
331
331
# Check that we have all privs.
332
332
if ( !($privs =~ m/select/ && $privs =~ m/insert/ && $privs =~ m/update/
333
333
&& $can_delete) ) {
334
MKDEBUG && _d('User does not have all privs');
334
PTDEBUG && _d('User does not have all privs');
338
MKDEBUG && _d('User has all privs');
338
PTDEBUG && _d('User has all privs');
343
343
my ( $self, $ddl, $opts ) = @_;
344
344
my ( $engine ) = $ddl =~ m/\).*?(?:ENGINE|TYPE)=(\w+)/;
345
MKDEBUG && _d('Storage engine:', $engine);
345
PTDEBUG && _d('Storage engine:', $engine);
346
346
return $engine || undef;
497
497
$sql .= ' LIKE ?';
498
498
push @params, $like;
500
MKDEBUG && _d($sql, @params);
500
PTDEBUG && _d($sql, @params);
501
501
my $sth = $dbh->prepare($sql);
502
502
eval { $sth->execute(@params); };
503
503
if ($EVAL_ERROR) {
504
MKDEBUG && _d($EVAL_ERROR);
504
PTDEBUG && _d($EVAL_ERROR);
507
507
my @tables = @{$sth->fetchall_arrayref({})};