File Coverage

blib/lib/WWW/MLite/Store/DBI.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package WWW::MLite::Store::DBI; # $Id: DBI.pm 15 2014-06-04 06:24:25Z minus $
2 1     1   48622 use strict;
  1         2  
  1         133  
3              
4             =head1 NAME
5              
6             WWW::MLite::Store::DBI - Database independent interface for WWW::MLite on CTK::DBI based
7              
8             =head1 VERSION
9              
10             Version 1.01
11              
12             =head1 SYNOPSIS
13              
14             use WWW::MLite::Store::DBI;
15              
16             # MySQL connect
17             my $mysql = new WWW::MLite::Store::DBI (
18             -mlite => $mlite, # OPTIONAL
19             -dsn => 'DBI:mysql:database=TEST;host=192.168.1.1',
20             -user => 'login',
21             -pass => 'password',
22             -connect_to => 5,
23             -request_to => 60
24             -attr => {
25             mysql_enable_utf8 => 1,
26             RaiseError => 0,
27             PrintError => 0,
28             },
29             ); # See CTK::DBI
30            
31             # MySQL connect (old style, without DSN)
32             my $mysql = new WWW::MLite::Store::DBI (
33             -mlite => $mlite, # OPTIONAL
34            
35             -driver => 'mysql', # Driver name. See DBI module
36             # Available drivers:
37             # CSV, DBM, ExampleP, File, Gofer, ODBC, Oracle,
38             # Pg, Proxy, SQLite, Sponge, mysql
39             -host => '192.168.1.1',
40             -port => '3306', # default
41             -database => 'TEST',
42            
43             -user => 'login',
44             -pass => 'password',
45             -attr => {
46             mysql_enable_utf8 => 1,
47             RaiseError => 0,
48             PrintError => 0,
49             },
50             );
51              
52             my $dbh = $mysql->connect;
53            
54             my $pingstat = $mysql->ping if $mysql;
55            
56             $mysql->reconnect() unless $pingstat;
57            
58             # Table select (as array)
59             my @result = $mysql->table($sql, @inargs);
60              
61             # Table select (as hash)
62             my %result = $mysql->tableh($key, $sql, @inargs); # $key - primary index field name
63              
64             # Record (as array)
65             my @result = $mysql->record($sql, @inargs);
66              
67             # Record (as hash)
68             my %result = $mysql->recordh($sql, @inargs);
69              
70             # Fiels (as scalar)
71             my $result = $mysql->field($sql, @inargs);
72              
73             # SQL/PL-SQL
74             my $sth = $mysql->execute($sql, @inargs);
75             ...
76             $sth->finish;
77              
78             =head1 DESCRIPTION
79              
80             Database independent interface for WWW::MLite on CTK::DBI based.
81              
82             =head2 DEBUG
83              
84             Set $WWW::MLite::Store::DBI::DEBUG_FORCE = 1 for enable debugging in STDERR where object $mlite undefined
85              
86             Coming soon
87              
88             =head1 METHODS
89              
90             =over 8
91              
92             =item B<ping>
93              
94             my $status = $mysql->ping();
95              
96             Returns connection's life status
97              
98             =item B<reconnect>
99              
100             $mysql->reconnect unless $mysql->ping();
101              
102             =item B<err, errstr, state>
103              
104             my $err = $mysql->err;
105             my $errstr = $mysql->errstr;
106             my $state = $mysql->state;
107              
108             Methods returns DBI values: err, errstr and state.
109              
110             See L<DBI/"METHODS_COMMON_TO_ALL_HANDLES">
111              
112             =back
113              
114             =head1 EXAMPLES
115              
116             =over 8
117              
118             =item B<Example 1>
119              
120             use WWW::MLite::Store::DBI;
121             # eval 'sub CTK::DBI::_error {1}'; # For supressing CTK::DBI errors
122            
123             my $mysql => new WWW::MLite::Store::DBI (
124             -mlite => $mlite,
125             -dsn => 'DBI:mysql:database=NAME;host=HOST',
126             -user => 'USER',
127             -pass => 'PASSWORD',
128             -attr => {
129             mysql_enable_utf8 => 1,
130             RaiseError => 0,
131             PrintError => 0,
132             HandleError => sub { $m->log_error(shift || '') },
133             },
134             )
135            
136             ...
137            
138             my @data = $mysql->table('select * from table');
139              
140             =item B<Example 2: with reconnection>
141              
142             use WWW::MLite::Store::DBI;
143            
144             my $mysql => new WWW::MLite::Store::DBI (
145             -mlite => $mlite, # OPTIONAL
146             -dsn => 'DBI:mysql:database=NAME;host=HOST',
147             -user => 'USER',
148             -pass => 'PASSWORD',
149             -attr => {
150             mysql_enable_utf8 => 1,
151             RaiseError => 0,
152             PrintError => 0,
153             HandleError => sub { $m->log_error(shift || '') },
154             },
155             )
156              
157             ...
158              
159             $mysql->reconnect unless $mysql->ping;
160            
161             ...
162              
163             my @data = $mysql->table('select * from table');
164              
165             =item B<Example 3: Oracle>
166              
167             # Oracle connect
168             my $oracle = new WWW::MLite::Store::DBI (
169             -mlite => $mlite, # OPTIONAL
170             -driver => 'Oracle',
171             -host => '192.168.1.1',
172             -database => 'TEST',
173             -user => 'login',
174             -pass => 'password',
175             -attr => {
176             RaiseError => 0,
177             PrintError => 0,
178             },
179             )
180            
181             ...
182            
183             my $value = mysql->field('select sysdate from dual');
184              
185              
186             =item B<Simple example>
187              
188             use WWW::MLite::Store::DBI;
189              
190             $WWW::MLite::Store::DBI::DEBUG_FORCE = 1;
191             my $dbi = new WWW::MLite::Store::DBI (
192             -driver => 'mysql',
193             -name => 'mylocaldb',
194             -user => 'user',
195             -password => 'password'
196             );
197             ...
198             my @table = $dbi->table("select * from tablename where date = ?", "01.01.2000");
199              
200             =item B<Sponge example>
201              
202             use WWW::MLite::Store::DBI;
203              
204             $WWW::MLite::Store::DBI::DEBUG_FORCE = 1;
205             my $o = new WWW::MLite::Store::DBI(
206             -driver => 'Sponge',
207             -attr => { RaiseError => 1 },
208             );
209             my $dbh = $o->connect();
210             my $sth = $dbh->prepare("select * from table", {
211             rows => [
212             [qw/foo bar baz/],
213             [qw/qux quux corge/],
214             [qw/grault garply waldo/],
215             ],
216             NAME => [qw/h1 h2 h3/],
217             });
218              
219             $sth->execute();
220             my $result = $sth->fetchall_arrayref;
221             $sth->finish;
222             print Dumper($result);
223              
224             =back
225              
226             =head1 HISTORY
227              
228             See C<CHANGES> file
229              
230             =head1 SEE ALSO
231              
232             L<CTK::DBI>, L<DBI>
233              
234             =head1 AUTHOR
235              
236             Serz Minus (Lepenkov Sergey) L<http://www.serzik.com> E<lt>minus@mail333.comE<gt>
237              
238             =head1 COPYRIGHT
239              
240             Copyright (C) 1998-2014 D&D Corporation. All Rights Reserved
241              
242             =head1 LICENSE
243              
244             This program is free software: you can redistribute it and/or modify
245             it under the terms of the GNU General Public License as published by
246             the Free Software Foundation, either version 3 of the License, or
247             (at your option) any later version.
248              
249             This program is distributed in the hope that it will be useful,
250             but WITHOUT ANY WARRANTY; without even the implied warranty of
251             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
252             GNU General Public License for more details.
253              
254             See C<LICENSE> file
255              
256             =cut
257              
258 1     1   6 use vars qw($VERSION $DEBUG_FORCE);
  1         2  
  1         174  
259             $VERSION = '1.01';
260              
261             use constant {
262 1         117 ATTR_NAMES => [
263             ['M', 'MLITE', 'GLOBAL', 'GLOB', 'OBJECT'], # 0
264             ['DSN','STRING','STR'], # 1
265             ['HOST','HOSTNAME','SERVER','SERVERNAME','ADDRESS','ADDR','SERVERADDR'], # 2
266             ['DB','BD','DBNAME','DATABASE','NAME','DATABASENAME'], # 3
267             ['PORT',], # 4
268             ['USER','USERNAME','LOGIN'], # 5
269             ['PASSWORD','PASS'], # 6
270             ['DRIVER','DRIVERNAME'], # 7
271             ['TIMEOUT_CONNECT','CONNECT_TIMEOUT','CNT_TIMEOUT','TIMEOUT_CNT','TO_CONNECT','CONNECT_TO'],# 8
272             ['TIMEOUT_REQUEST','REQUEST_TIMEOUT','REQ_TIMEOUT','TIMEOUT_REQ','TO_REQUEST','REQUEST_TO'],# 9
273             ['ATTRIBUTES','ATTR','ATTRHASH','PARAMS'], # 10
274             ],
275 1     1   6 };
  1         9  
276              
277 1     1   8161 use DBI;
  1         30661  
  1         71  
278 1     1   11 use base qw/CTK::DBI/;
  1         1  
  1         804  
279             use CTK::Util qw/ :API /;
280              
281             sub new {
282             my $class = shift;
283             my @in = read_attributes(ATTR_NAMES,@_);
284            
285             # Îñíîâíûå àòðèáóòû ñîåäèíåíèÿ MySQL
286             my $m = $in[0];
287             my $dsn = $in[1] || '';
288             my $host = $in[2] || '';
289             my $db = $in[3] || '';
290             my $port = $in[4] || '';
291             my $user = $in[5] || '';
292             my $pass = $in[6] || '';
293             my $driver = $in[7] || '';
294             my $toc = $in[8] || 0;
295             my $tor = $in[9] || 0;
296             my $attr = $in[10] || undef;
297            
298             unless ($dsn) {
299             my @adrivers = DBI->available_drivers();
300             if (grep {$driver eq $_} @adrivers) {
301             if ($driver =~ /mysql/i) {
302             $dsn = "DBI:mysql:database=$db".($host?";host=$host":'').($port?";port=$port":'');
303             } elsif ($driver =~ /Oracle/i) {
304             if ($host) {
305             $dsn = "DBI:Oracle:host=$host".($db?";service_name=$db":'').($port?";port=$port":'');
306             } else {
307             $dsn = "DBI:Oracle:".($db?"$db":'').($port?";port=$port":'');
308             }
309             } else {
310             # dbi:DriverName:database=database_name;host=hostname;port=port
311             $dsn = "DBI:".$driver.":"
312             .($db?"database=$db":'')
313             .($host?";host=$host":'')
314             .($port?";port=$port":'');
315             }
316             } else {
317             carp("Driver \"$driver\" not availebled. Available drivers: ",join(", ",@adrivers));
318             }
319             }
320             my %args = (
321             -dsn => $dsn,
322             -user => $user,
323             -pass => $pass,
324             -timeout_connect => $toc,
325             -timeout_request => $tor,
326             -attr => $attr,
327             );
328              
329             if ($dsn) {
330             my $obj = $class->SUPER::new(%args);
331             $obj = bless({}, $class) unless $obj && ref($obj) eq __PACKAGE__;
332             $obj->{mlite} = $m;
333             return $obj unless $obj->{dbh};
334             if ($m && ref($m) eq 'WWW::MLite') {
335             $m->debug("--- CONNECT {$dsn} AS $obj ---");
336             } else {
337             carp("--- CONNECT {$dsn} AS $obj ---") if $DEBUG_FORCE;
338             }
339             return $obj if $obj;
340             } else {
341             return bless({
342             mlite=>$m,
343             }, $class);
344             }
345             return undef;
346             }
347             sub ping {
348             my $self = shift;
349             return 0 unless $self && ref($self) eq __PACKAGE__;
350             return 0 unless $self->{dsn};
351             return 0 unless $self->{dbh};
352             return 0 unless $self->{dbh}->can('ping');
353             return $self->{dbh}->ping();
354             }
355             sub reconnect {
356             my $self = shift;
357              
358             my $m = $self->{mlite};
359             my $dsn = $self->{dsn};
360            
361             # See CTK::DBI::DBI_CONNECT
362             $self->{dbh} = CTK::DBI::DBI_CONNECT(
363             $dsn,
364             $self->{user},
365             $self->{password},
366             $self->{attr},
367             $self->{connect_to},
368             );
369             if ($self->{dbh}) {
370             if ($m && ref($m) eq 'WWW::MLite') {
371             $m->debug("--- RECONNECT {$dsn} AS $self ---");
372             } else {
373             carp("--- RECONNECT {$dsn} AS $self ---") if $DEBUG_FORCE;
374             }
375             return 1;
376             }
377             return undef;
378             }
379             sub err {
380             my $self = shift;
381             return $self->{dbh}->err if $self->{dbh} && $self->{dbh}->can('err');
382             return defined $DBI::err ? $DBI::err : 0;
383             }
384             sub errstr {
385             my $self = shift;
386             return $self->{dbh}->errstr if $self->{dbh} && $self->{dbh}->can('errstr');
387             return defined $DBI::errstr ? $DBI::errstr : '';
388             }
389             sub state {
390             my $self = shift;
391             return $self->{dbh}->state if $self->{dbh} && $self->{dbh}->can('state');
392             return defined $DBI::state ? $DBI::state : '';
393             }
394             sub DESTROY {
395             my $self = shift;
396             my $dsn = '';
397             $dsn = $self->{dsn} if $self->{dsn};
398             my $m = '';
399             $m = $self->{mlite} if $self->{mlite};
400            
401             if ($dsn && $self->{dbh}) {
402             if($m && ref($m) eq 'WWW::MLite') {
403             $m->debug("--- DISCONNECT {$dsn} ---");
404             } else {
405             carp("--- DISCONNECT {$dsn} ---") if $DEBUG_FORCE;
406             }
407             }
408             }
409              
410             1;