-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdbgrep
More file actions
executable file
·138 lines (122 loc) · 3.24 KB
/
dbgrep
File metadata and controls
executable file
·138 lines (122 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/perl -w
use strict;
use DBI;
my $sep = ","; # seperates fields
my $nsep = '_'; # Replacement in display
main(@ARGV);
############################
# We basically pretend a database is a directory tree,
# and match all components to the user's search string.
#
# table:tuple
#
# tuples are displayed as seperated by $sep, and consequently searches
# with $sep in it will "look funny"
# I would like to have fieldnames too, but there's no nice way to
# get that programmatically from empty tables, and including it
# would muddy the model..
############################
sub main
{
my %args = handle_args(@_);
($args{dbc}, $args{user}, $args{pass}) = cleanup_dbstring($args{dbstring});
my $dbh = DBI->connect($args{dbc}, $args{user}, $args{pass});
if(! $dbh->ping()) {die "Not connected: $!\n";}
my @tables = db_get_tables($dbh); # depreciated - hopefully still works
foreach my $table (@tables)
{
# print "I see $table\n\n\n";
if($table =~ /$args{search}/)
{print "$table/\n";}
my $dbq = $dbh->prepare("SELECT * FROM $table");
$dbq->execute();
while(my %tuple = get_dbresults($dbq))
{
if(grep { $tuple{$_} && $tuple{$_} =~ /$args{search}/ } keys %tuple)
{
print "$table:"
. join($sep,
map
{
if($tuple{$_})
{
$tuple{$_} =~ s/$sep/$nsep/g;
$tuple{$_} =~ s/[\r\f\n]/\\n/g;
$tuple{$_};
}
else {''}
}
keys %tuple) . "\n";
}
}
}
$dbh->disconnect();
}
sub handle_args
{
my @in = @_;
my %ret;
if(@in < 2)
{
die <<EOUSAGE;
Usage: dbgrep STRING DBSTRING
DBSTRING is one of the following:
[user:pass]\@dbi:DBISTRING
dbi:DBISTRING (assumes no username/password)
[user:pass]\@dbname (assumes PostgreSQL)
dbname (assumes PostgreSQL and no username/password required)
brackets and colons in usernames/database names/etc are not supported.
EOUSAGE
}
$ret{search} = $in[0];
$ret{dbstring} = $in[1];
return %ret;
}
sub cleanup_dbstring
{ # Although the user can pass in a full DBI string with
# username/password glued on, let's try not to make them do so...
my ($instring) = @_;
my $cstring;
my $cuser;
my $cpass;
if($instring =~ s/^\[([^]]+)\]\@//) # Remove user/pass string if present
{ # and parse it
my $authpart = $1;
($cuser,$cpass) = split(/:/, $authpart);
}
if($instring !~ /^dbi:/) # Without this, we assume it's just a Pg dbname
{
$cstring = "dbi:Pg:dbname=$instring";
}
else
{$cstring = $instring;} # Nice and simple
return ($cstring, $cuser, $cpass);
}
sub db_get_tables
{ # Right now, we know how to filter out postgres system stuff. Extend this to other dbs when possible
my ($dbh) = @_;
my @ret;
my $sth = $dbh->table_info(undef, undef, undef, "'TABLE'");
while(my %res = get_dbresults($sth))
{
next if($res{TABLE_TYPE} ne 'TABLE');
next if($res{pg_schema} eq 'information_schema');
next if($res{TABLE_SCHEM} eq 'information_schema');
push(@ret, $res{TABLE_NAME});
# print join('', map {"$_ -> $res{$_}\n"} keys %res) . "\n";
}
return @ret;
}
#################################
# Cut/paste from elsewhere
sub get_dbresults($)
{ # Returns a proper hash instead of a reference to one, for FIRST record returned
my ($dbq) = @_;
my $reshdl = $dbq->fetchrow_hashref();
my %returner;
if(defined($reshdl))
{
%returner = %$reshdl;
}
return %returner;
}