| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package MySQL::Diff::Database; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
MySQL::Diff::Database - Database Definition Class |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use MySQL::Diff::Database; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my $db = MySQL::Diff::Database->new(%options); |
|
12
|
|
|
|
|
|
|
my $source = $db->source_type(); |
|
13
|
|
|
|
|
|
|
my $summary = $db->summary(); |
|
14
|
|
|
|
|
|
|
my $name = $db->name(); |
|
15
|
|
|
|
|
|
|
my @tables = $db->tables(); |
|
16
|
|
|
|
|
|
|
my $table_def = $db->table_by_name($table); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
my @dbs = MySQL::Diff::Database::available_dbs(); |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Parses a database definition into component parts. |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=cut |
|
25
|
|
|
|
|
|
|
|
|
26
|
3
|
|
|
3
|
|
707
|
use warnings; |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
375
|
|
|
27
|
3
|
|
|
3
|
|
10
|
use strict; |
|
|
3
|
|
|
|
|
3
|
|
|
|
3
|
|
|
|
|
57
|
|
|
28
|
3
|
|
|
3
|
|
1234
|
use String::ShellQuote qw(shell_quote); |
|
|
3
|
|
|
|
|
1969
|
|
|
|
3
|
|
|
|
|
258
|
|
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
our $VERSION = '0.50'; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------ |
|
33
|
|
|
|
|
|
|
# Libraries |
|
34
|
|
|
|
|
|
|
|
|
35
|
3
|
|
|
3
|
|
14
|
use Carp qw(:DEFAULT); |
|
|
3
|
|
|
|
|
3
|
|
|
|
3
|
|
|
|
|
396
|
|
|
36
|
3
|
|
|
3
|
|
1404
|
use File::Slurp; |
|
|
3
|
|
|
|
|
30828
|
|
|
|
3
|
|
|
|
|
199
|
|
|
37
|
3
|
|
|
3
|
|
1471
|
use IO::File; |
|
|
3
|
|
|
|
|
19660
|
|
|
|
3
|
|
|
|
|
323
|
|
|
38
|
|
|
|
|
|
|
|
|
39
|
3
|
|
|
3
|
|
1151
|
use MySQL::Diff::Utils qw(debug); |
|
|
3
|
|
|
|
|
3
|
|
|
|
3
|
|
|
|
|
130
|
|
|
40
|
3
|
|
|
3
|
|
1007
|
use MySQL::Diff::Table; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
4248
|
|
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------ |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 METHODS |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head2 Constructor |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=over 4 |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=item new( %options ) |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Instantiate the objects, providing the command line options for database |
|
53
|
|
|
|
|
|
|
access and process requirements. |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=back |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=cut |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub new { |
|
60
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
|
61
|
0
|
|
|
|
|
|
my %p = @_; |
|
62
|
0
|
|
|
|
|
|
my $self = {}; |
|
63
|
0
|
|
0
|
|
|
|
bless $self, ref $class || $class; |
|
64
|
|
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
|
debug(3,"\nconstructing new MySQL::Diff::Database"); |
|
66
|
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
|
my $auth_ref = _auth_args_string(%{$p{auth}}); |
|
|
0
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
my $string = shell_quote @$auth_ref; |
|
69
|
0
|
|
|
|
|
|
debug(3,"auth args: $string"); |
|
70
|
0
|
|
|
|
|
|
$self->{_source}{auth} = $string; |
|
71
|
0
|
0
|
|
|
|
|
$self->{_source}{dbh} = $p{dbh} if $p{dbh}; |
|
72
|
0
|
|
|
|
|
|
$self->{'single-transaction'} = $p{'single-transaction'}; |
|
73
|
0
|
|
|
|
|
|
$self->{'table-re'} = $p{'table-re'}; |
|
74
|
|
|
|
|
|
|
|
|
75
|
0
|
0
|
|
|
|
|
if ($p{file}) { |
|
|
|
0
|
|
|
|
|
|
|
76
|
0
|
|
|
|
|
|
$self->_canonicalise_file($p{file}); |
|
77
|
|
|
|
|
|
|
} elsif ($p{db}) { |
|
78
|
0
|
|
|
|
|
|
$self->_read_db($p{db}); |
|
79
|
|
|
|
|
|
|
} else { |
|
80
|
0
|
|
|
|
|
|
confess "MySQL::Diff::Database::new called without db or file params"; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
$self->_parse_defs(); |
|
84
|
0
|
|
|
|
|
|
return $self; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=head2 Public Methods |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=over 4 |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=item * source_type() |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Returns 'file' if the data source is a text file, and 'db' if connected |
|
94
|
|
|
|
|
|
|
directly to a database. |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=cut |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub source_type { |
|
99
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
100
|
0
|
0
|
|
|
|
|
return 'file' if $self->{_source}{file}; |
|
101
|
0
|
0
|
|
|
|
|
return 'db' if $self->{_source}{db}; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=item * summary() |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Provides a summary of the database. |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=cut |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub summary { |
|
111
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
112
|
|
|
|
|
|
|
|
|
113
|
0
|
0
|
|
|
|
|
if ($self->{_source}{file}) { |
|
|
|
0
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
return "file: " . $self->{_source}{file}; |
|
115
|
|
|
|
|
|
|
} elsif ($self->{_source}{db}) { |
|
116
|
0
|
|
|
|
|
|
my $args = $self->{_source}{auth}; |
|
117
|
0
|
|
|
|
|
|
$args =~ tr/-//d; |
|
118
|
0
|
|
|
|
|
|
$args =~ s/\bpassword=\S+//; |
|
119
|
0
|
|
|
|
|
|
$args =~ s/^\s*(.*?)\s*$/$1/; |
|
120
|
0
|
|
|
|
|
|
my $summary = " db: " . $self->{_source}{db}; |
|
121
|
0
|
0
|
|
|
|
|
$summary .= " ($args)" if $args; |
|
122
|
0
|
|
|
|
|
|
return $summary; |
|
123
|
|
|
|
|
|
|
} else { |
|
124
|
0
|
|
|
|
|
|
return 'unknown'; |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item * name() |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Returns the name of the database. |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=cut |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub name { |
|
135
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
136
|
0
|
|
0
|
|
|
|
return $self->{_source}{file} || $self->{_source}{db}; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=item * tables() |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Returns a list of tables for the current database. |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub tables { |
|
146
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
147
|
0
|
|
|
|
|
|
return @{$self->{_tables}}; |
|
|
0
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item * table_by_name( $name ) |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Returns the table definition (see L) for the given table. |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=cut |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub table_by_name { |
|
157
|
0
|
|
|
0
|
1
|
|
my ($self,$name) = @_; |
|
158
|
0
|
|
|
|
|
|
return $self->{_by_name}{$name}; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=back |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 Public Functions |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=over 4 |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=item * available_dbs() |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Returns a list of the available databases. |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Note that is used as a function call, not a method call. |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=cut |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub available_dbs { |
|
178
|
0
|
|
|
0
|
1
|
|
my %auth = @_; |
|
179
|
0
|
|
|
|
|
|
my $args_ref = _auth_args_string(%auth); |
|
180
|
0
|
|
|
|
|
|
unshift @$args_ref, q{mysqlshow}; |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# evil but we don't use DBI because I don't want to implement -p properly |
|
183
|
|
|
|
|
|
|
# not that this works with -p anyway ... |
|
184
|
0
|
|
|
|
|
|
my $command = shell_quote @$args_ref; |
|
185
|
0
|
0
|
|
|
|
|
my $fh = IO::File->new("$command |") or die "Couldn't execute '$command': $!\n"; |
|
186
|
0
|
|
|
|
|
|
my $dbs_ref = _parse_mysqlshow_from_fh_into_arrayref($fh); |
|
187
|
0
|
0
|
|
|
|
|
$fh->close() or die "$command failed: $!"; |
|
188
|
|
|
|
|
|
|
|
|
189
|
0
|
|
|
|
|
|
return map { $_ => 1 } @{$dbs_ref}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=back |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=cut |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------ |
|
197
|
|
|
|
|
|
|
# Private Methods |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub auth_args { |
|
200
|
0
|
|
|
0
|
0
|
|
return _auth_args_string(); |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub _canonicalise_file { |
|
204
|
0
|
|
|
0
|
|
|
my ($self, $file) = @_; |
|
205
|
|
|
|
|
|
|
|
|
206
|
0
|
|
|
|
|
|
$self->{_source}{file} = $file; |
|
207
|
0
|
|
|
|
|
|
debug(2,"fetching table defs from file $file"); |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# FIXME: option to avoid create-and-dump bit |
|
210
|
|
|
|
|
|
|
# create a temporary database using defs from file ... |
|
211
|
|
|
|
|
|
|
# hopefully the temp db is unique! |
|
212
|
0
|
|
|
|
|
|
my $temp_db = sprintf "test_mysqldiff-temp-%d_%d_%d", time(), $$, rand(); |
|
213
|
0
|
|
|
|
|
|
debug(3,"creating temporary database $temp_db"); |
|
214
|
|
|
|
|
|
|
|
|
215
|
0
|
|
|
|
|
|
my $defs = read_file($file); |
|
216
|
0
|
0
|
|
|
|
|
die "$file contains dangerous command '$1'; aborting.\n" |
|
217
|
|
|
|
|
|
|
if $defs =~ /;\s*(use|((drop|create)\s+database))\b/i; |
|
218
|
|
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
my $args = $self->{_source}{auth}; |
|
220
|
0
|
0
|
|
|
|
|
my $fh = IO::File->new("| mysql $args") or die "Couldn't execute 'mysql$args': $!\n"; |
|
221
|
0
|
|
|
|
|
|
print $fh "\nCREATE DATABASE \`$temp_db\`;\nUSE \`$temp_db\`;\n"; |
|
222
|
0
|
|
|
|
|
|
print $fh $defs; |
|
223
|
0
|
|
|
|
|
|
$fh->close; |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# ... and then retrieve defs from mysqldump. Hence we've used |
|
226
|
|
|
|
|
|
|
# MySQL to massage the defs file into canonical form. |
|
227
|
0
|
|
|
|
|
|
$self->_get_defs($temp_db); |
|
228
|
|
|
|
|
|
|
|
|
229
|
0
|
|
|
|
|
|
debug(3,"dropping temporary database $temp_db"); |
|
230
|
0
|
0
|
|
|
|
|
$fh = IO::File->new("| mysql $args") or die "Couldn't execute 'mysql$args': $!\n"; |
|
231
|
0
|
|
|
|
|
|
print $fh "DROP DATABASE \`$temp_db\`;\n"; |
|
232
|
0
|
|
|
|
|
|
$fh->close; |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub _read_db { |
|
236
|
0
|
|
|
0
|
|
|
my ($self, $db) = @_; |
|
237
|
0
|
|
|
|
|
|
$self->{_source}{db} = $db; |
|
238
|
0
|
|
|
|
|
|
debug(3, "fetching table defs from db $db"); |
|
239
|
0
|
|
|
|
|
|
$self->_get_defs($db); |
|
240
|
|
|
|
|
|
|
} |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub _get_tables_to_dump { |
|
243
|
0
|
|
|
0
|
|
|
my ( $self, $db ) = @_; |
|
244
|
|
|
|
|
|
|
|
|
245
|
0
|
|
|
|
|
|
my $tables_ref = $self->_get_tables_in_db($db); |
|
246
|
|
|
|
|
|
|
|
|
247
|
0
|
|
|
|
|
|
my $compiled_table_re = qr/$self->{'table-re'}/; |
|
248
|
|
|
|
|
|
|
|
|
249
|
0
|
|
|
|
|
|
my @matching_tables = grep { $_ =~ $compiled_table_re } @{$tables_ref}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
|
|
251
|
0
|
|
|
|
|
|
return join( ' ', @matching_tables ); |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub _get_tables_in_db { |
|
255
|
0
|
|
|
0
|
|
|
my ( $self, $db ) = @_; |
|
256
|
|
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
my $args = $self->{_source}{auth}; |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# evil but we don't use DBI because I don't want to implement -p properly |
|
260
|
|
|
|
|
|
|
# not that this works with -p anyway ... |
|
261
|
0
|
0
|
|
|
|
|
my $fh = IO::File->new("mysqlshow $args $db|") |
|
262
|
|
|
|
|
|
|
or die "Couldn't execute 'mysqlshow $args $db': $!\n"; |
|
263
|
0
|
|
|
|
|
|
my $tables_ref = _parse_mysqlshow_from_fh_into_arrayref($fh); |
|
264
|
0
|
0
|
|
|
|
|
$fh->close() or die "mysqlshow $args $db failed: $!"; |
|
265
|
|
|
|
|
|
|
|
|
266
|
0
|
|
|
|
|
|
return $tables_ref; |
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# Note that is used as a function call, not a method call. |
|
270
|
|
|
|
|
|
|
sub _parse_mysqlshow_from_fh_into_arrayref { |
|
271
|
0
|
|
|
0
|
|
|
my ($fh) = @_; |
|
272
|
|
|
|
|
|
|
|
|
273
|
0
|
|
|
|
|
|
my @items; |
|
274
|
0
|
|
|
|
|
|
while (<$fh>) { |
|
275
|
0
|
0
|
|
|
|
|
next unless /^\| ([\w-]+)/; |
|
276
|
0
|
|
|
|
|
|
push @items, $1; |
|
277
|
|
|
|
|
|
|
} |
|
278
|
|
|
|
|
|
|
|
|
279
|
0
|
|
|
|
|
|
return \@items; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub _get_defs { |
|
283
|
0
|
|
|
0
|
|
|
my ( $self, $db ) = @_; |
|
284
|
|
|
|
|
|
|
|
|
285
|
0
|
|
|
|
|
|
my $args = $self->{_source}{auth}; |
|
286
|
0
|
0
|
|
|
|
|
my $single_transaction = $self->{'single-transaction'} ? "--single-transaction" : ""; |
|
287
|
0
|
|
|
|
|
|
my $tables = ''; #dump all tables by default |
|
288
|
0
|
0
|
|
|
|
|
if ( my $table_re = $self->{'table-re'} ) { |
|
289
|
0
|
|
|
|
|
|
$tables = $self->_get_tables_to_dump($db); |
|
290
|
0
|
0
|
|
|
|
|
if ( !length $tables ) { # No tables to dump |
|
291
|
0
|
|
|
|
|
|
$self->{_defs} = []; |
|
292
|
0
|
|
|
|
|
|
return; |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
} |
|
295
|
|
|
|
|
|
|
|
|
296
|
0
|
0
|
|
|
|
|
my $fh = IO::File->new("mysqldump -d $single_transaction $args $db $tables 2>&1 |") |
|
297
|
|
|
|
|
|
|
or die "Couldn't read ${db}'s table defs via mysqldump: $!\n"; |
|
298
|
|
|
|
|
|
|
|
|
299
|
0
|
|
|
|
|
|
debug( 3, "running mysqldump -d $single_transaction $args $db $tables" ); |
|
300
|
0
|
|
|
|
|
|
my $defs = $self->{_defs} = [<$fh>]; |
|
301
|
0
|
|
|
|
|
|
$fh->close; |
|
302
|
0
|
|
|
|
|
|
my $exit_status = $? >> 8; |
|
303
|
|
|
|
|
|
|
|
|
304
|
0
|
0
|
|
|
|
|
if ( grep /mysqldump: Got error: .*: Unknown database/, @$defs ) { |
|
|
|
0
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
die <
|
|
306
|
|
|
|
|
|
|
Failed to create temporary database $db |
|
307
|
|
|
|
|
|
|
during canonicalization. Make sure that your mysql.db table has a row |
|
308
|
|
|
|
|
|
|
authorizing full access to all databases matching 'test\\_%', and that |
|
309
|
|
|
|
|
|
|
the database doesn't already exist. |
|
310
|
|
|
|
|
|
|
EOF |
|
311
|
|
|
|
|
|
|
} elsif ($exit_status) { |
|
312
|
|
|
|
|
|
|
# If mysqldump exited with a non-zero status, then |
|
313
|
|
|
|
|
|
|
# we can not reliably make a diff, so better to die and bubble that error up. |
|
314
|
0
|
|
|
|
|
|
die "mysqldump failed. Exit status: $exit_status:\n" . join( "\n", @{$defs} ); |
|
|
0
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
} |
|
316
|
0
|
|
|
|
|
|
return; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub _parse_defs { |
|
320
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
321
|
|
|
|
|
|
|
|
|
322
|
0
|
0
|
|
|
|
|
return if $self->{_tables}; |
|
323
|
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
debug(2, "parsing table defs"); |
|
325
|
0
|
|
|
|
|
|
my $defs = join '', grep ! /^\s*(\#|--|SET|\/\*)/, @{$self->{_defs}}; |
|
|
0
|
|
|
|
|
|
|
|
326
|
0
|
|
|
|
|
|
$defs =~ s/`//sg; |
|
327
|
0
|
|
|
|
|
|
my @tables = split /(?=^\s*(?:create|alter|drop)\s+table\s+)/im, $defs; |
|
328
|
0
|
|
|
|
|
|
$self->{_tables} = []; |
|
329
|
0
|
|
|
|
|
|
for my $table (@tables) { |
|
330
|
0
|
|
|
|
|
|
debug(4, " table def [$table]"); |
|
331
|
0
|
0
|
|
|
|
|
if($table =~ /create\s+table/i) { |
|
332
|
0
|
|
|
|
|
|
my $obj = MySQL::Diff::Table->new(source => $self->{_source}, def => $table); |
|
333
|
0
|
|
|
|
|
|
push @{$self->{_tables}}, $obj; |
|
|
0
|
|
|
|
|
|
|
|
334
|
0
|
|
|
|
|
|
$self->{_by_name}{$obj->name()} = $obj; |
|
335
|
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
} |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub _auth_args_string { |
|
340
|
0
|
|
|
0
|
|
|
my %auth = @_; |
|
341
|
0
|
|
|
|
|
|
my $args = []; |
|
342
|
0
|
|
|
|
|
|
for my $arg (qw/host port user password socket/) { |
|
343
|
0
|
0
|
|
|
|
|
push @$args, qq/--$arg=$auth{$arg}/ if $auth{$arg}; |
|
344
|
|
|
|
|
|
|
} |
|
345
|
0
|
|
|
|
|
|
return $args; |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
1; |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
__END__ |