Your main point of confusion seems to be in the inner loop. (Well, that and your lack of 'use strict'!) You are looking for inactive records, and doing something confusing with each occurence of those records. If I understand your problem description correctly, you should instead search for *active* records, and if you see *any*, then it does not matter how many there are - it means that the user is active, so just skip that user.
Here is that loop, recast but not tested (because I don't have 'db-common.sub'):
USER: while ( $pointer = $sth->fetchrow_hashref ) { $username = $pointer->{'username'}; # Connect to jobs DB and get the entries that match the username # XXX Changed from != to =, and selecting only the count. $SQL2 = "SELECT count(*) FROM $jobstable" . " where username = '$username' and active = 'yes'"; &Do_SQL2; $pointer2 = $sth2->fetchrow_hashref; if ( $pointer2->{'count(*)'} > 0 ) { print "Skipping active user '$username'\n"; next USER; } $userdirectory = $rootpath . $username; print "Directory '$userdirectory' to be deleted\n"; File::Path::rmtree( $userdirectory ); }
Because the amount of data is relatively small, if I was writing this from scratch, I would approach the problem quite differently.
The code below makes 2 DB calls instead of 30,000+ calls, and (with the *highly* recommended SQLite and DBD::SQLite) is fully testable on your desktop PC.
Working, tested code:
#!/usr/bin/perl use strict; use warnings; use DBI; use File::Path; my $really_delete_the_directories = 1; #require 'db-common.sub' or die "Error loading db-common.sub"; #my $rootpath = '/usr/www/users/me/reg/'; my $rootpath = './'; die if not -d $rootpath; my $regtype = 'ch'; my $yeartodelete = '2002'; my $dbh; #&Conn_to_DB; # Something to initialize $dbh, I hope! TEST_STUFF: { my $sqlite_db_name = 'pm_666415.db'; unlink $sqlite_db_name or die if -e $sqlite_db_name; $dbh = DBI->connect("dbi:SQLite:dbname=$sqlite_db_name") or die; # Create data just for testing. my @db_setup = grep { /\S/ } split /(?:#.+)?\n/, <<'END_OF_SQL'; CREATE TABLE registrations ( username CHAR(10), regtype CHAR(2), datea +dded CHAR(8) ); INSERT INTO registrations VALUES( 'Able' , 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Baker' , 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Charlie', 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Roger' , 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Fox' , 'zz', '20020101' ); # Wr +ong regtype INSERT INTO registrations VALUES( 'Dog' , 'ch', '20030101' ); # No +t in date range CREATE TABLE joblistings ( username CHAR(10), active CHAR(3) ); INSERT INTO joblistings VALUES( 'Able' , 'yes' ); # Has both yes INSERT INTO joblistings VALUES( 'Able' , 'no' ); # and no INSERT INTO joblistings VALUES( 'Baker' , 'yes' ); INSERT INTO joblistings VALUES( 'Charlie', 'no' ); INSERT INTO joblistings VALUES( 'Roger' , 'no' ); INSERT INTO joblistings VALUES( 'Fox' , 'yes' ); INSERT INTO joblistings VALUES( 'Dog' , 'no' ); END_OF_SQL # I expect Charlie and Roger to be removed. $dbh->do($_) or die for @db_setup; mkdir $_ for qw( Able Baker Charlie Roger Fox Dog ); } my $sql1 = <<'END_OF_SQL'; SELECT username FROM registrations WHERE regtype = ? AND dateadded LIKE ? END_OF_SQL my @parms1 = ( $regtype, '%'.$yeartodelete.'%' ); my $jobstable = ( $regtype eq 'ch' ) ? 'joblistings' : 'jobswanted'; my $sql2 = <<"END_OF_SQL"; SELECT username FROM $jobstable WHERE active = 'yes' GROUP BY username END_OF_SQL # All data will fit into memory, so slurp in: # 1) an array of all the usernames that were # registered in some past year, and # 2) an array of all the users considered "active". my @registered_users = get_all_of_a_single_column( $dbh, $sql1, @parms +1 ); my @active_users = get_all_of_a_single_column( $dbh, $sql2 ); $dbh->disconnect; # make a lookup table of the actives my %active_user = map { $_ => 1 } @active_users; #use Data::Dumper; #print Dumper \@registered_users, \@active_users; # Only consider inactive users my @users_to_remove = grep { not $active_user{$_} } @registered_users; # Generate a list of those users directories. my @user_dirs_to_remove = map { $rootpath . $_ } @users_to_remove; # Any dirs already deleted, we remove from the list. @user_dirs_to_remove = grep { -d $_ } @user_dirs_to_remove; print "Going to remove directories:\n ", join("\n ", @user_dirs_to_remove), "\n"; if ($really_delete_the_directories) { File::Path::rmtree( \@user_dirs_to_remove, { verbose => 1 } ); } sub get_all_of_a_single_column { my ( $dbh, $sql, @params ) = @_; my $all_rows_aref = $dbh->selectall_arrayref( $sql, undef, @params ) or die; # Return a list of the first column of each row. return map { $_->[0] } @{ $all_rows_aref }; }
In reply to Re: Need help with loops and 3 tables
by Util
in thread Need help with loops and 3 tables
by htmanning
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |