File Coverage

blib/lib/MySQL/Util/CLI.pm
Criterion Covered Total %
statement 171 511 33.4
branch 0 192 0.0
condition 0 48 0.0
subroutine 57 79 72.1
pod n/a
total 228 830 27.4


line stmt bran cond sub pod time code
1             package MySQL::Util::CLI;
2             $MySQL::Util::CLI::VERSION = '0.002';
3             =head1 NAME
4              
5             MySQL::Util::CLI
6              
7             =head1 VERSION
8              
9             version 0.002
10              
11             =cut
12              
13 2     2   324805 use Modern::Perl;
  2         22  
  2         19  
14 2     2   1457 use Moose;
  2         924233  
  2         13  
15 2     2   16408 use namespace::autoclean;
  2         16860  
  2         8  
16 2     2   1106 use Kavorka '-all';
  2         21257  
  2         15  
17 2     2   743057 use MySQL::Util;
  2         642206  
  2         102  
18 2     2   19 use Carp;
  2         4  
  2         161  
19 2     2   14 use Data::Printer alias => 'pdump';
  2         13  
  2         24  
20              
21             with 'Util::Medley::Roles::Attributes::Logger';
22             with 'Util::Medley::Roles::Attributes::String';
23              
24 2     2   2692 use constant DEFAULT_USER => 'root';
  2         4  
  2         154  
25 2     2   13 use constant DEFAULT_PORT => 3306;
  2         4  
  2         97  
26 2     2   16 use constant DEFAULT_HOST => 'localhost';
  2         4  
  2         96  
27 2     2   12 use constant DEFAULT_DBNAME => 'mysql';
  2         5  
  2         347  
28              
29             ##################################################################
30              
31             # MYSQL_USER, DBI_USER, USER, DEFAULT_USER
32             has user => (
33             is => 'rw',
34             isa => 'Str',
35             lazy => 1,
36             builder => '_buildUser',
37             );
38              
39             # MYSQL_PASS, MYSQL_PWD, or confess
40             has pass => (
41             is => 'rw',
42             isa => 'Str',
43             lazy => 1,
44             builder => '_buildPass',
45             );
46              
47             # MYSQL_HOST or DEFAULT_HOST
48             has host => (
49             is => 'rw',
50             isa => 'Str',
51             lazy => 1,
52             builder => '_buildHost',
53             );
54              
55             # MYSQL_PORT, MYSQL_TCP_PORT, or DEFAULT_PORT
56             has port => (
57             is => 'rw',
58             isa => 'Str',
59             lazy => 1,
60             builder => '_buildPort',
61             );
62              
63             # MYSQL_DBNAME, MYSQL_SCHEMA, or DEFAULT_DBNAME
64             has dbName => (
65             is => 'rw',
66             isa => 'Str',
67             lazy => 1,
68             builder => '_buildDbName',
69             );
70              
71             has raiseError => (
72             is => 'ro',
73             isa => 'Int',
74             default => 1,
75             );
76              
77             has printError => (
78             is => 'ro',
79             isa => 'Int',
80             default => 0,
81             );
82              
83             has fetchHashKeyName => (
84             is => 'ro',
85             isa => 'Str',
86             default => 'NAME_lc',
87             );
88              
89             has dryRun => (
90             is => 'ro',
91             isa => 'Bool',
92             default => 0,
93             );
94              
95             ##################################################################
96              
97             has _util => (
98             is => 'rw',
99             isa => 'MySQL::Util',
100             lazy => 1,
101             builder => '_buildUtil',
102             );
103              
104             has _dbh => (
105             is => 'rw',
106             lazy => 1,
107             builder => '_buildDbh',
108             );
109              
110             ##################################################################
111              
112             #
113             # drop all anonymous user entries
114             # * dropUser(userName => '')
115             #
116             # drop all user foo entries
117             # * dropUser(userName => 'foo')
118             #
119             # drop all root entries except '%'
120             # * dropUser(userName => 'root', keepHosts => ['%'])
121             #
122             method dropUser (Str :$userName!,
123             Str :$hosts,
124 2 0 0 2   66048 ArrayRef[Str] :$keepHosts) {
  2 0 0 2   5  
  2 0   2   233  
  2 0   2   15  
  2 0   0   13  
  2 0       108  
  2 0       1190  
  2 0       2797  
  2 0       14  
  2         194  
  2         5  
  2         1830  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
125              
126 0           my @sql = ('select * from user');
127 0           my @where = ('user = ?');
128 0           my @bind = ($userName);
129              
130 0 0         if ($hosts) {
    0          
131 0           foreach my $host (@$hosts) {
132 0           push @where, 'host = ?';
133 0           push @bind, $hosts;
134             }
135             }
136             elsif ($keepHosts) {
137 0           foreach my $keepHost (@$keepHosts) {
138 0           push @where, 'host != ?';
139 0           push @bind, $keepHost;
140             }
141             }
142              
143 0           push @sql, 'where', join(' and '), @where;
144 0           my $sql = join ' ', @sql;
145              
146 0           $self->Logger->verbose( sprintf 'bind vars: (%s)', join( ', ', @bind ) );
147 0           $self->Logger->verbose($sql);
148              
149 0           my $dbh = $self->getDbh;
150 0           my $sth = $dbh->prepare($sql);
151 0           $sth->execute(@bind);
152              
153 0           while ( my $href = $sth->fetchrow_hashref ) {
154              
155 0           my $sql = sprintf q{drop user '%s'@'%s'}, $userName, $href->{host};
156 0           $self->doSql( sql => $sql );
157             }
158              
159 0           $self->flushPrivileges;
160             }
161              
162             method createDatabase (Str :$dbName!,
163 2 0 0 2   7151 Bool :$ifNotExists = 1) {
  2 0 0 2   6  
  2 0   2   246  
  2 0   2   15  
  2 0   0   4  
  2 0       85  
  2         23  
  2         5  
  2         9  
  2         151  
  2         4  
  2         1119  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
164              
165 0           my @sql = 'create database';
166 0 0         push @sql, "if not exists" if $ifNotExists;
167 0           push @sql, $dbName;
168              
169 0           $self->doSql( sql => join( ' ', @sql ) );
170             }
171              
172             method getGrants (Str :$forUser,
173 2 0 0 2   7286 Str :$forHost) {
  2 0 0 2   5  
  2 0   2   272  
  2 0   2   16  
  2 0   0   6  
  2 0       103  
  2 0       14  
  2         4  
  2         25  
  2         143  
  2         4  
  2         1309  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
174              
175 0           my @sql = 'show grants';
176 0 0         if ($forUser) {
177 0           push @sql, "for";
178 0           push @sql, "'$forUser'";
179 0 0         push @sql, sprintf( "%s'%s'", '@', $forHost ) if $forHost;
180             }
181              
182 0           my $dbh = $self->getDbh;
183 0           my $sql = join( ' ', @sql );
184 0           $self->Logger->verbose($sql);
185 0           my $aref = $dbh->selectall_arrayref($sql);
186              
187 0           return @$aref;
188             }
189              
190 2 0   2   2265 method getDatabases () {
  2 0   0   3  
  2         320  
  0            
  0            
  0            
191              
192 0           my $dbh = $self->getDbh;
193 0           my $sql = "show databases";
194 0           $self->Logger->verbose($sql);
195 0           my $aref = $dbh->selectall_arrayref($sql);
196              
197 0           return @$aref;
198             }
199              
200             method userExists (Str :$userName!,
201 2 0 0 2   6155 Str :$host!) {
  2 0 0 2   14  
  2 0   2   207  
  2 0   2   15  
  2 0   0   4  
  2 0       106  
  2 0       13  
  2         4  
  2         9  
  2         160  
  2         5  
  2         1220  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
202 0           my $sql = q{
203             select
204             *
205             from
206             user
207             where
208             user = ? and
209             host = ?
210             };
211              
212 0           my $aref =
213             $self->getDbh->selectrow_arrayref( $sql, undef, $userName, $host );
214              
215 0 0         if ($aref) {
216 0           $self->Logger->verbose("user exists");
217 0           return 1;
218             }
219              
220 0           return 0;
221             }
222              
223             method grantPrivileges (Str :$userName!,
224             ArrayRef[Str] :$hosts = [DEFAULT_HOST],
225             ArrayRef[Str] :$privileges!,
226             Str :$dbName = '*',
227 2 0 0 2   15850 Str :$tables = '*') {
  2 0 0 2   5  
  2 0   2   204  
  2 0   2   15  
  2 0   0   11  
  2 0       93  
  2 0       12  
  2 0       27  
  2 0       11  
  2 0       149  
  2         6  
  2         1541  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
228              
229 0           foreach my $host (@$hosts) {
230              
231 0           my @sql = ('grant');
232 0           push @sql, join( ', ', @$privileges );
233 0           push @sql, 'on';
234 0           push @sql, sprintf( '%s.%s', $dbName, $tables );
235 0           push @sql, 'to';
236 0           push @sql, sprintf( q{'%s'@'%s'}, $userName, $host );
237              
238 0           $self->doSql( sql => join( ' ', @sql ) );
239             }
240              
241 0           $self->flushPrivileges;
242             }
243              
244             method revokePrivileges (Str :$userName!,
245             ArrayRef[Str] :$hosts = [DEFAULT_HOST],
246             ArrayRef[Str] :$privileges!,
247             Str :$dbName = '*',
248 2 0 0 2   15961 Str :$tables = '*') {
  2 0 0 2   5  
  2 0   2   219  
  2 0   2   15  
  2 0   0   3  
  2 0       94  
  2 0       12  
  2 0       4  
  2 0       8  
  2 0       149  
  2         4  
  2         1538  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
249              
250 0           foreach my $host (@$hosts) {
251              
252 0           my @sql = ('revoke');
253 0           push @sql, join( ', ', @$privileges );
254 0           push @sql, 'on';
255 0           push @sql, sprintf( '%s.%s', $dbName, $tables );
256 0           push @sql, 'from';
257 0           push @sql, sprintf( q{'%s'@'%s'}, $userName, $host );
258              
259 0           $self->doSql( sql => join( ' ', @sql ) );
260             }
261              
262 0           $self->flushPrivileges;
263             }
264              
265             method createUser (Str :$userName!,
266             Str :$userPass!,
267 2 0 0 2   9806 ArrayRef[Str] :$hosts = []) {
  2 0 0 2   14  
  2 0   2   229  
  2 0   2   24  
  2 0   0   4  
  2 0       90  
  2 0       12  
  2 0       5  
  2         9  
  2         160  
  2         5  
  2         1343  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
268              
269 0           foreach my $host (@$hosts) {
270 0 0         if ( !$self->userExists( userName => $userName, host => $host ) ) {
271 0           my $sql = sprintf "create user '%s'\@'%s' identified by '%s'",
272             $userName,
273             $host, $userPass;
274              
275 0           $self->doSql( sql => $sql, );
276             }
277             }
278              
279 0           $self->flushPrivileges;
280             }
281              
282 2 0   2   2280 method getMysqlCli {
  2     0   4  
  2         351  
  0            
  0            
283              
284 0           my @cmd = ('mysql');
285 0           push @cmd, '-u', $self->user;
286 0           push @cmd, sprintf '--password="%s"', $self->pass; # is there a better way?
287 0           push @cmd, '-h', $self->host;
288 0           push @cmd, '-P', $self->port;
289 0           push @cmd, '-D', $self->dbName;
290              
291 0           return join( ' ', @cmd );
292             }
293              
294 2 0   2   2463 method printMysqlCli {
  2     0   4  
  2         194  
  0            
  0            
295              
296 0           say $self->getMysqlCli;
297             }
298              
299             method doSql (Str :$sql!,
300 2 0 0 2   6704 ArrayRef :$bind = []) {
  2 0 0 2   4  
  2 0   2   261  
  2 0   2   14  
  2 0   0   5  
  2 0       91  
  2         13  
  2         4  
  2         16  
  2         187  
  2         4  
  2         1149  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
301              
302 0           my $dbh = $self->getDbh;
303              
304 0           $sql = $self->String->trim($sql);
305              
306 0           $self->Logger->debug( sprintf 'bind vars: (%s)', join( ', ', @$bind ) );
307 0           $self->Logger->verbose($sql);
308              
309 0 0         if ( !$self->dryRun ) {
310 0           $dbh->do( $sql, undef, @$bind );
311             }
312             }
313              
314 2 0   2   2365 method flushPrivileges {
  2     0   5  
  2         171  
  0            
  0            
315              
316 0           $self->doSql( sql => "flush privileges" );
317             }
318              
319 2 0   2   2265 method getMysqlUtil {
  2     0   6  
  2         171  
  0            
  0            
320              
321 0           return $self->_util;
322             }
323              
324 2 0   2   2325 method getDbh {
  2     0   5  
  2         197  
  0            
  0            
325              
326 0           return $self->_dbh;
327             }
328              
329             ##################################################################
330              
331 2 0   2   2284 method _buildUser {
  2     0   4  
  2         351  
  0            
  0            
332              
333 0 0         return $ENV{MYSQL_USER} if $ENV{MYSQL_USER};
334 0 0         return $ENV{DBI_USER} if $ENV{DBI_USER};
335 0 0         return $ENV{USER} if $ENV{USER};
336 0           return DEFAULT_USER;
337             }
338              
339 2 0   2   2250 method _buildPass {
  2     0   4  
  2         301  
  0            
  0            
340              
341 0 0         return $ENV{MYSQL_PASS} if $ENV{MYSQL_PASS};
342 0 0         return $ENV{MYSQL_PWD} if $ENV{MYSQL_PWD};
343 0           confess "unable to derive a password";
344             }
345              
346 2 0   2   2295 method _buildHost {
  2     0   5  
  2         249  
  0            
  0            
347              
348 0 0         return $ENV{MYSQL_HOST} if $ENV{MYSQL_HOST};
349 0           return DEFAULT_HOST;
350             }
351              
352 2 0   2   2348 method _buildPort {
  2     0   6  
  2         295  
  0            
  0            
353              
354 0 0         return $ENV{MYSQL_PORT} if $ENV{MYSQL_PORT};
355 0 0         return $ENV{MYSQL_TCP_PORT} if $ENV{MYSQL_TCP_PORT};
356 0           return DEFAULT_PORT;
357             }
358              
359 2 0   2   2257 method _buildDbName {
  2     0   4  
  2         290  
  0            
  0            
360              
361 0 0         return $ENV{MYSQL_DBNAME} if $ENV{MYSQL_DBNAME};
362 0 0         return $ENV{MYSQL_SCHEMA} if $ENV{MYSQL_SCHEMA};
363 0           return DEFAULT_DBNAME;
364             }
365              
366 2 0   2   2335 method _getNewDbh {
  2     0   4  
  2         475  
  0            
  0            
367              
368 0           my @dsn = sprintf 'dbi:mysql:host=%s', $self->host;
369 0           push @dsn, sprintf 'database=%s', $self->dbName;
370 0           push @dsn, sprintf 'port=%s', $self->port;
371 0           my $dsn = join ';', @dsn;
372              
373 0           my $dbh = DBI->connect(
374             $dsn,
375             $self->user,
376             $self->pass,
377             {
378             RaiseError => $self->raiseError,
379             PrintError => $self->printError,
380             }
381             );
382              
383 0           $self->Logger->verbose( "connected to $dsn as " . $self->user );
384              
385 0           return $dbh;
386             }
387              
388 2 0   2   2271 method _buildDbh {
  2     0   5  
  2         235  
  0            
  0            
389              
390 0           my $dbh = $self->_getNewDbh;
391 0           $dbh->{FetchHashKeyName} = $self->fetchHashKeyName;
392              
393 0           return $dbh;
394             }
395              
396 2 0   2   2218 method _buildUtil {
  2     0   5  
  2         281  
  0            
  0            
397              
398 0           return MySQL::Util->new( dbh => $self->_getNewDbh );
399             }
400              
401             1;