| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Bio::ConnectDots::DB; |
|
2
|
16
|
|
|
16
|
|
22654
|
use vars qw(@ISA @AUTO_ATTRIBUTES @OTHER_ATTRIBUTES %SYNONYMS); |
|
|
16
|
|
|
|
|
29
|
|
|
|
16
|
|
|
|
|
5493
|
|
|
3
|
16
|
|
|
16
|
|
99
|
use strict; |
|
|
16
|
|
|
|
|
28
|
|
|
|
16
|
|
|
|
|
1784
|
|
|
4
|
16
|
|
|
16
|
|
81499
|
use DBI; |
|
|
16
|
|
|
|
|
417457
|
|
|
|
16
|
|
|
|
|
1239
|
|
|
5
|
16
|
|
|
16
|
|
190
|
use File::Path; |
|
|
16
|
|
|
|
|
63
|
|
|
|
16
|
|
|
|
|
1392
|
|
|
6
|
16
|
|
|
16
|
|
29739
|
use Class::AutoClass; |
|
|
16
|
|
|
|
|
618726
|
|
|
|
16
|
|
|
|
|
576
|
|
|
7
|
16
|
|
|
16
|
|
63248
|
use Class::AutoClass::Args; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use Bio::ConnectDots::DotSet; |
|
9
|
|
|
|
|
|
|
use Bio::ConnectDots::ConnectorSet; |
|
10
|
|
|
|
|
|
|
@ISA = qw(Class::AutoClass); |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
@AUTO_ATTRIBUTES=qw(dsn dbh dbd database host port user password |
|
13
|
|
|
|
|
|
|
read_only read_only_schema |
|
14
|
|
|
|
|
|
|
_needs_disconnect _db_cursor _exists |
|
15
|
|
|
|
|
|
|
load_name load_save load_chunksize load_cid_base |
|
16
|
|
|
|
|
|
|
_ext_directory _load_fh _load_count _load_chunk sql_log |
|
17
|
|
|
|
|
|
|
); |
|
18
|
|
|
|
|
|
|
@OTHER_ATTRIBUTES=qw(ext_directory); |
|
19
|
|
|
|
|
|
|
%SYNONYMS=(server=>'host'); |
|
20
|
|
|
|
|
|
|
Class::AutoClass::declare(__PACKAGE__); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# use 'double quotations to get case-sensitivity in label |
|
23
|
|
|
|
|
|
|
# use 'not null' wherever possible to help query optimizier use indexes better |
|
24
|
|
|
|
|
|
|
# denormalized connector to cut down the number of joins in big queries |
|
25
|
|
|
|
|
|
|
my %SCHEMA= |
|
26
|
|
|
|
|
|
|
(connectorset=> |
|
27
|
|
|
|
|
|
|
qq(connectorset_id SERIAL, |
|
28
|
|
|
|
|
|
|
"name" VARCHAR(255) NOT NULL, |
|
29
|
|
|
|
|
|
|
"file_name" TEXT, |
|
30
|
|
|
|
|
|
|
"version" VARCHAR(255) NOT NULL, |
|
31
|
|
|
|
|
|
|
"source_date" VARCHAR(255), |
|
32
|
|
|
|
|
|
|
"source_version" VARCHAR(255), |
|
33
|
|
|
|
|
|
|
"download_date" VARCHAR(255), |
|
34
|
|
|
|
|
|
|
"ftp" TEXT, |
|
35
|
|
|
|
|
|
|
"ftp_files" TEXT, |
|
36
|
|
|
|
|
|
|
"comment" TEXT, |
|
37
|
|
|
|
|
|
|
PRIMARY KEY("connectorset_id"),UNIQUE("name","version")), |
|
38
|
|
|
|
|
|
|
dotset=> |
|
39
|
|
|
|
|
|
|
qq(dotset_id SERIAL, |
|
40
|
|
|
|
|
|
|
"name" VARCHAR(255) NOT NULL, |
|
41
|
|
|
|
|
|
|
PRIMARY KEY(dotset_id),UNIQUE("name")), |
|
42
|
|
|
|
|
|
|
connectdotset=> |
|
43
|
|
|
|
|
|
|
qq(connectdotset_id SERIAL, |
|
44
|
|
|
|
|
|
|
connectorset_id INT NOT NULL, |
|
45
|
|
|
|
|
|
|
dotset_id INT NOT NULL, |
|
46
|
|
|
|
|
|
|
label_id INT NOT NULL, |
|
47
|
|
|
|
|
|
|
PRIMARY KEY(connectdotset_id)), |
|
48
|
|
|
|
|
|
|
label=> |
|
49
|
|
|
|
|
|
|
qq(label_id SERIAL, |
|
50
|
|
|
|
|
|
|
"label" VARCHAR(255) NOT NULL, |
|
51
|
|
|
|
|
|
|
"source_label" VARCHAR(255), |
|
52
|
|
|
|
|
|
|
"description" TEXT, |
|
53
|
|
|
|
|
|
|
PRIMARY KEY(label_id),UNIQUE("label")), |
|
54
|
|
|
|
|
|
|
connectortable=> |
|
55
|
|
|
|
|
|
|
qq(connectortable_id SERIAL, |
|
56
|
|
|
|
|
|
|
"name" VARCHAR(255) NOT NULL, |
|
57
|
|
|
|
|
|
|
PRIMARY KEY(connectortable_id),UNIQUE("name")), |
|
58
|
|
|
|
|
|
|
connectortableset=> |
|
59
|
|
|
|
|
|
|
qq(connectortable_id INT NOT NULL, |
|
60
|
|
|
|
|
|
|
connectorset_id INT NOT NULL, |
|
61
|
|
|
|
|
|
|
"alias" VARCHAR(255) NOT NULL, |
|
62
|
|
|
|
|
|
|
UNIQUE(connectortable_id,"alias")), |
|
63
|
|
|
|
|
|
|
dottable=> |
|
64
|
|
|
|
|
|
|
qq(dottable_id SERIAL, |
|
65
|
|
|
|
|
|
|
"name" VARCHAR(255) NOT NULL, |
|
66
|
|
|
|
|
|
|
PRIMARY KEY(dottable_id),UNIQUE("name")), |
|
67
|
|
|
|
|
|
|
dottableset=> |
|
68
|
|
|
|
|
|
|
qq(dottable_id INT NOT NULL, |
|
69
|
|
|
|
|
|
|
dotset_id INT NOT NULL, |
|
70
|
|
|
|
|
|
|
label_id INT NOT NULL, |
|
71
|
|
|
|
|
|
|
cs_id INT NOT NULL, |
|
72
|
|
|
|
|
|
|
"alias" VARCHAR(255) NOT NULL, |
|
73
|
|
|
|
|
|
|
UNIQUE(dottable_id,"alias")), |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
connectdot=> |
|
76
|
|
|
|
|
|
|
qq(connector_id INT NOT NULL, |
|
77
|
|
|
|
|
|
|
connectorset_id INT NOT NULL, |
|
78
|
|
|
|
|
|
|
dot_id INT NOT NULL, |
|
79
|
|
|
|
|
|
|
label_id INT NOT NULL, |
|
80
|
|
|
|
|
|
|
"id" TEXT NOT NULL), |
|
81
|
|
|
|
|
|
|
dot=> |
|
82
|
|
|
|
|
|
|
qq(dot_id SERIAL, |
|
83
|
|
|
|
|
|
|
dotset_id INT NOT NULL, |
|
84
|
|
|
|
|
|
|
"id" TEXT NOT NULL, |
|
85
|
|
|
|
|
|
|
PRIMARY KEY(dot_id),UNIQUE("id",dotset_id)), |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
cdload=> |
|
88
|
|
|
|
|
|
|
qq(connector_id INT NOT NULL, |
|
89
|
|
|
|
|
|
|
connectorset_id INT NOT NULL, |
|
90
|
|
|
|
|
|
|
dotset_id INT NOT NULL, |
|
91
|
|
|
|
|
|
|
label_id INT NOT NULL, |
|
92
|
|
|
|
|
|
|
"id" TEXT NOT NULL), |
|
93
|
|
|
|
|
|
|
); |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
my %INDICIES = ( |
|
96
|
|
|
|
|
|
|
connectdot=> |
|
97
|
|
|
|
|
|
|
['connectorset_id,connector_id,label_id', |
|
98
|
|
|
|
|
|
|
'connectorset_id,dot_id,label_id', |
|
99
|
|
|
|
|
|
|
'connectorset_id,label_id', |
|
100
|
|
|
|
|
|
|
'"id"'] |
|
101
|
|
|
|
|
|
|
); |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
my @INDEX_NAMES; |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
my @TABLES=keys %SCHEMA; |
|
106
|
|
|
|
|
|
|
# maximum number of rows loaded in one 'load infile' operation |
|
107
|
|
|
|
|
|
|
my $LOAD_CHUNKSIZE=150000; |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub _init_self { |
|
110
|
|
|
|
|
|
|
my($self,$class,$args)=@_; |
|
111
|
|
|
|
|
|
|
return unless $class eq __PACKAGE__; # to prevent subclasses from re-running this |
|
112
|
|
|
|
|
|
|
$self->_connect; |
|
113
|
|
|
|
|
|
|
return unless $self->is_connected; |
|
114
|
|
|
|
|
|
|
$self->_manage_schema($args); |
|
115
|
|
|
|
|
|
|
if(!$self->ext_directory) { |
|
116
|
|
|
|
|
|
|
$self->ext_directory("/usr/tmp/$ENV{USER}") if $ENV{USER}; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
$self->load_chunksize or $self->load_chunksize($LOAD_CHUNKSIZE); |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub is_connected { |
|
122
|
|
|
|
|
|
|
$_[0]->dbh; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub connect { |
|
126
|
|
|
|
|
|
|
my($self,@args)=@_; |
|
127
|
|
|
|
|
|
|
my $args=new Bio::ISB::AutoArgs(@args); |
|
128
|
|
|
|
|
|
|
$self->Class::AutoClass::set_attributes([qw(dbh dsn dbd host server user password)],$args); |
|
129
|
|
|
|
|
|
|
$self->_connect; |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
sub _connect { |
|
132
|
|
|
|
|
|
|
my($self)=@_; |
|
133
|
|
|
|
|
|
|
return $self->dbh if $self->dbh; # if dbh set, then already connected |
|
134
|
|
|
|
|
|
|
my $dbd=lc($self->dbd)||'Pg'; |
|
135
|
|
|
|
|
|
|
$self->throw("-dbd must be 'Pg' at present") if $dbd && $dbd ne 'Pg'; |
|
136
|
|
|
|
|
|
|
my $dsn=$self->dsn; |
|
137
|
|
|
|
|
|
|
if ($dsn) { # parse off the dbd, database, host elements |
|
138
|
|
|
|
|
|
|
$dsn = "DBI:$dsn" unless $dsn=~ /^dbi/i; |
|
139
|
|
|
|
|
|
|
} else { |
|
140
|
|
|
|
|
|
|
my $database=$self->database; |
|
141
|
|
|
|
|
|
|
my $host=$self->host; |
|
142
|
|
|
|
|
|
|
my $port=$self->port; |
|
143
|
|
|
|
|
|
|
return undef unless $database; |
|
144
|
|
|
|
|
|
|
$dsn="DBI:$dbd:dbname=$database;"; |
|
145
|
|
|
|
|
|
|
$dsn .= "host=$host;" if $host; |
|
146
|
|
|
|
|
|
|
$dsn .= "port=$port;" if $port; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
# Try to establish connection with data source. |
|
149
|
|
|
|
|
|
|
my $user=$self->user; |
|
150
|
|
|
|
|
|
|
my $password = $self->password; |
|
151
|
|
|
|
|
|
|
my $dbh = DBI->connect($dsn,$user,$password, |
|
152
|
|
|
|
|
|
|
{AutoCommit=>1, ChopBlanks=>1, PrintError=>0, Warn=>0,}); |
|
153
|
|
|
|
|
|
|
$self->dsn($dsn); |
|
154
|
|
|
|
|
|
|
$self->dbh($dbh); |
|
155
|
|
|
|
|
|
|
$self->_needs_disconnect(1); |
|
156
|
|
|
|
|
|
|
$self->throw("DBI::connect failed for dsn=$dsn, username=$user: ".DBI->errstr) unless $dbh; |
|
157
|
|
|
|
|
|
|
return $dbh; |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
sub _manage_schema { |
|
160
|
|
|
|
|
|
|
my($self,$args)=@_; |
|
161
|
|
|
|
|
|
|
# grab schema modification parameters |
|
162
|
|
|
|
|
|
|
my $read_only_schema=$self->read_only_schema || $self->read_only; |
|
163
|
|
|
|
|
|
|
my $drop=$args->drop; |
|
164
|
|
|
|
|
|
|
my $create=$args->create; |
|
165
|
|
|
|
|
|
|
$self->throw("Schema changes not allowed by -read_only or -read_only_schema setting") if ($drop||$create) && $read_only_schema; |
|
166
|
|
|
|
|
|
|
$self->drop if $drop; |
|
167
|
|
|
|
|
|
|
$self->create if $create || !($self->exists && !defined $create); |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# returns 1 if all tables exist, -1 if some exist, 0 if none exist |
|
171
|
|
|
|
|
|
|
# note that Perl treats -1 as 'true' |
|
172
|
|
|
|
|
|
|
sub exists { |
|
173
|
|
|
|
|
|
|
my($self,$doit)=@_; |
|
174
|
|
|
|
|
|
|
return $self->_exists if !$doit && defined $self->_exists; |
|
175
|
|
|
|
|
|
|
$self->throw("Cannot check schema: database is not connected") unless $self->is_connected; |
|
176
|
|
|
|
|
|
|
my $dbh=$self->dbh; |
|
177
|
|
|
|
|
|
|
my $tables=$dbh->selectall_arrayref(qq(select tablename from pg_tables where schemaname='public')); |
|
178
|
|
|
|
|
|
|
my $count; |
|
179
|
|
|
|
|
|
|
for my $table (@TABLES) { |
|
180
|
|
|
|
|
|
|
$count++ if grep {$table eq $_->[0]} @$tables; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
my $exists; |
|
183
|
|
|
|
|
|
|
$exists=0 if $count==0; |
|
184
|
|
|
|
|
|
|
$exists=1 if $count==@TABLES; |
|
185
|
|
|
|
|
|
|
$exists=-1 if $count>0 && $count!=@TABLES; |
|
186
|
|
|
|
|
|
|
$self->_exists($exists); |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
sub drop { |
|
189
|
|
|
|
|
|
|
my $self=shift; |
|
190
|
|
|
|
|
|
|
$self->throw("Cannot drop database: database is not connected") unless $self->is_connected; |
|
191
|
|
|
|
|
|
|
my @sql; |
|
192
|
|
|
|
|
|
|
foreach my $tbl (@TABLES) { |
|
193
|
|
|
|
|
|
|
push ( @sql, qq(DROP TABLE $tbl) ) if table_exist($tbl); |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
foreach my $indx (@INDEX_NAMES) { |
|
196
|
|
|
|
|
|
|
push(@sql, qq(DROP INDEX $indx)); |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
$self->do_sql(@sql); |
|
200
|
|
|
|
|
|
|
$self->exists('DOIT'); # make sure schema was really dropped |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
### Returns true (1) if table exists in database, 0 otherwise |
|
204
|
|
|
|
|
|
|
sub table_exist { |
|
205
|
|
|
|
|
|
|
my ($self, $table_name)=@_; |
|
206
|
|
|
|
|
|
|
$self->throw("Cannot create database: database is not connected") unless $self->is_connected; |
|
207
|
|
|
|
|
|
|
$table_name = lc($table_name); |
|
208
|
|
|
|
|
|
|
my $query = "SELECT tablename FROM pg_tables WHERE tablename='$table_name'"; |
|
209
|
|
|
|
|
|
|
my $dbh=$self->dbh; |
|
210
|
|
|
|
|
|
|
my $rslt = $dbh->selectrow_arrayref($query); |
|
211
|
|
|
|
|
|
|
return $rslt ? 1 : 0; |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub create { |
|
215
|
|
|
|
|
|
|
my $self=shift; |
|
216
|
|
|
|
|
|
|
$self->throw("Cannot create database: database is not connected") unless $self->is_connected; |
|
217
|
|
|
|
|
|
|
$self->drop if $self->exists; |
|
218
|
|
|
|
|
|
|
my @sql; |
|
219
|
|
|
|
|
|
|
while(my($table,$schema)=each %SCHEMA) { |
|
220
|
|
|
|
|
|
|
push(@sql,qq(CREATE TABLE $table ($schema))); |
|
221
|
|
|
|
|
|
|
if ($INDICIES{$table}) { |
|
222
|
|
|
|
|
|
|
my $num=0; |
|
223
|
|
|
|
|
|
|
foreach my $tbl_index (@{ $INDICIES{$table} }) { |
|
224
|
|
|
|
|
|
|
my $index_name = $table .'_index_'. ($num+1); |
|
225
|
|
|
|
|
|
|
push( @INDEX_NAMES, $index_name ); |
|
226
|
|
|
|
|
|
|
$INDICIES{$table}->[$num] eq 'id'? |
|
227
|
|
|
|
|
|
|
push( @sql, qq(CREATE INDEX $index_name ON $table USING BTREE ($INDICIES{$table}->[$num])) ) : |
|
228
|
|
|
|
|
|
|
push( @sql, qq(CREATE INDEX $index_name ON $table ($INDICIES{$table}->[$num])) ); |
|
229
|
|
|
|
|
|
|
$num++; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
} |
|
233
|
|
|
|
|
|
|
$self->do_sql(@sql); |
|
234
|
|
|
|
|
|
|
$self->exists('DOIT'); # make sure schema was really created |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
sub analyze { |
|
237
|
|
|
|
|
|
|
my $self=shift; |
|
238
|
|
|
|
|
|
|
$self->throw("Cannot analyze database: database is not connected") unless $self->is_connected; |
|
239
|
|
|
|
|
|
|
my @sql=map {qq(ANALYZE $_)} @TABLES; |
|
240
|
|
|
|
|
|
|
$self->do_sql(@sql); |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
# load dots and connectdots |
|
243
|
|
|
|
|
|
|
sub load_init { |
|
244
|
|
|
|
|
|
|
my($self,$load_name,$load_save,$load_chunksize)=@_; |
|
245
|
|
|
|
|
|
|
my $max=$self->dbh->selectrow_array |
|
246
|
|
|
|
|
|
|
(qq(select max(connector_id) from connectdot)) || 0; |
|
247
|
|
|
|
|
|
|
$self->set |
|
248
|
|
|
|
|
|
|
(load_name=>$load_name, |
|
249
|
|
|
|
|
|
|
load_save=>$load_save, |
|
250
|
|
|
|
|
|
|
load_chunksize=>$load_chunksize||$LOAD_CHUNKSIZE, |
|
251
|
|
|
|
|
|
|
load_cid_base=>$max, |
|
252
|
|
|
|
|
|
|
_load_fh=>undef,_load_count=>0,_load_chunk=>0); |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
sub load_row { |
|
255
|
|
|
|
|
|
|
my($self,$connector_id,$connectorset_id,$id,$dotset_id,$label_id)=@_; |
|
256
|
|
|
|
|
|
|
my($ext_directory,$load_name,$load_fh,$load_count,$load_chunk)= |
|
257
|
|
|
|
|
|
|
$self->get(qw(ext_directory load_name _load_fh _load_count _load_chunk)); |
|
258
|
|
|
|
|
|
|
my $load_file="$ext_directory/load.$load_name.$load_chunk"; |
|
259
|
|
|
|
|
|
|
if (!defined $load_fh) { |
|
260
|
|
|
|
|
|
|
open($load_fh, "> $load_file") || $self->throw("Cannot open load file $load_file: $!"); |
|
261
|
|
|
|
|
|
|
$self->_load_fh($load_fh); |
|
262
|
|
|
|
|
|
|
} elsif ($load_count>=$self->load_chunksize) { |
|
263
|
|
|
|
|
|
|
close $load_fh; |
|
264
|
|
|
|
|
|
|
$self->load($load_file); |
|
265
|
|
|
|
|
|
|
$load_chunk++; |
|
266
|
|
|
|
|
|
|
$load_count=0; |
|
267
|
|
|
|
|
|
|
my $load_file="$ext_directory/load.$load_name.$load_chunk"; # bug found by YW 04-01-15 |
|
268
|
|
|
|
|
|
|
open($load_fh, "> $load_file") || $self->throw("Cannot open load file $load_file: $!"); |
|
269
|
|
|
|
|
|
|
$self->set(_load_fh=>$load_fh,_load_chunk=>$load_chunk); |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
$connector_id+=$self->load_cid_base; |
|
272
|
|
|
|
|
|
|
$id=$self->escape($id); # escape special chars |
|
273
|
|
|
|
|
|
|
print $load_fh join("\t",$connector_id,$connectorset_id,$dotset_id,$label_id,$id),"\n"; |
|
274
|
|
|
|
|
|
|
$self->_load_count($load_count+1); |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
sub load_finish { |
|
277
|
|
|
|
|
|
|
my($self)=@_; |
|
278
|
|
|
|
|
|
|
my($ext_directory,$load_name,$load_fh,$load_count,$load_chunk)= |
|
279
|
|
|
|
|
|
|
$self->get(qw(ext_directory load_name _load_fh _load_count _load_chunk)); |
|
280
|
|
|
|
|
|
|
if (defined $load_fh) { |
|
281
|
|
|
|
|
|
|
close $load_fh; |
|
282
|
|
|
|
|
|
|
my $load_file="$ext_directory/load.$load_name.$load_chunk"; |
|
283
|
|
|
|
|
|
|
$self->load($load_file,'last'); |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
sub load { |
|
287
|
|
|
|
|
|
|
my($self,$load_file,$last)=@_; |
|
288
|
|
|
|
|
|
|
my $dbh=$self->dbh; |
|
289
|
|
|
|
|
|
|
my @sql; |
|
290
|
|
|
|
|
|
|
push(@sql, |
|
291
|
|
|
|
|
|
|
qq(set enable_hashjoin to off), |
|
292
|
|
|
|
|
|
|
qq(set enable_mergejoin to off)); |
|
293
|
|
|
|
|
|
|
push(@sql, # load data |
|
294
|
|
|
|
|
|
|
qq(COPY cdload (connector_id,connectorset_id,dotset_id,label_id,id) FROM '$load_file')); |
|
295
|
|
|
|
|
|
|
push(@sql, qq(SELECT cdload.connector_id,cdload.connectorset_id,cdload.dotset_id,dot.dot_id,cdload.label_id,cdload.id |
|
296
|
|
|
|
|
|
|
INTO TABLE cdload_dot |
|
297
|
|
|
|
|
|
|
FROM cdload LEFT JOIN dot ON cdload.id=dot.id)); |
|
298
|
|
|
|
|
|
|
push(@sql,qq(INSERT INTO dot (dotset_id,id) SELECT DISTINCT dotset_id,id FROM cdload_dot WHERE dot_id IS NULL)); |
|
299
|
|
|
|
|
|
|
push(@sql,qq(INSERT INTO connectdot (connector_id,connectorset_id,dot_id,label_id,id) |
|
300
|
|
|
|
|
|
|
SELECT connector_id,connectorset_id,dot_id,label_id,id FROM cdload_dot WHERE dot_id IS NOT NULL)); |
|
301
|
|
|
|
|
|
|
push(@sql,qq(INSERT INTO connectdot (connector_id,connectorset_id,dot_id,label_id,id) |
|
302
|
|
|
|
|
|
|
SELECT cdload_dot.connector_id,cdload_dot.connectorset_id,dot.dot_id,cdload_dot.label_id,cdload_dot.id |
|
303
|
|
|
|
|
|
|
FROM cdload_dot,dot |
|
304
|
|
|
|
|
|
|
WHERE cdload_dot.dot_id IS NULL AND cdload_dot.id=dot.id)); |
|
305
|
|
|
|
|
|
|
push(@sql,qq(DROP TABLE cdload)); |
|
306
|
|
|
|
|
|
|
push(@sql,qq(CREATE TABLE cdload ($SCHEMA{'cdload'}))); |
|
307
|
|
|
|
|
|
|
push(@sql,qq(DROP TABLE cdload_dot)); |
|
308
|
|
|
|
|
|
|
push(@sql,qq(ANALYZE)); |
|
309
|
|
|
|
|
|
|
$self->do_sql(@sql); |
|
310
|
|
|
|
|
|
|
$self->do_sql(qq(set enable_hashjoin to on)); |
|
311
|
|
|
|
|
|
|
$self->do_sql(qq(set enable_mergejoin to on)); |
|
312
|
|
|
|
|
|
|
unlink($load_file) unless $self->load_save eq 'all' || ($last && $self->load_save eq $last) ; |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub ext_directory { |
|
316
|
|
|
|
|
|
|
my $self=shift; |
|
317
|
|
|
|
|
|
|
if (@_) { |
|
318
|
|
|
|
|
|
|
my $ext_directory=shift; |
|
319
|
|
|
|
|
|
|
mkpath([$ext_directory]) if $ext_directory; |
|
320
|
|
|
|
|
|
|
return $self->_ext_directory($ext_directory); |
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
$self->_ext_directory; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub create_table_sql { |
|
326
|
|
|
|
|
|
|
my($self,$name,$sql,$indexed_columns,$sql_columns)=@_; |
|
327
|
|
|
|
|
|
|
$name = lc($name); # Postgres has inconsistent support for capitalization of table names |
|
328
|
|
|
|
|
|
|
my @sql; |
|
329
|
|
|
|
|
|
|
push (@sql, "DROP TABLE $name") if $self->table_exist($name); |
|
330
|
|
|
|
|
|
|
push (@sql, "CREATE TABLE $name AS $sql"); |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
my $num=0; |
|
333
|
|
|
|
|
|
|
foreach (@$indexed_columns) { |
|
334
|
|
|
|
|
|
|
my $index_name = $name ."_index_".$_ . $num ; |
|
335
|
|
|
|
|
|
|
push( @INDEX_NAMES, $index_name ); |
|
336
|
|
|
|
|
|
|
push( @sql, qq(CREATE INDEX $index_name ON $name ($_)) ); |
|
337
|
|
|
|
|
|
|
$num++; |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
push (@sql, "ANALYZE $name"); |
|
340
|
|
|
|
|
|
|
$self->do_sql(@sql); |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub create_file_sql { |
|
345
|
|
|
|
|
|
|
my($self,$file,$sql)=@_; |
|
346
|
|
|
|
|
|
|
unlink($file); |
|
347
|
|
|
|
|
|
|
# print "$sql ",`date`; |
|
348
|
|
|
|
|
|
|
my $dbh=$self->dbh; |
|
349
|
|
|
|
|
|
|
$dbh->do($sql) || $self->throw($dbh->errstr); |
|
350
|
|
|
|
|
|
|
} |
|
351
|
|
|
|
|
|
|
sub do_sql { |
|
352
|
|
|
|
|
|
|
my $self=shift; |
|
353
|
|
|
|
|
|
|
my @sql=_flatten(@_); |
|
354
|
|
|
|
|
|
|
$self->throw("Cannot run SQL: database is not connected") unless $self->is_connected; |
|
355
|
|
|
|
|
|
|
my $dbh=$self->dbh; |
|
356
|
|
|
|
|
|
|
for my $sql (@sql) { |
|
357
|
|
|
|
|
|
|
if($self->sql_log) { |
|
358
|
|
|
|
|
|
|
my $file = $self->sql_log; |
|
359
|
|
|
|
|
|
|
open (LOG, ">>$file") or $self->throw("Can not open SQL log file: $file"); |
|
360
|
|
|
|
|
|
|
print LOG "#", `date`; |
|
361
|
|
|
|
|
|
|
print LOG "$sql\n\n"; |
|
362
|
|
|
|
|
|
|
close(LOG); |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
$dbh->do($sql) || do { print "### SQL: $sql\n"; $self->throw($dbh->errstr); } |
|
365
|
|
|
|
|
|
|
} |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub quote { |
|
369
|
|
|
|
|
|
|
my($self,$value)=@_; |
|
370
|
|
|
|
|
|
|
$self->dbh->quote($value); |
|
371
|
|
|
|
|
|
|
} |
|
372
|
|
|
|
|
|
|
sub quote_dot { |
|
373
|
|
|
|
|
|
|
my($self,$value)=@_; |
|
374
|
|
|
|
|
|
|
$self->dbh->quote($value); |
|
375
|
|
|
|
|
|
|
} |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub escape { |
|
378
|
|
|
|
|
|
|
my($self,$field)=@_; |
|
379
|
|
|
|
|
|
|
my $q_field=$self->dbh->quote($field); |
|
380
|
|
|
|
|
|
|
$q_field=~s/^\'|\'$//g; |
|
381
|
|
|
|
|
|
|
$q_field; |
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
sub _flatten {map {'ARRAY' eq ref $_? @$_: $_} @_;} |
|
384
|
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
1; |
|
388
|
|
|
|
|
|
|
__END__ |