#!/usr/bin/perl -w use warnings; use strict; my @data = ( # Host User DB Permissions [ "localhost", "jma_dbo", "*", "USAGE, SELECT, INSERT, SHOW VIEW" ], [ "localhost", "jma_ro", "*", "USAGE, SELECT" ], [ "localhost", "jma_ro", "jma", "SHOW VIEW" ], [ "localhost", "jma_ro", "uat", "SELECT, INSERT" ], [ "localhost", "jma_rw", "jma", "USAGE, SELECT, INSERT, SHOW VIEW" ], [ "prod", "robo", "*", "SELECT, SHOW VIEW" ], [ "prod", "robo", "jma", "USAGE" ], ); . . . your attempt to solve the problem . . . #### host user DB usage select insert show view ... --------- ------- --- ----- ------ ------ --------- ... localhost jma_dbo jma ** ** ** ** localhost jma_ro jma ** ** Y localhost jma_ro uat ** Y* Y localhost jma_rw jma Y Y Y Y prod robo jma Y ** ** . . . #### #!/usr/bin/perl -w use warnings; use strict; my @data = ( ... same as above ... ); # First scan the data to find out what rows are needed, and the permissions # columns needed my %report; # {HOST}{USER}{DB} my %DBs; # {HOST}{DB} # (see tricky bit below) my %perms; my $next_column=0; for my $row (@data) { my ($host, $uid, $db, $tmp) = @$row; # Convert permissions string to array of permissions $tmp = [ split /,\s*/, $tmp ]; # Ensure we have a column for each permission for my $p (@$tmp) { next if exists $perms{$p}; $perms{$p} = $next_column++; } $report{$host}{$uid}{$db} = $tmp; # Track each database we see $DBs{$host}{$db}=0; } my $max_perm = scalar(keys %perms) - 1; # Tricky bit: We want to include rows for databases the user has access to # (the USAGE permission) even when they have no database-specific entries. # So we'll find all host/user combinations with a '*' database having a # 'USAGE' permission, and make sure that we have a hash entry with a blank # list of permissions. To simplify this, we built the DBs hash in the previous # step to hold a list of all databases we have on each server for my $host (keys %report) { my @dbs_to_add; for my $user (keys %{$report{$host}}) { next unless exists $report{$host}{$user}{'*'}; next unless grep { $_ eq 'USAGE' } values $report{$host}{$user}{'*'}; # OK, we have HOST/USER entry where the user has access to all databases # on the server, so add a blank permissions list for all servers not # already on the list for my $DB (keys %{$DBs{$host}}) { next if exists $report{$host}{$user}{$DB}; $report{$host}{$user}{$DB} = [ ]; } } } # Now we can transform the permissions lists for each row into the symbols we # want to show in the report for my $host (keys %report) { for my $user (keys %{$report{$host}}) { # First set symbol to '' or 'Y' for my $DB (keys %{$report{$host}{$user}}) { next if $DB eq '*'; my @symbol = ('') x $max_perm; # default values $symbol[$perms{$_}] = 'Y' for @{$report{$host}{$user}{$DB}}; $report{$host}{$user}{$DB} = [ @symbol ]; } # Now add '*' for all default permissions next unless exists $report{$host}{$user}{'*'}; my @defaults = @{$report{$host}{$user}{'*'}}; for my $DB (keys %{$report{$host}{$user}}) { next if $DB eq '*'; $report{$host}{$user}{$DB}[$perms{$_}] .= '**' for @defaults; } } } # Print the report # Header print "server user ID DB "; printf "% 2u ", $_+1 for 0 .. $max_perm; print "\n"; print "---------- -------- --- "; print "-- " for 0 .. $max_perm; print "\n"; # Data for my $host (sort keys %report) { for my $user (sort keys %{$report{$host}}) { for my $DB (sort keys %{$report{$host}{$user}}) { next if $DB eq '*'; printf "%-10.10s %-8.8s %-3.3s: ", $host, $user, $DB; printf "%-2.2s ", $_ for @{$report{$host}{$user}{$DB}}; print "\n"; } } } print "\nColumns:\n"; for my $perm (sort { $perms{$a} <=> $perms{$b} } keys %perms) { printf "% 2u: %s\n", $perms{$perm} + 1, $perm; }