line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Fry::Lib::CDBI::Basic; |
2
|
1
|
|
|
1
|
|
1780
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1519
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
our $VERSION='0.15'; |
5
|
|
|
|
|
|
|
my $sql_count; |
6
|
|
|
|
|
|
|
#our $cdbi_search = "search_abstract"; |
7
|
|
|
|
|
|
|
#other possible values are cdbi_search,cdbi_regex and cdbi_search_like |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
#functions |
10
|
|
|
|
|
|
|
sub _default_data { |
11
|
0
|
|
|
0
|
|
|
my $class = shift; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
return { |
14
|
0
|
|
|
|
|
|
depend=>[':CDBI::Load'], |
15
|
|
|
|
|
|
|
vars=>{ |
16
|
|
|
|
|
|
|
editor=>$ENV{EDITOR}, |
17
|
|
|
|
|
|
|
splitter=>'=', |
18
|
|
|
|
|
|
|
insert_columns=>'', |
19
|
|
|
|
|
|
|
abstract_opts=>{logic=>'and'}, |
20
|
|
|
|
|
|
|
insert_delimiter=>',,', |
21
|
|
|
|
|
|
|
cdbi_search=>'search_abstract', |
22
|
|
|
|
|
|
|
#flags |
23
|
|
|
|
|
|
|
safe_update=>1, |
24
|
|
|
|
|
|
|
only_modified=>1, |
25
|
|
|
|
|
|
|
}, |
26
|
|
|
|
|
|
|
subs=>{parseHash=>{qw/a h/},parseHashref=>{qw/a hr/}, |
27
|
|
|
|
|
|
|
printTextTable=>{qw/a tt/} |
28
|
|
|
|
|
|
|
#search=>{sub=>'search'},search_like=>{} |
29
|
|
|
|
|
|
|
}, |
30
|
|
|
|
|
|
|
cmds=>{ |
31
|
|
|
|
|
|
|
print_columns=>{a=>'pc',d=>'Prints columns of current table',u=>''}, |
32
|
|
|
|
|
|
|
search_abstract=>{a=>'s',aa=>\&aliasInputAndSql, |
33
|
|
|
|
|
|
|
d=>'Search for results via AbstractSearch' |
34
|
|
|
|
|
|
|
,u=>'@search_term'}, |
35
|
|
|
|
|
|
|
cdbi_search=>{a=>'sn',aa=>\&aliasInputAndSql,u=>'@search_term'}, |
36
|
|
|
|
|
|
|
cdbi_search_like=>{a=>'sl',aa=>\&aliasInputAndSql,u=>'@search_term'}, |
37
|
|
|
|
|
|
|
cdbi_search_regex=>{a=>'sr',aa=>\&aliasInputAndSql,u=>'@search_term'}, |
38
|
|
|
|
|
|
|
cdbi_delete=>{a=>'d',aa=>\&aliasInputAndSql, |
39
|
|
|
|
|
|
|
d=>'Deletes results of given query',u=>'@search_term'}, |
40
|
|
|
|
|
|
|
cdbi_create=>{a=>'i',aa=>\&aliasInsert, d=>"Creates a record", |
41
|
|
|
|
|
|
|
u=>'($value$delim)+'}, |
42
|
|
|
|
|
|
|
cdbi_find_or_create=>{a=>'fc',aa=>\&aliasInputAndSql, d=>"Find or create a record", |
43
|
|
|
|
|
|
|
u=>'@search_term'}, |
44
|
|
|
|
|
|
|
cdbi_multi_insert=>{a=>'mi',arg=>'$file',u=>'$file'}, |
45
|
|
|
|
|
|
|
cdbi_update=>{a=>'U',aa=>\&aliasInputAndSql, d=>'Updates records via a text editor', |
46
|
|
|
|
|
|
|
u=>'@search_term'}, |
47
|
|
|
|
|
|
|
replace=>{d=>'evals each value of each result row with $operation', a=>'r', |
48
|
|
|
|
|
|
|
u=>'@search_term$operation'}, |
49
|
|
|
|
|
|
|
cdbi_delete_obj=>{a=>':d',u=>'@cdbi'}, |
50
|
|
|
|
|
|
|
cdbi_update_obj=>{a=>':U',u=>'@cdbi'}, |
51
|
|
|
|
|
|
|
verify_no_delim=>{a=>'V',aa=>\&aliasInputAndSql, u=>'@cdbi', |
52
|
|
|
|
|
|
|
d=>"Verify that specified records don't have display delimiter in them"}, |
53
|
|
|
|
|
|
|
display_table_list=>{qw/a dpt/, d=>'Displays public tables',u=>''}, |
54
|
|
|
|
|
|
|
print_dbi_log=>{a=>'dpl',d=>'Prints the current DBI log',u=>''}, |
55
|
|
|
|
|
|
|
clear_dbi_log=>{d=>'Clears the dbi log',u=>'',a=>'dcl',u=>''}, |
56
|
|
|
|
|
|
|
set_dbi_log_level=>{a=>'dsl',d=>'Sets the log level of a DBI handler', |
57
|
|
|
|
|
|
|
u=>'$num'}, |
58
|
|
|
|
|
|
|
}, |
59
|
|
|
|
|
|
|
opts=>{cdbi_search=>{qw/a cs type var noreset 1 default cdbi_search_regex/ }} |
60
|
|
|
|
|
|
|
#retrieve_all retrieve/], |
61
|
|
|
|
|
|
|
#construct,has*,trigger,constrain_column,set_sql |
62
|
|
|
|
|
|
|
#} |
63
|
|
|
|
|
|
|
#subs=>{aliasInputAndSql=>{}}, |
64
|
|
|
|
|
|
|
#td: obj-$result(autoupdate,update,delete,set/get,copy,discard_changes,is_changed),$iterator,$col,$relation |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
sub _initLib { |
68
|
0
|
|
|
0
|
|
|
my $cls = shift; |
69
|
0
|
|
|
|
|
|
$cls->_set_insert_col; |
70
|
0
|
|
|
|
|
|
$cls->Var('abstract_opts')->{cmp} = $cls->_regex_operator; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
#ugly, should be in _default_data |
73
|
0
|
|
|
|
|
|
$cls->call(var=>'set','cdbi_search',enum=>[qw/cdbi_search cdbi_search_like cdbi_search_regex search_abstract/]); |
74
|
0
|
|
|
|
|
|
$cls->call(var=>'set','cdbi_search',default=>'cdbi_search_regex'); |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
#note for library use outside of shell |
77
|
|
|
|
|
|
|
#this module depends on external subs: &parse_num |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
##utils |
80
|
|
|
|
|
|
|
sub uniqueInArrays { |
81
|
0
|
|
|
0
|
|
|
my ($cls,$uniq,$array2) =@_; |
82
|
0
|
|
|
|
|
|
my (@unique,%seen,$i,@num); |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
for (@$array2) {$seen{$_}++} |
|
0
|
|
|
|
|
|
|
85
|
0
|
0
|
|
|
|
|
for (@$uniq) { $i++; do {push(@unique,$_);push(@num,$i) } if (! exists $seen{$_}) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
return (\@unique,\@num); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
sub file2array { |
89
|
0
|
|
|
0
|
|
|
shift; |
90
|
|
|
|
|
|
|
#local function |
91
|
|
|
|
|
|
|
#d:converts file to @ of lines |
92
|
0
|
|
|
|
|
|
open(FILE,"< $_[0]"); |
93
|
0
|
|
|
|
|
|
my @lines; chomp(@lines = ); |
|
0
|
|
|
|
|
|
|
94
|
0
|
|
|
|
|
|
close FILE; |
95
|
0
|
|
|
|
|
|
return @lines; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
sub check_for_regex { |
98
|
|
|
|
|
|
|
#d: AoHregexp, could be used as an 'or' search on multiple columns |
99
|
0
|
|
|
0
|
|
|
my ($class,$regex,@records) = @_; |
100
|
0
|
|
|
|
|
|
my @unclean; |
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
for (@records) { |
103
|
0
|
|
|
|
|
|
for my $col (@{$class->Var('action_columns')}) { |
|
0
|
|
|
|
|
|
|
104
|
0
|
0
|
|
|
|
|
if ($_->$col =~ /$regex/) { |
105
|
0
|
|
|
|
|
|
push(@unclean,$_); |
106
|
0
|
|
|
|
|
|
last; #break? |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
} |
110
|
0
|
|
|
|
|
|
return @unclean; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
#internal methods |
113
|
|
|
|
|
|
|
sub _set_insert_col { |
114
|
0
|
|
|
0
|
|
|
my $cls = shift; |
115
|
|
|
|
|
|
|
#set insert_columns |
116
|
0
|
|
|
|
|
|
my @insert_columns = @{$cls->Var('columns')}; |
|
0
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
|
shift @insert_columns; |
118
|
0
|
|
|
|
|
|
$cls->setVar(insert_columns=>\@insert_columns); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
sub regexChangeAoH { |
122
|
0
|
|
|
0
|
|
|
my ($cls,$op,@records2update) = @_; |
123
|
0
|
|
|
|
|
|
for my $rec (@records2update) { |
124
|
0
|
|
|
|
|
|
for (my $j=0; $j < @{$cls->Var('action_columns')}; $j++) { |
|
0
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
my $col= $cls->Var('action_columns')->[$j]; |
126
|
0
|
|
|
|
|
|
$_ = $rec->$col; |
127
|
0
|
0
|
|
|
|
|
eval $op; die($@) if $@; |
|
0
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
|
$rec->$col($_); |
129
|
|
|
|
|
|
|
} |
130
|
0
|
|
|
|
|
|
$rec->update; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
sub modify_file { |
134
|
0
|
|
|
0
|
|
|
my ($cls,$tempfile) = @_; |
135
|
0
|
|
|
|
|
|
my $inp; |
136
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
system($cls->Var('editor') . " $tempfile");# or die "can't execute command as $<: $@"; |
138
|
|
|
|
|
|
|
#?: why does this system always return a fail code |
139
|
|
|
|
|
|
|
#$cls->view("cdbi_update (y/n)? "); chomp($inp = ); |
140
|
0
|
|
|
|
|
|
$inp = $cls->Rline->stdin("cdbi_update (y/n)?"); |
141
|
0
|
|
|
|
|
|
return ($inp eq "y"); |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
sub update_from_file { |
144
|
0
|
|
|
0
|
|
|
my ($cls,$tempfile,@records) = @_; |
145
|
|
|
|
|
|
|
|
146
|
0
|
|
|
|
|
|
my @lines = $cls->file2array($tempfile); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
#my $firstline = shift(@lines); |
149
|
|
|
|
|
|
|
#read column order from file |
150
|
|
|
|
|
|
|
#my @fields = split(/$updatedelim/,$firstline); |
151
|
|
|
|
|
|
|
#or not |
152
|
0
|
|
|
|
|
|
my @fields = @{$cls->Var('action_columns')}; |
|
0
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
my $i; |
155
|
0
|
|
|
|
|
|
foreach (@records) { #each row to update |
156
|
0
|
|
|
|
|
|
my @fvalues = split(/${\$cls->Var('field_delimiter')}/,$lines[$i]); |
|
0
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
for (my $j=0; $j < @fields; $j++) { #each column to update |
158
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
my $temp=$fields[$j]; |
160
|
0
|
|
|
|
|
|
$_->$temp($fvalues[$j]); # this line = $_->$field($fieldvalue) |
161
|
|
|
|
|
|
|
} |
162
|
0
|
|
|
|
|
|
$_->update; |
163
|
|
|
|
|
|
|
#$_->dbi_commit if ($db = postgres |
164
|
0
|
|
|
|
|
|
$i++; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
sub col2f1 { |
168
|
|
|
|
|
|
|
#d: aliases column names with c and number |
169
|
0
|
|
|
0
|
|
|
my $class = shift; |
170
|
0
|
|
|
|
|
|
my @newterms; |
171
|
|
|
|
|
|
|
|
172
|
0
|
|
|
|
|
|
for (@_) { |
173
|
|
|
|
|
|
|
#if (/c(\d+)=/) { my $col = $col[$1-1];s/c\d+/$col/} |
174
|
0
|
0
|
|
|
|
|
if (/c([-,\d]+)(.*)/) { |
|
0
|
|
|
|
|
|
|
175
|
0
|
|
|
|
|
|
my @tempcol = $class->sub->parseNum($1,@{$class->Var('columns')}); |
|
0
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
for my $eachcol (@tempcol) { |
177
|
0
|
|
|
|
|
|
push(@newterms,$eachcol.$2); |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
else {push (@newterms,$_)} |
181
|
|
|
|
|
|
|
} |
182
|
0
|
|
|
|
|
|
return @newterms; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
#sub objects |
185
|
|
|
|
|
|
|
##print functions,input is objects |
186
|
|
|
|
|
|
|
sub printtofile { |
187
|
|
|
|
|
|
|
#d:prints rows to temporary file |
188
|
0
|
|
|
0
|
|
|
my ($cls,$tempfile,@records) = @_; |
189
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
|
my $output = join($cls->Var('field_delimiter'),@{$cls->Var('action_columns')})."\n"; |
|
0
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
$output .= $cls->View->objAoH_dt(\@records,$cls->Var('action_columns')); |
192
|
0
|
|
|
|
|
|
$cls->View->file($tempfile,$output); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
sub printTextTable { |
195
|
0
|
|
|
0
|
|
|
my $cls = shift; |
196
|
0
|
|
|
|
|
|
$cls->print_text_table(\@_,$cls->Var('action_columns')); |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
sub print_text_table { |
199
|
|
|
|
|
|
|
my $cls = shift; |
200
|
|
|
|
|
|
|
my ($ref1,$ref2) = @_; my @row = @{$ref1}; my @columns = @{$ref2}; |
201
|
|
|
|
|
|
|
my (@column_values,@longest); |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
#defaul |
204
|
1
|
|
|
1
|
|
387
|
eval { use Text::Reform}; die $@ if ($@); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
for my $column (@columns) { |
207
|
|
|
|
|
|
|
my @column_value; |
208
|
|
|
|
|
|
|
my $longest = length($column); |
209
|
|
|
|
|
|
|
for (@row) { |
210
|
|
|
|
|
|
|
#find longest string in each column including string |
211
|
|
|
|
|
|
|
my $newlength = length($_->$column); |
212
|
|
|
|
|
|
|
$longest = $newlength if ($newlength > $longest); |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
push(@column_value,$_->$column); |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
push(@longest,$longest); |
217
|
|
|
|
|
|
|
push(@column_values,\@column_value); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
#create format |
221
|
|
|
|
|
|
|
my $line_length = 3 * @columns + 1; |
222
|
|
|
|
|
|
|
my $picture_line = "|"; |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
for (@longest) { |
225
|
|
|
|
|
|
|
$line_length += $_ ; |
226
|
|
|
|
|
|
|
$picture_line .= " " . "["x $_ . " |"; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
my $firstline = "=" x $line_length; |
229
|
|
|
|
|
|
|
#$picture_line .= "\n" . "-" x $line_length; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
#print column names |
232
|
|
|
|
|
|
|
$cls->view(form $picture_line,@columns); |
233
|
|
|
|
|
|
|
#print body |
234
|
|
|
|
|
|
|
$cls->view(form $firstline,$picture_line, @column_values); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
sub print_horizontal_numbered_list { |
237
|
|
|
|
|
|
|
my ($cls,$prompt,$list) = @_; |
238
|
|
|
|
|
|
|
my $a; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
my $output = $prompt; |
241
|
|
|
|
|
|
|
for (@$list){$a++;$output .= "$a.$_ " }; |
242
|
|
|
|
|
|
|
$output .= "\n"; |
243
|
|
|
|
|
|
|
$cls->view($output); |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
##alias fns |
246
|
|
|
|
|
|
|
sub cdbiDbh { shift->Var('table_class')->db_Main } |
247
|
|
|
|
|
|
|
sub aliasInputAndSql { my $cls = shift; |
248
|
|
|
|
|
|
|
return $cls->aliasSqlAbstract($cls->aliasInput(@_)) } |
249
|
|
|
|
|
|
|
sub aliasInput { |
250
|
|
|
|
|
|
|
my $class = shift; |
251
|
|
|
|
|
|
|
@_ = $class->Var('columns')->[0].$class->Var('splitter').".*" if ($_[0] eq "a"); #all results given |
252
|
|
|
|
|
|
|
@_ = $class->col2f1(@_) if ("@_" =~ /c[-,\d]+=/); #c\d instead of column name |
253
|
|
|
|
|
|
|
return @_; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
sub aliasInsert { |
256
|
|
|
|
|
|
|
#d:parses userinput to hashref for &create |
257
|
|
|
|
|
|
|
my $cls = shift; |
258
|
|
|
|
|
|
|
my %chosenf; |
259
|
|
|
|
|
|
|
#die "Nothing given for cdbi_insert" if (not defined @_); |
260
|
|
|
|
|
|
|
my @fields = split(/${\$cls->Var('insert_delimiter')}/,"@_"); |
261
|
|
|
|
|
|
|
my @insert_columns = @{$cls->Var('insert_columns')}; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
for (my $i=0;$i< @insert_columns;$i++) { |
264
|
|
|
|
|
|
|
$chosenf{$insert_columns[$i]} = $fields[$i]; |
265
|
|
|
|
|
|
|
$cls->view("$insert_columns[$i] = $fields[$i]\n"); |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
return \%chosenf; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
sub aliasSqlAbstract { |
270
|
|
|
|
|
|
|
#d:parse to feed to sql::abstract |
271
|
|
|
|
|
|
|
#note: operators hardcoded for now |
272
|
|
|
|
|
|
|
my $class = shift; |
273
|
|
|
|
|
|
|
my @processf; |
274
|
|
|
|
|
|
|
my $splitter = $class->Var('splitter'); |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
foreach (@_) { |
277
|
|
|
|
|
|
|
if (/$splitter([>!<])=/) { |
278
|
|
|
|
|
|
|
my $operator = $1; |
279
|
|
|
|
|
|
|
my ($key,$value) = split(/=$operator=/); |
280
|
|
|
|
|
|
|
push(@processf,$key,{"$operator\=",$value}); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
elsif (/$splitter([><=])/) { |
283
|
|
|
|
|
|
|
my $operator = $1; |
284
|
|
|
|
|
|
|
my ($key,$value) = split (/$splitter$operator/); |
285
|
|
|
|
|
|
|
push(@processf,$key,{$operator,$value}); |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
#embedded sql |
288
|
|
|
|
|
|
|
elsif (/$splitter(.*)$splitter/) { |
289
|
|
|
|
|
|
|
my $literal_sql = $1; |
290
|
|
|
|
|
|
|
$literal_sql =~ s/_/ /g; |
291
|
|
|
|
|
|
|
my ($key,$dump) = split (/$splitter/); |
292
|
|
|
|
|
|
|
push(@processf,$key,\$literal_sql); |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
#default operator |
295
|
|
|
|
|
|
|
#elsif(/=/) |
296
|
|
|
|
|
|
|
else { |
297
|
|
|
|
|
|
|
my ($key,$value) = split(/$splitter/) or die "error splitting select"; |
298
|
|
|
|
|
|
|
push(@processf,$key,$value); |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
#else { warn "no valid operator specified" }; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
return @processf; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
##parse functions,input is from commandine |
305
|
|
|
|
|
|
|
sub parseHash { |
306
|
|
|
|
|
|
|
my ($cls,$input) = @_; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
my @arg = split(/ /,$input); |
309
|
|
|
|
|
|
|
my $cmd = shift @arg; |
310
|
|
|
|
|
|
|
my %results = $cls->parseIndHash($cls->Var('splitter'),@arg); |
311
|
|
|
|
|
|
|
return ($cmd,%results) |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
sub parseHashref { |
314
|
|
|
|
|
|
|
my ($cls,$input) = @_; |
315
|
|
|
|
|
|
|
my ($cmd,%results) = $cls->parseHash($input); |
316
|
|
|
|
|
|
|
return ($cmd,\%results); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
sub parseIndHash { |
319
|
|
|
|
|
|
|
my ($class,$splitter,@chunks) = @_; |
320
|
|
|
|
|
|
|
my %processf; |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
for (@chunks) { |
323
|
|
|
|
|
|
|
my ($key,$value) = split(/$splitter/) or die "error splitting select"; |
324
|
|
|
|
|
|
|
$processf{$key} = $value; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
return %processf; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
#commands |
329
|
|
|
|
|
|
|
sub print_columns { |
330
|
|
|
|
|
|
|
my $cls = shift; |
331
|
|
|
|
|
|
|
$cls->print_horizontal_numbered_list($cls->Var('table')."'s columns are ",$cls->Var('columns')); |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
sub search_abstract { |
334
|
|
|
|
|
|
|
#d:handles multiple parsing cases and returns search results |
335
|
|
|
|
|
|
|
my $cls = shift; |
336
|
|
|
|
|
|
|
if (@_ ==0 ) {warn("No arguments given to &search_abstract\n");return () } |
337
|
|
|
|
|
|
|
$cls->sub->_require('Class::DBI::AbstractSearch'); |
338
|
|
|
|
|
|
|
$cls->sub->useThere('Class::DBI::AbstractSearch',$cls->Var('table_class')); |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
#calling class determines class |
341
|
|
|
|
|
|
|
my @results = $cls->Var('table_class')->Class::DBI::AbstractSearch::search_where(\@_,$cls->Var('abstract_opts')); |
342
|
|
|
|
|
|
|
$cls->saveArray(@results) if ($cls->Flag('menu')); |
343
|
|
|
|
|
|
|
return @results; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
sub cdbi_search { shift->Var('table_class')->search(@_) } |
346
|
|
|
|
|
|
|
sub cdbi_search_like { shift->Var('table_class')->search_like(@_) } |
347
|
|
|
|
|
|
|
sub cdbi_search_regex { shift->Var('table_class')->search_regex(@_) } |
348
|
|
|
|
|
|
|
sub cdbi_create { shift->Var('table_class')->create(@_) } |
349
|
|
|
|
|
|
|
sub cdbi_delete { |
350
|
|
|
|
|
|
|
#td: chain |
351
|
|
|
|
|
|
|
my $cls = shift; |
352
|
|
|
|
|
|
|
my @aliasedinput = @_; |
353
|
|
|
|
|
|
|
my @results = $cls->${\$cls->Var('cdbi_search')}(@aliasedinput); |
354
|
|
|
|
|
|
|
#my @results = $cls->sub->subHook(args=>\@aliasedinput,var=>'cdbi_search',default=>'search_abstract',caller=>$cls); |
355
|
|
|
|
|
|
|
$cls->cdbi_delete_obj(@results); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
sub cdbi_find_or_create { |
358
|
|
|
|
|
|
|
my ($cls,%dt) = @_; |
359
|
|
|
|
|
|
|
#my $hash = ref $_[0] eq "HASH" ? shift: {@_}; |
360
|
|
|
|
|
|
|
my ($exists) = $cls->${\$cls->Var('cdbi_search')}(%dt); |
361
|
|
|
|
|
|
|
return defined($exists) ? $exists : $cls->Var('table_class')->create(\%dt); |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
sub cdbi_multi_insert { |
364
|
|
|
|
|
|
|
my ($cls,$file) = @_; |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
chomp(my @lines= $cls->file2array($file)); |
367
|
|
|
|
|
|
|
for (@lines) { |
368
|
|
|
|
|
|
|
$cls->create($cls->aliasInsert($_)); |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
sub replace { |
372
|
|
|
|
|
|
|
#td:chain |
373
|
|
|
|
|
|
|
my $cls = shift; |
374
|
|
|
|
|
|
|
my $op = pop(@_); |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
my @records2update = $cls->${\$cls->Var('cdbi_search')}($cls->aliasInputAndSql(@_)); |
377
|
|
|
|
|
|
|
$cls->regexChangeAoH($op,@records2update); |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
sub verify_no_delim { |
380
|
|
|
|
|
|
|
#td:chain |
381
|
|
|
|
|
|
|
my $cls = shift; |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
my @records2update = $cls->${\$cls->Var('cdbi_search')}(@_); |
384
|
|
|
|
|
|
|
my $clean = $cls->verify_no_delim_obj(@records2update); |
385
|
|
|
|
|
|
|
$cls->view("No records containing delimiter found") if ($clean); |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
sub cdbi_update { |
388
|
|
|
|
|
|
|
#td:chain |
389
|
|
|
|
|
|
|
my $cls = shift; |
390
|
|
|
|
|
|
|
#$cls->cdbi_update_obj($cls->${\$cls->Var('cdbi_search')}(@_)); |
391
|
|
|
|
|
|
|
$cls->cdbi_update_obj($cls->search_abstract(@_)); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
##$result obj |
394
|
|
|
|
|
|
|
sub cdbi_update_obj { |
395
|
|
|
|
|
|
|
my ($cls,@records2update) = @_; |
396
|
|
|
|
|
|
|
$cls->sub->_require('File::Temp'); |
397
|
|
|
|
|
|
|
do {warn("File::Temp"); return} if ($@); |
398
|
|
|
|
|
|
|
my (undef,$tempfile) = File::Temp::tempfile(); |
399
|
|
|
|
|
|
|
#$tempfile = 'ya'; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
if ($cls->Flag('safe_update')) { |
402
|
|
|
|
|
|
|
my $clean = $cls->verify_no_delim_obj(@records2update); |
403
|
|
|
|
|
|
|
return if (not $clean); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
$cls->printtofile($tempfile,@records2update); |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
#only for changed rec |
409
|
|
|
|
|
|
|
my @original_lines = $cls->file2array($tempfile) |
410
|
|
|
|
|
|
|
if ($cls->Flag('only_modified')); |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
my $modify = $cls->modify_file($tempfile); |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
#only update changed records |
415
|
|
|
|
|
|
|
if ($cls->Flag('only_modified')) { |
416
|
|
|
|
|
|
|
my @new_lines = $cls->file2array($tempfile); |
417
|
|
|
|
|
|
|
#shift off columns line |
418
|
|
|
|
|
|
|
shift(@new_lines); shift(@original_lines); |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
my ($modified_lines,$num) = ([],[]); |
421
|
|
|
|
|
|
|
($modified_lines,$num) = $cls->uniqueInArrays(\@new_lines,\@original_lines); |
422
|
|
|
|
|
|
|
#exit early if nothing to modify |
423
|
|
|
|
|
|
|
if (@$modified_lines == 0) { $modify = 0; last } |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
#write new file |
426
|
|
|
|
|
|
|
$cls->View->file($tempfile,join("\n",@$modified_lines)); |
427
|
|
|
|
|
|
|
@records2update = $cls->sub->parseNum(join(',',@$num),@records2update); |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
$cls->update_from_file($tempfile,@records2update) if ($modify); |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
sub verify_no_delim_obj { |
433
|
|
|
|
|
|
|
my ($cls,@records) = @_; |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
my @unclean_records = |
436
|
|
|
|
|
|
|
$cls->check_for_regex($cls->Var('field_delimiter'),@records); |
437
|
|
|
|
|
|
|
#$cls->check_for_regex('a',@records); |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
if (defined @unclean_records) { |
440
|
|
|
|
|
|
|
$cls->view( "The following are records containing the delimiter '", |
441
|
|
|
|
|
|
|
$cls->Var('field_delimiter'),"':\n\n"); |
442
|
|
|
|
|
|
|
$cls->View->objAoH(\@unclean_records,$cls->Var('action_columns')); |
443
|
|
|
|
|
|
|
return 0; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
#passed successfully |
446
|
|
|
|
|
|
|
return 1; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
sub cdbi_delete_obj { |
449
|
|
|
|
|
|
|
my $class = shift; |
450
|
|
|
|
|
|
|
for (@_) { $_->delete; } |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
#$dbh commands: could be used in DBI |
453
|
|
|
|
|
|
|
sub display_table_list { |
454
|
|
|
|
|
|
|
my ($class,$dbh) = @_; |
455
|
|
|
|
|
|
|
$class->print_horizontal_numbered_list("Database's tables are ",[$class->get_table_list($dbh)]); |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
sub print_dbi_log { |
458
|
|
|
|
|
|
|
my ($cls) = @_; |
459
|
|
|
|
|
|
|
my $dbh = $cls->cdbiDbh; |
460
|
|
|
|
|
|
|
$cls->view($dbh->{Profile}->format); |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
sub clear_dbi_log { |
463
|
|
|
|
|
|
|
my ($cls) = @_; |
464
|
|
|
|
|
|
|
my $dbh = $cls->cdbiDbh; |
465
|
|
|
|
|
|
|
$dbh->{Profile}->{Data}=undef; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
sub set_dbi_log_level{ |
468
|
|
|
|
|
|
|
my ($cls,$num) = @_; |
469
|
|
|
|
|
|
|
my $dbh = $cls->cdbiDbh; |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
if ($num > 15 or $num < -15) { |
472
|
|
|
|
|
|
|
warn" given log level out of -15 to 15 range"; |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
else { $dbh->{Profile} = $num; } |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
#$dbh = (defined $dbh) ? $cls->idToObj($dbh) : $cls->cdbiDbh; |
477
|
|
|
|
|
|
|
##other |
478
|
|
|
|
|
|
|
sub t_file { |
479
|
|
|
|
|
|
|
my $cls = shift; |
480
|
|
|
|
|
|
|
#w |
481
|
|
|
|
|
|
|
my $file = shift || do { $cls->view("No file given.\n"); return 0 }; |
482
|
|
|
|
|
|
|
if (! -e $file) { $cls->view("File doesn't exist.\n"); return 0}; |
483
|
|
|
|
|
|
|
return 1; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
sub cmpl_file { |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
###internal |
488
|
|
|
|
|
|
|
sub get_table_list { |
489
|
|
|
|
|
|
|
my ($cls,$dbh) = @_; |
490
|
|
|
|
|
|
|
$dbh = (defined $dbh) ? $cls->idToObj($dbh) : $cls->cdbiDbh; |
491
|
|
|
|
|
|
|
my $sth = $cls->get_table_info($dbh); |
492
|
|
|
|
|
|
|
return warn "Driver hasn't implemented the table_info() method" unless (ref $sth); |
493
|
|
|
|
|
|
|
my @tables = map {$_->[2]} @{$sth->fetchall_arrayref}; |
494
|
|
|
|
|
|
|
return @tables; |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
sub get_table_info { |
497
|
|
|
|
|
|
|
#d: displays public tables for postgres, may have to adjust &table_info per database |
498
|
|
|
|
|
|
|
my ($class,$dbh,$table) = @_; |
499
|
|
|
|
|
|
|
my $catalog = undef; |
500
|
|
|
|
|
|
|
my $schema = ($class->Var('db') eq "postgres") ? 'public' : undef; |
501
|
|
|
|
|
|
|
my $type; |
502
|
|
|
|
|
|
|
return $dbh->table_info($catalog,$schema,$table,$type); |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
1; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
__END__ |