File Coverage

blib/lib/DeltaX/Database.pm
Criterion Covered Total %
statement 24 1029 2.3
branch 0 704 0.0
condition 0 238 0.0
subroutine 8 50 16.0
pod 31 35 88.5
total 63 2056 3.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             #
3             # (c) DELTA E.S., 2002 - 2003
4             # This package is free software; you can use it under "Artistic License" from
5             # Perl.
6             # Author : Martin Kula, 1999
7             # to object model rewritten by
8             # Jakub Spicak
9             # $Id: Database.pm,v 1.16 2003/10/13 06:28:34 spicak Exp $
10             #
11              
12             package DeltaX::Database;
13 2     2   1370 use strict;
  2         3  
  2         82  
14 2     2   3485 use DBI;
  2         34492  
  2         156  
15 2     2   19 use Carp;
  2         2  
  2         127  
16 2     2   1058 use DeltaX::Trace;
  2         4  
  2         150  
17 2     2   1267 use Time::HiRes qw/gettimeofday tv_interval/;
  2         2785  
  2         10  
18 2         180 use vars qw(@ISA @EXPORT @EXPORT_OK
19             $VERSION
20             $Dcmdstatus
21             $Dsqlstatus
22             $Derror_message
23             $Dstr_command
24 2     2   374 );
  2         3  
25 2     2   9 use Exporter;
  2         1  
  2         16283  
26             @ISA = ('Exporter');
27             @EXPORT = ();
28             @EXPORT_OK = qw(
29             $Dstr_command
30             $Derror_message
31             $Dsqlstatus
32             $Dcmdstatus
33             );
34              
35             #########################################################################
36             # Setting global module variables
37             #########################################################################
38             $DeltaX::Database::VERSION = '3.4'; # Module version
39              
40             #########################################################################
41             # Procedure declaration
42             #########################################################################
43              
44             #########################################################################
45             sub new {
46 0     0 1   my $pkg = shift;
47 0           my $self = {};
48 0           bless($self, $pkg);
49              
50 0           $self->{driver} = '';
51 0           $self->{dbname} = '';
52 0           $self->{user} = '';
53 0           $self->{auth} = '';
54 0           $self->{autocommit} = 0;
55 0           $self->{datestyle} = '';
56 0           $self->{close_curs} = 0;
57 0           $self->{cursor_type} = 'INTERNAL';
58 0           $self->{trace} = 0;
59 0           $self->{app} = '';
60 0           $self->{host} = '';
61 0           $self->{port} = '';
62 0           $self->{codepage} = '';
63 0           $self->{stat_type} = 'none';
64 0           $self->{stat_max_high} = 3;
65 0           $self->{stat_max_all} = 1000;
66 0           $self->{imix_number_correct} = 0;
67 0           $self->{use_sequences} = 0; # Informix server 1-use internal sequences 0-use external sequences
68              
69 0 0         croak ("DeltaX::Database::new called with odd number of parameters -".
70             " should be of the form field => value")
71             if (@_ % 2);
72              
73 0           for (my $x = 0; $x <= $#_; $x += 2) {
74 0 0         croak ("Unknown parameter $_[$x] in DeltaX::Database::new()")
75             unless exists $self->{lc($_[$x])};
76 0           $self->{lc($_[$x])} = $_[$x+1];
77             }
78 0           $self->{transaction} = 0;
79 0           $self->{cursors} = {};
80 0           $self->{statements} = {};
81              
82 0           my $orig_driver = $self->{driver};
83 0           $self->{driver} = get_driver($self->{driver});
84 0 0         if (! $self->{driver}) {
85 0           $Derror_message = "MODULE ERROR: Can't get a DBD driver";
86 0           return -3;
87             }
88              
89 0           my %attr = ('AutoCommit' => $self->{autocommit}, 'PrintError' => 0);
90 0           $self->{driver} = $self->get_source($self->{driver}, $self->{dbname});
91 0 0         if (! $self->{driver}) {
92 0           $Derror_message = "MODULE ERROR: Can't get a DB source";
93 0           return -4;
94             }
95              
96 0           my ($user, $auth);
97 0           SWITCH: for ($self->{driver}) {
98 0 0         /Pg/ && do {
99 0 0         $ENV{'PGDATESTYLE'} = $self->{datestyle} if $self->{datestyle};
100 0           $user = $self->{user};
101 0           $auth = $self->{auth};
102 0           last SWITCH;};
103 0 0         /Oracle/ && do {
104 0 0         $ENV{'NLS_DATE_FORMAT'} = $self->{datestyle} if $self->{datestyle};
105 0           $auth = '';
106 0 0         $user = $self->{auth} ? $self->{user}.'/'.$self->{auth} :
107             $self->{user};
108 0           last SWITCH;};
109 0 0         /Informix/ && do {
110 0 0         $ENV{'DBDATE'} = $self->{datestyle} if $self->{datestyle};
111 0           $user = $self->{user};
112 0           $auth = $self->{auth};
113 0           last SWITCH;};
114 0 0         /DB2/ && do {
115 0 0         $ENV{'DB2CODEPAGE'} = $self->{codepage} if $self->{codepage};
116 0           $user = $self->{user};
117 0           $auth = $self->{auth};
118 0           last SWITCH;};
119 0 0         /mysql/ && do {
120 0           $user = $self->{user};
121 0           $auth = $self->{auth};
122 0           last SWITCH;};
123 0 0         /Sybase/ && do {
124 0           $user = $self->{user};
125 0           $auth = $self->{auth};
126 0           last SWITCH;};
127 0 0         /mssql/ && do {
128 0           $user = $self->{user};
129 0           $auth = $self->{auth};
130 0           last SWITCH;};
131 0 0         /Solid/ && do {
132 0           $user = $self->{user};
133 0           $auth = $self->{auth};
134 0           last SWITCH;};
135             # Default (not supported)
136 0           $Derror_message = "MODULE ERROR: DBD driver not supported";
137 0           return -5;
138             }
139 0           $self->{conn} = DBI->connect($self->{driver}, $user, $auth, \%attr);
140 0           $self->{driver} = $orig_driver;
141 0           $Dcmdstatus = $DBI::state;
142 0           $Dsqlstatus = $DBI::err;
143 0           $Derror_message = $DBI::errstr;
144 0 0 0       $self->_trace() if ! $self->{conn} and $self->{trace};
145 0 0         return undef if ! $self->{conn};
146 0           return $self;
147              
148             } # sub new()
149            
150             #########################################################################
151             sub close {
152              
153 0     0 1   my $self = shift;
154              
155 0 0         $self->transaction_end(1) if $self->{transaction};
156 0 0         $self->{conn}->disconnect if $self->{conn};
157              
158             } # sub close
159              
160             #########################################################################
161             sub check {
162            
163 0     0 1   my $self = shift;
164              
165 0 0         return -1 if ! $self->{conn};
166 0 0         return 0 if $self->{conn}->ping;
167 0           return -1;
168              
169             } # END check
170              
171              
172             ##########################################################################
173             sub transaction_begin {
174              
175 0     0 1   my $self = shift;
176 0           my $type_f = shift;
177 0 0         if (! defined $type_f) {
178 0           $type_f = 1;
179             }
180              
181 0           my $result = $self->transaction_end($type_f);
182 0 0         $self->{transaction} = 1 if $result > 0;
183              
184 0           return $result;
185              
186             } # transaction_begin
187              
188             ##########################################################################
189             sub transaction_end {
190              
191 0     0 1   my $self = shift;
192 0           my $type_f = shift;
193 0 0         if (! defined $type_f) {
194 0           $type_f = 1;
195             }
196 0           my $result;
197              
198 0 0         if (! $self->{conn}) {
199 0           $Derror_message = "MODULE ERROR: DB connect not exists";
200 0           return -2;
201             }
202 0 0         if ($self->{autocommit}) {
203 0           $Derror_message = "MODULE ERROR: Autocommit ON";
204 0           return -1;
205             }
206              
207 0 0 0       if ($type_f or ! $self->{transaction}) {
208 0 0         if ($self->{driver} ne 'Oracle') {
209 0           $result = $self->{conn}->commit;
210             }
211             else {
212 0           $result = $self->{conn}->do('COMMIT');
213             }
214             }
215             else {
216 0 0         if ($self->{driver} ne 'Oracle') {
217 0 0         $result = $self->{conn}->rollback if ! $type_f;
218             }
219             else {
220 0           $result = $self->{conn}->do('ROLLBACK');
221             }
222             }
223 0           $self->{transaction} = 0;
224 0 0         $self->{cursors} = {} if $self->{close_curs};
225              
226 0 0         return 1 if $result;
227 0           return 0;
228              
229             } # transaction_end
230              
231             #########################################################################
232             sub select {
233              
234 0     0 1   my $self = shift;
235 0           my $sql_command = shift;
236 0           my @ret_array;
237              
238 0 0         if (! defined $sql_command) {
239 0           $Derror_message = "MODULE ERROR: SQL command not defined";
240 0           return (-2);
241             }
242 0 0         if (! $self->{conn}) {
243 0           $Derror_message = "MODULE ERROR: DB connect not exists";
244 0           return (-3);
245             }
246              
247 0           $self->_stat_start('SELECT', $sql_command, undef);
248              
249 0           $Dstr_command = $sql_command;
250 0           my $statement = $self->{conn}->prepare($sql_command);
251 0 0         if (! $statement ) {
252 0           $Dcmdstatus = $self->{conn}->state;
253 0           $Dsqlstatus = $self->{conn}->err;
254 0           $Derror_message = $self->{conn}->errstr;
255 0 0         $self->_trace() if $self->{trace};
256 0           $self->_stat_end('ERROR');
257 0           return (-1);
258             }
259 0           my $result = $statement->execute;
260 0           $Dcmdstatus = $statement->state;
261 0           $Dsqlstatus = $statement->err;
262 0           $Derror_message = $statement->errstr;
263 0 0         if ($self->{driver} eq 'mssql') {
264 0           $result = !$self->{conn}->err;
265             }
266 0 0         if (! $result ) {
267             # SQL command failed
268 0 0         $self->_trace() if $self->{trace};
269 0 0         $self->transaction_end(0) if ! $self->{transaction};
270 0           $self->_stat_end('ERROR');
271 0           return (-1);
272             }
273 0           my $ret_rows = $statement->rows;
274              
275 0           @ret_array = $statement->fetchrow_array;
276 0           $ret_rows = 1 if scalar @ret_array and
277 0 0 0       grep {$self->{driver} eq $_} ('Oracle','Informix','mssql','DB2','Solid');
278 0 0 0       $ret_rows = 0 if $#ret_array < 0 and grep {$self->{driver} eq $_} ('mssql', 'DB2', 'Solid') and
  0   0        
279             !$statement->err;
280 0 0 0       if ($#ret_array < 0 and ($statement->err or $ret_rows)) {
      0        
281 0           $Dcmdstatus = $statement->state;
282 0           $Dsqlstatus = $statement->err;
283 0           $Derror_message = $statement->errstr;
284 0 0         $self->_trace() if $self->{trace};
285 0 0         $self->transaction_end(0) if ! $self->{transaction};
286 0           $self->_stat_end('ERROR');
287 0           return (-1);
288             }
289              
290             # convert data for MS SQL
291 0 0         if ($self->{driver} eq 'mssql') {
292 0           @ret_array = map { y/\x9a\x9e\x8a\x8e/¹¾©®/; $_ } @ret_array;
  0            
  0            
293             }
294             # correct numbers for Informix
295 0 0 0       if ($self->{driver} eq 'Informix' and $self->{imix_number_correct}) {
296 0           my @types = @{$statement->{TYPE}};
  0            
297 0           for (my $i=0; $i<=$#ret_array; $i++) {
298 0 0         next if $types[$i] != DBI::SQL_DECIMAL;
299 0 0         next if !defined $ret_array[$i];
300 0           $ret_array[$i] += 0;
301             }
302             }
303              
304 0           $self->_stat_end('OK');
305 0           return ($ret_rows, @ret_array);
306              
307             } # select
308            
309             #########################################################################
310             sub open_cursor {
311              
312 0     0 1   my $self = shift;
313 0           my $cursor_name = shift;
314              
315 0 0         if (!$self->{conn}) {
316 0           $Derror_message = "MODULE ERROR: DB connect not exists";
317 0           return -3;
318             }
319              
320 0           my $sql_command = shift;
321 0 0         if (! defined $sql_command) {
322 0           $Derror_message = "MODULE ERROR: SQL command not defined";
323 0           return -2;
324             }
325              
326 0           my $cursortype = $self->{cursor_type};
327 0           my $result;
328             my $statement;
329 0           my $statement_name = undef;
330 0           my @bind_values;
331              
332 0 0         if (exists $self->{statements}->{$self->{app}.$sql_command}) {
333             # cursor from prepared statement
334 0           $statement_name = $sql_command;
335 0           $statement_name = $self->{app} . $statement_name;
336 0           $Dstr_command = $self->{statements}->{$statement_name}->[5];
337 0 0         return -20
338             if !$self->{statements}->{$statement_name}->[3]; # not is_select
339 0           $cursortype = 'INTERNAL';
340 0           $statement = $self->{statements}->{$statement_name}->[0];
341 0 0         if ($#_ < 0 ) {
342 0 0 0       return -21 if ! $self->{statements}->{$statement_name}->[2]
343             and $self->{statements}->{$statement_name}->[1];
344 0           @bind_values = @{$self->{statements}->{$statement_name}->[4]};
  0            
345             }
346             else {
347 0           for (1 .. $self->{statements}->{$statement_name}->[1]) {
348 0           push @bind_values, shift;
349             }
350             }
351 0 0         return -22 if $self->{statements}->{$statement_name}->[1] !=
352             scalar @bind_values;
353 0           $self->{statements}->{$statement_name}->[4] = \@bind_values;
354              
355 0           $self->_stat_start('CURSOR_STATEMENT', $Dstr_command, \@bind_values, $sql_command);
356              
357             # MS SQL
358 0 0         if ($self->{driver} eq 'mssql') {
359 0           my $sql = $self->_replace_values($self->{statements}->{$statement_name}->[5],
360             @bind_values);
361 0           $statement = $self->{conn}->prepare($sql);
362 0 0         if (! $statement ) {
363 0           $Dcmdstatus = $self->{conn}->state;
364 0           $Dsqlstatus = $self->{conn}->err;
365 0           $Derror_message = $self->{conn}->errstr;
366 0 0         $self->_trace(@bind_values) if $self->{trace};
367 0           $self->_stat_end('ERROR');
368 0           return -1;
369             }
370 0           $result = $statement->execute;
371             }
372             else {
373 0           $result = $statement->execute(@bind_values);
374             }
375             }
376             else {
377 0 0         if ($#_ >= 0) {
378 0           $cursortype = shift;
379             }
380 0 0         return -23 if $cursortype !~ /^INTERNAL|^EXTERNAL/;
381 0 0         $cursortype = 'INTERNAL' if $self->{driver} eq 'mssql';
382              
383 0           $Dstr_command = $sql_command;
384 0           $self->_stat_start('CURSOR_SQL', $Dstr_command, \@bind_values);
385              
386 0 0         if ( exists $self->{cursors}->{$cursor_name} ) {
387 0           undef $self->{cursors}->{$cursor_name};
388             }
389              
390 0           $statement = $self->{conn}->prepare($sql_command);
391 0 0         if (! $statement ) {
392 0           $Dcmdstatus = $self->{conn}->state;
393 0           $Dsqlstatus = $self->{conn}->err;
394 0           $Derror_message = $self->{conn}->errstr;
395 0 0         $self->_trace(@bind_values) if $self->{trace};
396 0           $self->_stat_end('ERROR');
397 0           return -1;
398             }
399 0           $result = $statement->execute;
400             }
401 0 0         $Dcmdstatus = $statement ? $statement->state : $self->{conn}->state;
402 0 0         $Dsqlstatus = $statement ? $statement->err : $self->{conn}->err;
403 0 0         $Derror_message = $statement ? $statement->errstr : $self->{conn}->errstr;
404              
405             # Sybase driver returns -1 in case of success (?!)
406 0 0 0       if (grep {$self->{driver} eq $_} ('mssql','DB2', 'Solid')
  0   0        
407             and !$Derror_message and $result eq '-1') {
408 0           $result = 1;
409             }
410              
411 0 0         if (! $result ) {
412             # SQL command failed
413 0 0         $self->_trace(@bind_values) if $self->{trace};
414 0 0         $self->transaction_end(0) if ! $self->{transaction};
415 0           $self->_stat_end('ERROR');
416 0           return -1;
417             }
418 0 0         if (defined $statement_name) {
419 0           $self->{statements}->{$statement_name}->[2]++;
420             }
421 0           my $ret_rows = $statement->rows;
422 0 0 0       if ($self->{driver} eq 'Oracle' and ! $ret_rows) {
423 0           $ret_rows = '0E0';
424             }
425 0 0 0       if (grep {$self->{driver} eq $_} ('mssql', 'DB2', 'Solid') and $ret_rows < 0) {
  0            
426 0           $ret_rows = '0E0';
427             }
428 0           my $cur_ref;
429              
430 0 0         if ( $ret_rows >= 0 ) {
431 0 0         if ($cursortype eq 'INTERNAL') {
432 0           $cur_ref = $statement->fetchall_arrayref;
433 0           $ret_rows = scalar @$cur_ref;
434 0 0 0       if (! $cur_ref and ($statement->err or $ret_rows)) {
      0        
435 0           $Dcmdstatus = $statement->state;
436 0           $Dsqlstatus = $statement->err;
437 0           $Derror_message = $statement->errstr;
438 0 0         $self->_trace(@bind_values) if $self->{trace};
439 0 0         $self->transaction_end(0) if ! $self->{transaction};
440 0           $self->_stat_end('ERROR');
441 0           return -1;
442             }
443             else {
444 0           $self->{cursors}->{$cursor_name} = [$cur_ref, $ret_rows, -1,
445             $cursortype, $Dstr_command];
446             }
447             }
448             else {
449 0 0 0       if ($self->{driver} eq 'Informix' and ! $ret_rows) {
450 0           $ret_rows = 1;
451             }
452 0           $self->{cursors}->{$cursor_name} = [$statement, $ret_rows, -1,
453             $cursortype, $Dstr_command];
454             }
455             }
456 0           $self->_stat_end('OK');
457 0           return $ret_rows;
458              
459             } # open_cursor
460              
461             #########################################################################
462             sub fetch_cursor {
463              
464 0     0 1   my $self = shift;
465 0           my @ret_array;
466             my $result;
467 0           my $num_row;
468 0           my @tmp_array;
469 0           my $cursor_name = shift;
470              
471 0 0         if (! defined $cursor_name) {
472 0           $Derror_message = "MODULE ERROR: cursor not defined";
473 0           return (-2);
474             }
475 0 0         if (! $self->{conn}) {
476 0           $Derror_message = "MODULE ERROR: DB connect not exists";
477 0           return (-4);
478             }
479              
480 0 0 0       if ( not exists $self->{cursors}->{$cursor_name}
481             or not defined $self->{cursors}->{$cursor_name}) {
482 0           $Derror_message = "MODULE ERROR: cursor ($cursor_name) not exists";
483 0           return (-3);
484             }
485 0           $Dstr_command = $self->{cursors}->{$cursor_name}->[4];
486 0           $ret_array[0] = $self->{cursors}->{$cursor_name}->[1];
487 0 0         if ($self->{cursors}->{$cursor_name}->[3] eq 'INTERNAL') {
488 0           $num_row = $self->{cursors}->{$cursor_name}->[2] + 1;
489 0 0         if ( $#_ >= 0 ) {
490 0           $num_row = shift;
491             }
492 0 0         $num_row = $self->{cursors}->{$cursor_name}->[1] - 1
493             if $num_row =~ /^LAST/;
494 0 0         $num_row = 0 if $num_row =~ /^FIRST/;
495 0 0         if ( $num_row > $self->{cursors}->{$cursor_name}->[1] - 1 ) {
496 0           return (0);
497             }
498              
499 0 0         push @ret_array, @{$self->{cursors}->{$cursor_name}->[0]->[$num_row]}
  0            
500             if $ret_array[0];
501             }
502             else {
503 0           $num_row = $self->{cursors}->{$cursor_name}->[2] + 1;
504 0           @tmp_array = $self->{cursors}->{$cursor_name}->[0]->fetchrow_array;
505 0 0         if (! @tmp_array) {
506 0           return (0);
507             }
508 0           push @ret_array, @tmp_array;
509             }
510 0 0         if ($num_row >= $self->{cursors}->{$cursor_name}->[1]) {
511 0           $self->{cursors}->{$cursor_name}->[2] = -1;
512             }
513             else {
514 0           $self->{cursors}->{$cursor_name}->[2] = $num_row;
515             }
516              
517 0 0         if ($self->{driver} eq 'Informix') {
518 0           for (my $i=0; $i<=$#ret_array; $i++) {
519 0           $ret_array[$i] =~ s/[ ]*$//g;
520             }
521             }
522              
523             # convert data for MS SQL
524 0 0         if ($self->{driver} eq 'mssql') {
525 0           @ret_array = map { y/\x9a\x9e\x8a\x8e/¹¾©®/; $_ } @ret_array;
  0            
  0            
526             }
527             # correct numbers for Informix
528 0 0 0       if ($self->{driver} eq 'Informix' and $self->{imix_number_correct}) {
529 0           my @types = @{$self->{cursors}->{$cursor_name}->[5]};
  0            
530 0           for (my $i=1; $i<=$#ret_array; $i++) {
531 0 0         next if $types[$i-1] != DBI::SQL_DECIMAL;
532 0 0         next if !defined $ret_array[$i];
533 0           $ret_array[$i] += 0;
534             }
535             }
536              
537 0           return @ret_array;
538              
539             } # fetch_cursor
540              
541             #########################################################################
542             sub close_cursor {
543              
544 0     0 1   my $self = shift;
545 0           my $cursor_name = shift;
546              
547 0 0         if (! defined $cursor_name) {
548 0           $Derror_message = "MODULE ERROR: cursor not defined";
549 0           return -2;
550             }
551 0 0         if (! $self->{conn}) {
552 0           $Derror_message = "MODULE ERROR: DB connect not exists";
553 0           return -4;
554             }
555              
556 0 0         if ( not exists $self->{cursors}->{$cursor_name} ) {
557 0           $Derror_message = "MODULE ERROR: cursor ($cursor_name) not exists";
558 0           return -3;
559             }
560             #$Dstr_command = $self->{cursors}->{$cursor_name}->[4];
561 0           delete $self->{cursors}->{$cursor_name};
562              
563 0           return 0;
564              
565             } # close_cursor
566              
567             #########################################################################
568             sub exists_cursor {
569            
570 0     0 1   my $self = shift;
571 0           my $cursor_name = shift;
572            
573 0 0         return 0 if ! $cursor_name;
574 0 0 0       if ( not exists $self->{cursors}->{$cursor_name}
575             or not defined $self->{cursors}->{$cursor_name}) {
576 0           $Derror_message = "MODULE ERROR: cursor ($cursor_name) not exists";
577 0           return 0;
578             }
579 0           return 1;
580              
581             } # END exists_cursor
582              
583              
584             #########################################################################
585             sub open_statement {
586              
587 0     0 1   my $self = shift;
588 0           my $statement_name = shift;
589 0           $statement_name = $self->{app} . $statement_name;
590              
591 0 0         if (! defined $statement_name) {
592 0           $Derror_message = "MODULE ERROR: statement not defined";
593 0           return -2;
594             }
595              
596 0           my $sql_command = shift;
597              
598 0 0         if (! $self->{conn}) {
599 0           $Derror_message = "MODULE ERROR: DB connect not exists";
600 0           return -4;
601             }
602              
603 0 0         if (! defined $sql_command) {
604 0           $Derror_message = "MODULE ERROR: SQL command not defined";
605 0           return -2;
606             }
607              
608 0 0         my $is_select = 1 if uc($sql_command) =~ /^[ \n]*SELECT[ \n]/;
609              
610 0           my $bind_re = '\?\w?|!';
611 0           my @sqlc_tmp = $sql_command =~ /$bind_re/g;
612 0           my $number_bval = scalar @sqlc_tmp;
613 0           $sql_command =~ s/$bind_re/?/g;
614 0 0         if ($#_ >= 0) {
615 0 0         if ($number_bval != shift) {
616 0           $Derror_message = "MODULE ERROR: Number of the bind value not matched";
617 0           return -3;
618             }
619             }
620              
621 0 0         if ( exists $self->{statements}->{$statement_name} ) {
622 0           undef $self->{statements}->{$statement_name};
623             }
624              
625             # MS SQL cannot prepare statements
626 0 0         if ($self->{driver} eq 'mssql') {
627 0           $self->{statements}->{$statement_name} =
628             [undef, $number_bval, 0, $is_select, [], $sql_command];
629 0           return $number_bval;
630             }
631              
632 0           my $statement = $self->{conn}->prepare($sql_command);
633 0           $Dstr_command = $sql_command;
634 0 0         if (! $statement ) {
635 0           $Dcmdstatus = $self->{conn}->state;
636 0           $Dsqlstatus = $self->{conn}->err;
637 0           $Derror_message = $self->{conn}->errstr;
638 0 0         $self->_trace() if $self->{trace};
639 0           return -1;
640             }
641              
642 0 0         if ($self->{driver} eq 'Oracle') {
643 0           for (my $i = 0; $i < scalar @sqlc_tmp; $i++) {
644             # BLOB
645 0 0 0       if ($sqlc_tmp[$i] eq '!' or uc($sqlc_tmp[$i]) eq '?B') {
646 0 0         return if ! $statement->bind_param($i + 1, undef,
647             {ora_type => 113});
648             }
649             # CLOB
650 0 0         if (uc($sqlc_tmp[$i]) eq '?C') {
651 0 0         return if ! $statement->bind_param($i + 1, undef,
652             {ora_type => 112});
653             }
654             }
655             }
656              
657 0           $self->{statements}->{$statement_name} =
658             [$statement, $number_bval, 0, $is_select, [], $sql_command];
659 0           return $number_bval;
660              
661             } # open_statement
662              
663             #########################################################################
664             sub perform_statement {
665              
666 0     0 1   my $self = shift;
667 0           my @ret_array;
668             my $result;
669 0           my $num_rows;
670 0           my @tmp_array;
671 0           my @bind_values;
672 0           my $statement;
673 0           my $statement_name = shift;
674 0           $statement_name = $self->{app} . $statement_name;
675              
676 0 0         if (! defined $statement_name) {
677 0           $Derror_message = "MODULE ERROR: statement name not defined";
678 0           return (-2);
679             }
680              
681 0 0         if (! $self->{conn}) {
682 0           $Derror_message = "MODULE ERROR: DB connect not exists";
683 0           return (-4);
684             }
685              
686 0 0 0       if ( not exists $self->{statements}->{$statement_name}
687             or not defined $self->{statements}->{$statement_name}) {
688 0 0         $self->_trace_msg("Statement '$statement_name' does not exists!")
689             if $self->{trace};
690 0           $Derror_message = "MODULE ERROR: Statement ($statement_name) not exists";
691 0           return (-3);
692             }
693 0           $Dstr_command = $self->{statements}->{$statement_name}->[5];
694 0           $statement = $self->{statements}->{$statement_name}->[0];
695 0 0         if ($#_ < 0 ) {
696 0 0 0       if (! $self->{statements}->{$statement_name}->[2]
697             and $self->{statements}->{$statement_name}->[1]) {
698 0           $Derror_message = "MODULE ERROR: Number of the bind value not matched";
699 0           return -2;
700             }
701 0           @bind_values = @{$self->{statements}->{$statement_name}->[4]};
  0            
702             }
703             else {
704 0           for (1 .. $self->{statements}->{$statement_name}->[1]) {
705 0           push @bind_values, shift;
706             }
707             }
708            
709 0 0         if ($self->{statements}->{$statement_name}->[1] != scalar @bind_values) {
710 0           $Derror_message = "MODULE ERROR: Number of the bind value not matched";
711 0           return -2;
712             }
713 0           $self->{statements}->{$statement_name}->[4] = \@bind_values;
714              
715 0           $self->_stat_start('PERFORM', $Dstr_command, \@bind_values, $statement_name);
716            
717             # MS SQL
718 0 0         if ($self->{driver} eq 'mssql') {
719             # replace values
720 0           my $sql = $self->_replace_values($self->{statements}->{$statement_name}->[5],
721             @bind_values);
722 0 0         if ($self->{statements}->{$statement_name}->[3]) { # is_select
723 0           return $self->select($sql);
724             }
725             else {
726 0           return $self->command($sql);
727             }
728             }
729            
730 0           $result = $statement->execute(@bind_values);
731 0           $Dcmdstatus = $statement->state;
732 0           $Dsqlstatus = $statement->err;
733 0           $Derror_message = $statement->errstr;
734 0 0         if (! $result ) {
735             # SQL command failed
736 0 0         $self->_trace(@bind_values) if $self->{trace};
737 0 0         $self->transaction_end(0) if ! $self->{transaction};
738 0           $self->_stat_end('ERROR');
739 0           return (-1);
740             }
741 0           $num_rows = $statement->rows;
742              
743 0 0         if ($self->{statements}->{$statement_name}->[3]) { # is_select
744 0           @ret_array = $statement->fetchrow_array;
745 0 0 0       if (grep {$self->{driver} eq $_} ('DB2', 'Solid', 'Oracle', 'Informix')) {
  0 0 0        
746 0 0         if (scalar @ret_array) {
    0          
747 0           $num_rows = 1
748             }
749             elsif ($statement->err) {
750 0           $Dcmdstatus = $statement->state;
751 0           $Dsqlstatus = $statement->err;
752 0           $Derror_message = $statement->errstr;
753 0 0         $self->_trace(@bind_values) if $self->{trace};
754 0 0         $self->transaction_end(0) if ! $self->{transaction};
755 0           $self->_stat_end('ERROR');
756 0           return (-1);
757             }
758             else {
759 0           $num_rows = 0;
760             }
761 0           $statement->finish;
762             }
763             elsif ($#ret_array < 0 and ($statement->err or $num_rows)) {
764 0           $Dcmdstatus = $statement->state;
765 0           $Dsqlstatus = $statement->err;
766 0           $Derror_message = $statement->errstr;
767 0 0         $self->_trace(@bind_values) if $self->{trace};
768 0 0         $self->transaction_end(0) if ! $self->{transaction};
769 0           $self->_stat_end('ERROR');
770 0           return (-1);
771             }
772             }
773 0           $self->{statements}->{$statement_name}->[2]++;
774              
775 0 0         if ($self->{driver} eq 'Informix') {
776 0           for (my $i=0; $i<=$#ret_array; $i++) {
777 0           $ret_array[$i] =~ s/[ ]*$//g;
778             }
779             }
780              
781             # Transakci automaticky neukoncuji, pokud se jedna o select!!!
782             # JS
783             #Dtransaction_end($sid, 1) if ! $Dtransaction[$sid];
784 0           $self->_stat_end('OK');
785 0 0         if ($self->{statements}->{$statement_name}->[3]) { # is_select
786 0 0 0       if ($self->{driver} eq 'Informix' and $self->{imix_number_correct}) {
787 0           my @types = @{$statement->{TYPE}};
  0            
788 0           for (my $i=0; $i<=$#ret_array; $i++) {
789 0 0         next if $types[$i] != DBI::SQL_DECIMAL;
790 0 0         next if !defined $ret_array[$i];
791 0           $ret_array[$i] += 0;
792             }
793             }
794 0           return ($num_rows, @ret_array);
795             }
796             else {
797 0 0         $self->transaction_end(1) if ! $self->{transaction};
798 0           return($num_rows);
799             }
800              
801             } # perform_statement
802              
803              
804             #########################################################################
805             sub close_statement {
806              
807 0     0 1   my $self = shift;
808 0           my $statement_name = shift;
809 0           $statement_name = $self->{app} . $statement_name;
810              
811 0 0         if (! defined $statement_name) {
812 0           $Derror_message = "MODULE ERROR: statement name not defined";
813 0           return -2;
814             }
815              
816 0 0         if (! $self->{conn}) {
817 0           $Derror_message = "MODULE ERROR: DB connect not exists";
818 0           return -4;
819             }
820              
821 0 0         if ( not exists $self->{statements}->{$statement_name} ) {
822 0           $Derror_message = "MODULE ERROR: Statement ($statement_name) not exists";
823 0           return -3;
824             }
825              
826             #$Dstr_command = $self->{statements}->{$statement_name}->[5];
827 0           delete $self->{statements}->{$statement_name};
828              
829 0           return 0;
830              
831             } # close_statement
832              
833             #########################################################################
834             sub exists_statement {
835              
836 0     0 1   my $self = shift;
837 0           my $statement_name = shift;
838 0           $statement_name = $self->{app} . $statement_name;
839            
840 0 0         return 0 if ! defined $statement_name;
841 0 0         if ( not exists $self->{statements}->{$statement_name} ) {
842 0           $Derror_message = "MODULE ERROR: Statement ($statement_name) not exists";
843 0           return 0;
844             }
845 0           return 1;
846             } # END exists_statement
847              
848             #########################################################################
849             sub insert {
850              
851 0     0 1   my $self = shift;
852 0           my $insert_command = shift;
853              
854 0 0         if (! defined $insert_command) {
855 0           $Derror_message = "MODULE ERROR: INSERT command not defined";
856 0           return -2;
857             }
858              
859 0 0         if (! $self->{conn}) {
860 0           $Derror_message = "MODULE ERROR: DB connect not exists";
861 0           return -3;
862             }
863              
864              
865 0           $self->_stat_start('INSERT', $insert_command, undef);
866              
867 0           $Dstr_command = $insert_command;
868 0           my $result = $self->{conn}->do($insert_command);
869 0 0         if ($self->{driver} eq 'mssql') {
870 0           $result = !$self->{conn}->err;
871             }
872              
873 0           $Dsqlstatus = $self->{conn}->err;
874 0           $Dcmdstatus = $self->{conn}->state;
875 0           $Derror_message = $self->{conn}->errstr;
876 0 0         if (! $result) {
877 0 0         $self->_trace() if $self->{trace};
878 0 0         $self->transaction_end(0) if ! $self->{transaction};
879 0           $self->_stat_end('ERROR');
880 0           return -1;
881             }
882 0 0         $self->transaction_end(1) if ! $self->{transaction};
883 0           $self->_stat_end('OK');
884 0           return $result;
885              
886             } # insert
887              
888             #########################################################################
889             sub delete {
890              
891 0     0 1   my $self = shift;
892 0           my $delete_command = shift;
893              
894 0 0         if (! defined $delete_command) {
895 0           $Derror_message = "MODULE ERROR: DELETE command not defined";
896 0           return -2;
897             }
898              
899 0 0         if (! $self->{conn}) {
900 0           $Derror_message = "MODULE ERROR: DB connect not exists";
901 0           return -3;
902             }
903              
904 0           $self->_stat_start('DELETE', $delete_command, undef);
905              
906 0           $Dstr_command = $delete_command;
907 0           my $result = $self->{conn}->do($delete_command);
908 0 0         if ($self->{driver} eq 'mssql') {
909 0           $result = !$self->{conn}->err;
910             }
911 0 0 0       $result = 1 if $self->{driver} eq 'mysql' && $result eq '0E0';
912              
913 0           $Dsqlstatus = $self->{conn}->err;
914 0           $Dcmdstatus = $self->{conn}->state;
915 0           $Derror_message = $self->{conn}->errstr;
916 0 0         if (! $result) {
917 0 0         $self->_trace() if $self->{trace};
918 0 0         $self->transaction_end(0) if ! $self->{transaction};
919 0           $self->_stat_end('ERROR');
920 0           return -1;
921             }
922 0 0         $self->transaction_end(1) if ! $self->{transaction};
923 0           $self->_stat_end('OK');
924 0           return $result;
925              
926             } # delete
927              
928             #########################################################################
929             sub update {
930              
931 0     0 1   my $self = shift;
932 0           my $update_command = shift;
933              
934 0 0         if (! defined $update_command) {
935 0           $Derror_message = "MODULE ERROR: UPDATE command not defined";
936 0           return -2;
937             }
938              
939 0 0         if (! $self->{conn}) {
940 0           $Derror_message = "MODULE ERROR: DB connect not exists";
941 0           return -3;
942             }
943              
944 0           $self->_stat_start('UPDATE', $update_command, undef);
945              
946 0           $Dstr_command = $update_command;
947 0           my $result = $self->{conn}->do($update_command);
948 0 0         if ($self->{driver} eq 'mssql') {
949 0           $result = !$self->{conn}->err;
950             }
951              
952 0 0 0       $result = 1 if $self->{driver} eq 'mysql' && $result eq '0E0';
953              
954 0           $Dsqlstatus = $self->{conn}->err;
955 0           $Dcmdstatus = $self->{conn}->state;
956 0           $Derror_message = $self->{conn}->errstr;
957 0 0         if (! $result) {
958 0 0         $self->_trace() if $self->{trace};
959 0 0         $self->transaction_end(0) if ! $self->{transaction};
960 0           $self->_stat_end('ERROR');
961 0           return -1;
962             }
963 0 0         $self->transaction_end(1) if ! $self->{transaction};
964 0           $self->_stat_end('OK');
965 0           return $result;
966              
967             } # update
968              
969             #########################################################################
970             sub command {
971              
972 0     0 1   my $self = shift;
973 0           my $sql_command = shift;
974              
975 0 0         if (! defined $sql_command) {
976 0           $Derror_message = "MODULE ERROR: SQL command not defined";
977 0           return -2;
978             }
979              
980 0 0         if (! $self->{conn}) {
981 0           $Derror_message = "MODULE ERROR: DB connect not exists";
982 0           return -3;
983             }
984              
985 0           $self->_stat_start('COMMAND', $sql_command, undef);
986              
987 0           $Dstr_command = $sql_command;
988 0           my $result = $self->{conn}->do($sql_command);
989 0 0         if ($self->{driver} eq 'mssql') {
990 0           $result = !$self->{conn}->err;
991             }
992              
993 0           $Dsqlstatus = $self->{conn}->err;
994 0           $Dcmdstatus = $self->{conn}->state;
995 0           $Derror_message = $self->{conn}->errstr;
996 0 0         if (! $result) {
997 0 0         $self->_trace() if $self->{trace};
998 0 0         $self->transaction_end(0) if ! $self->{transaction};
999 0           $self->_stat_end('ERROR');
1000 0           return -1;
1001             }
1002 0 0         $self->transaction_end(1) if ! $self->{transaction};
1003 0           $self->_stat_end('OK');
1004 0           return 1;
1005              
1006             } # command
1007              
1008             #########################################################################
1009             sub func {
1010              
1011 0     0 1   my $self = shift;
1012              
1013 0           my $result = $self->{conn}->func(@_);
1014 0           $Dsqlstatus = $self->{conn}->err;
1015 0           $Dcmdstatus = $self->{conn}->state;
1016 0           $Derror_message = $self->{conn}->errstr;
1017 0 0 0       $self->_trace() if $self->{trace} and ! $result;
1018              
1019 0           return $result;
1020            
1021             } # func
1022              
1023             #########################################################################
1024             sub const {
1025              
1026 0     0 1   my $self = shift;
1027 0           my $const_name = shift;
1028 0           my $value = shift;
1029            
1030 0 0         if (defined $value) {
1031 0           $self->{conn}->{$const_name} = $value;
1032             }
1033              
1034 0           return $self->{conn}->{$const_name};
1035            
1036             } # const
1037              
1038             #########################################################################
1039             sub nextval {
1040              
1041 0     0 1   my $self = shift;
1042 0           my $seq_name = shift;
1043 0           my @sqlresult;
1044              
1045 0 0         if (! defined $seq_name) {
1046 0           $Derror_message = "MODULE ERROR: Sequence name not defined";
1047 0           return -2;
1048             }
1049              
1050 0 0         if (! $self->{conn}) {
1051 0           $Derror_message = "MODULE ERROR: DB connect not exists";
1052 0           return -3;
1053             }
1054              
1055 0 0 0       if ($self->{driver} eq 'Pg') {
    0          
    0          
    0          
    0          
1056 0           @sqlresult = $self->select("select nextval('$seq_name')");
1057 0 0         return -1 if $sqlresult[0] < 1;
1058 0           return $sqlresult[1];
1059             }
1060             elsif ($self->{use_sequences} && $self->{driver} eq 'Informix') {
1061 0           @sqlresult = $self->select("select $seq_name.nextval from kdb_sequences ".
1062             "where sequence_name = 'dual'");
1063 0 0         return -1 if $sqlresult[0] < 1;
1064 0           return $sqlresult[1];
1065             }
1066             elsif ($self->{driver} eq 'Oracle') {
1067 0           @sqlresult = $self->select("select $seq_name.nextval from dual");
1068 0 0         return -1 if $sqlresult[0] < 1;
1069 0           return $sqlresult[1];
1070             }
1071 0           elsif ($self->{driver} eq 'Solid') {
1072 0           @sqlresult = $self->select("select $seq_name.nextval");
1073 0 0         return -1 if $sqlresult[0] < 1;
1074 0           return $sqlresult[1];
1075             }
1076             elsif (grep {$self->{driver} eq $_} ('Informix', 'mssql', 'DB2', 'mysql')) {
1077 0           my $trans = $self->{transaction};
1078 0           my $sqlresult = 0;
1079 0           my $ret_val;
1080 0 0         $trans = 1 if $self->{autocommit};
1081 0 0         $sqlresult = $self->transaction_begin(1) if ! $trans;
1082 0 0         return -1 if $sqlresult < 0;
1083 0           $sqlresult = $self->open_cursor('Kdb-CUR_SEQ',
1084             "select init_v, step_v, finish_v, act_v ".
1085             "from kdb_sequences where ".
1086             "sequence_name = '$seq_name'");
1087 0 0         if ($sqlresult < 0) {
1088 0 0         $self->transaction_end(0) if ! $trans;
1089 0           return -1;
1090             }
1091 0           @sqlresult = $self->fetch_cursor('Kdb-CUR_SEQ');
1092 0 0         if ($sqlresult[0] < 1) {
1093 0 0         $self->transaction_end(0) if ! $trans;
1094 0           return -1;
1095             }
1096 0           $self->close_cursor('Kdb-CUR_SEQ');
1097 0 0         if ($sqlresult[4] == 0) {
    0          
1098 0           $ret_val = $sqlresult[1];
1099             }
1100             elsif (($sqlresult[4] + $sqlresult[2]) <= $sqlresult[3]) {
1101 0           $ret_val = $sqlresult[4] + $sqlresult[2];
1102             }
1103             else {
1104 0           $ret_val = 0;
1105             }
1106 0 0         if ($ret_val) {
1107 0           $sqlresult = $self->update("update kdb_sequences set ".
1108             "act_v = $ret_val ".
1109             "where sequence_name = '$seq_name'");
1110 0 0         if ($sqlresult < 0) {
1111 0 0         $self->transaction_end(0) if ! $trans;
1112 0           return -1;
1113             }
1114             }
1115 0 0         $self->transaction_end(1) if ! $trans;
1116 0           return $ret_val;
1117             }
1118              
1119 0           $Derror_message = "MODULE ERROR: DBD driver not supported";
1120 0           return -2;
1121              
1122             } # nextval
1123              
1124             #########################################################################
1125             sub quote {
1126              
1127 0     0 1   my $self = shift;
1128 0           my $string;
1129 0           my @retstr = ();
1130              
1131 0           for (@_) {
1132 0           push @retstr, $self->{conn}->quote($_);
1133             }
1134              
1135 0           return @retstr;
1136              
1137             } # quote
1138              
1139             #########################################################################
1140             sub date2db {
1141              
1142 0     0 1   my $self = shift;
1143 0           my $type = shift;
1144 0           my ($year, $mon, $day, $hour, $min, $sec);
1145 0           my ($d, $t);
1146 0           my ($idatetime, $odatetime);
1147              
1148 0 0         if (uc $type eq 'PREPARED') {
    0          
1149 0           $type = 0;
1150 0           $idatetime = shift;
1151 0 0 0       if (defined $idatetime and
      0        
1152             ($idatetime eq '?' or $idatetime eq '??')) {
1153 0 0         if ($self->{driver} eq 'Oracle') {
    0          
    0          
1154 0 0         if ($idatetime eq '?') {
1155 0           return "TO_DATE(?, 'dd.mm.yyyy')";
1156             }
1157             else {
1158 0           return "TO_DATE(?, 'dd.mm.yyyy hh24:mi:ss')";
1159             }
1160             }
1161 0           elsif ($self->{driver} eq 'mssql') {
1162 0           return "convert(datetime, ?, 120)";
1163             }
1164             elsif (grep {$self->{driver} eq $_} ('Pg','Informix','Sybase','DB2','mysql','Solid')) {
1165 0           return '?';
1166             }
1167             else {
1168 0           return undef;
1169             }
1170             }
1171             }
1172             elsif ( uc $type eq 'COMMON') {
1173 0           $type = 1;
1174 0           $idatetime = shift;
1175             }
1176             else {
1177 0           $idatetime = $type;
1178 0           $type = 1;
1179             }
1180 0 0         if ($#_ < 0) { # input is in the $idatetime
    0          
    0          
    0          
    0          
1181 0 0 0       if (defined $idatetime && $idatetime !~ /!/) {
1182 0           ($d, $t) = split / /, $idatetime;
1183 0           ($day, $mon, $year) = split /\./, $d;
1184 0 0         if (defined $t) {
1185 0           ($hour, $min, $sec) = split /:/, $t;
1186 0           $t = 1;
1187             }
1188             else {
1189 0           $t = 0;
1190             }
1191             }
1192             else {
1193 0           ($sec, $min, $hour, $day, $mon, $year) = localtime;
1194 0 0 0       if (!defined $idatetime || $idatetime ne '!') {
1195 0           $t = 1;
1196             }
1197             else {
1198 0           $t = 0;
1199             }
1200             }
1201             }
1202             elsif ($#_ < 1) { # input is mon and year
1203 0           $mon = $idatetime;
1204 0           $year = shift;
1205 0           $t = 0;
1206             }
1207             elsif ($#_ < 2) { # input is day, mon and year
1208 0           $day = $idatetime;
1209 0           $mon = shift;
1210 0           $year = shift;
1211 0           $t = 0;
1212             }
1213             elsif ($#_ < 3) { # input is hour, day, mon and year
1214 0           $hour = $idatetime;
1215 0           $day = shift;
1216 0           $mon = shift;
1217 0           $year = shift;
1218 0           $t = 1;
1219 0           $min = 0;
1220 0           $sec = 0;
1221             }
1222             elsif ($#_ < 4) { # input is min, hour, day, mon and year
1223 0           $min = $idatetime;
1224 0           $hour = shift;
1225 0           $day = shift;
1226 0           $mon = shift;
1227 0           $year = shift;
1228 0           $t = 1;
1229 0           $sec = 0;
1230             }
1231             else { # input is sec, min, hour, day, mon and year
1232 0           $sec = $idatetime;
1233 0           $min = shift;
1234 0           $hour = shift;
1235 0           $day = shift;
1236 0           $mon = shift;
1237 0           $year = shift;
1238 0           $t = 1;
1239             }
1240              
1241 0 0 0       if ($mon == 0 or $year < 1000) { # perl-localtime output
1242 0           $mon++;
1243 0           $year += 1900;
1244             }
1245 0 0 0       if ($mon == 1 or $mon == 3 or $mon == 5 or $mon == 7 or $mon == 8 or
    0 0        
    0 0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
1246             $mon == 10 or $mon == 12) {
1247 0 0         if (! defined $day) {
    0          
1248 0           $day = 31;
1249             }
1250             elsif ($day > 31) {
1251 0           return undef;
1252             }
1253             }
1254             elsif ($mon == 4 or $mon == 6 or $mon == 9 or $mon == 11) {
1255 0 0         if (! defined $day) {
    0          
1256 0           $day = 30;
1257             }
1258             elsif ($day > 30) {
1259 0           return undef;
1260             }
1261             }
1262             elsif ($year % 4 or (!($year % 100) and $year % 1000)) {
1263 0 0         if (! defined $day) {
    0          
1264 0           $day = 28;
1265             }
1266             elsif ($day > 28) {
1267 0           return undef;
1268             }
1269             }
1270             else {
1271 0 0         if (! defined $day) {
    0          
1272 0           $day = 29;
1273             }
1274             elsif ($day > 29) {
1275 0           return undef;
1276             }
1277             }
1278             # some tests
1279 0 0 0       return undef if $mon < 1 or $mon > 12 or $day < 1;
      0        
1280 0 0 0       return undef if $t and ($hour < 0 or $hour > 23 or $min < 0 or $min > 59 or
      0        
1281             $sec < 0 or $sec > 59);
1282              
1283 0 0         if ($self->{driver} eq 'Oracle') {
  0 0          
    0          
    0          
1284 0 0         if ($type) {
1285 0 0         if ($t) {
1286 0           $odatetime = sprintf "TO_DATE('%02d.%02d.%04d %02d:%02d:%02d',".
1287             "'dd.mm.yyyy hh24:mi:ss')",
1288             $day, $mon, $year, $hour, $min, $sec;
1289             }
1290             else {
1291 0           $odatetime = sprintf "TO_DATE('%02d.%02d.%04d', 'dd.mm.yyyy')",
1292             $day, $mon, $year;
1293             }
1294             }
1295             else {
1296             # WARNING - IT'S A BUG (FEATURE).
1297             # IT SHOULD BE FORMATTED ACCORDING TO NLS_DATE_FORMAT
1298 0 0         if ($t) {
1299 0           $odatetime = sprintf "%02d.%02d.%04d %02d:%02d:%02d",
1300             $day, $mon, $year, $hour, $min, $sec;
1301             }
1302             else {
1303 0           $odatetime = sprintf "%02d.%02d.%04d", $day, $mon, $year;
1304             }
1305             }
1306             }
1307             elsif ( grep {$self->{driver} eq $_} ('Pg','DB2','Solid','mysql')) {
1308 0 0         if ($type) {
1309 0 0         if ($t) {
1310 0           $odatetime = sprintf "'%04d-%02d-%02d %02d:%02d:%02d'",
1311             $year, $mon, $day, $hour, $min, $sec;
1312             }
1313             else {
1314 0           $odatetime = sprintf "'%04d-%02d-%02d'", $year, $mon, $day;
1315             }
1316             } else {
1317 0 0         if ($t) {
1318 0           $odatetime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
1319             $year, $mon, $day, $hour, $min, $sec;
1320             }
1321             else {
1322 0           $odatetime = sprintf "%04d-%02d-%02d", $year, $mon, $day;
1323             }
1324             }
1325             }
1326             elsif ($self->{driver} eq 'Informix') {
1327 0 0         if ($type) {
1328 0 0         if ($t) {
1329 0           $odatetime = sprintf "'%04d-%02d-%02d %02d:%02d:%02d'",
1330             $year, $mon, $day, $hour, $min, $sec;
1331             }
1332             else {
1333 0           $odatetime = sprintf "'%02d.%02d.%04d'", $day, $mon, $year;
1334             }
1335             } else {
1336 0 0         if ($t) {
1337 0           $odatetime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
1338             $year, $mon, $day, $hour, $min, $sec;
1339             }
1340             else {
1341 0           $odatetime = sprintf "%02d.%02d.%04d", $day, $mon, $year;
1342             }
1343             }
1344             }
1345             elsif ($self->{driver} eq 'mssql') {
1346 0 0         if ($type) {
1347 0 0         if ($t) {
1348 0           $odatetime = sprintf "convert(datetime, '%04d-%02d-%02d %02d:%02d:%02d', 120)",
1349             $year, $mon, $day, $hour, $min, $sec;
1350             }
1351             else {
1352 0           $odatetime = sprintf "convert(datetime, '%04d-%02d-%02d %02d:%02d:%02d', 120)",
1353             $year, $mon, $day, 0, 0, 0;
1354             }
1355             } else {
1356 0 0         if ($t) {
1357 0           $odatetime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
1358             $year, $mon, $day, $hour, $min, $sec;
1359             }
1360             else {
1361 0           $odatetime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
1362             $year, $mon, $day, 0, 0, 0;
1363             }
1364             }
1365             }
1366             else { # other drivers not supported
1367 0           $Derror_message = "MODULE ERROR: DBD driver not supported";
1368 0           return undef;
1369             }
1370              
1371 0           return $odatetime;
1372              
1373             } # date2db
1374              
1375             #########################################################################
1376             sub db2date {
1377              
1378 0     0 1   my $self = shift;
1379 0   0       my $idatetime = shift || return wantarray ? () : undef;
1380 0           my ($year, $mon, $day, $hour, $min, $sec);
1381 0           my ($d, $t);
1382              
1383 0 0         if ($self->{driver} eq 'Oracle') { # assumed NLS_DATE_FORMAT = DD.MM.YYYY
  0 0          
    0          
    0          
1384 0           ($d, $t) = split / /, $idatetime;
1385 0           ($day, $mon, $year) = split /\./, $d;
1386 0 0         ($hour, $min, $sec) = split /:/, $t if $t;
1387             }
1388             elsif (grep {$self->{driver} eq $_} ('Pg','DB2','Solid','mysql')) { # assumed PGDATESTYLE = 'ISO'
1389 0           ($d, $t) = split / /, $idatetime;
1390 0           ($year, $mon, $day) = split /-/, $d;
1391 0 0         if ($t) {
1392 0           ($t) = split /\+/, $t; # tz in postgresql
1393 0           ($t) = split /\./, $t; # fraction in solid
1394 0           ($hour, $min, $sec) = split /:/, $t;
1395             }
1396             }
1397             elsif ($self->{driver} eq 'Informix') { # assumed DBDATE=dmy4.
1398 0           ($d, $t) = split / /, $idatetime;
1399 0 0         if ($t) {
1400 0           ($year, $mon, $day) = split /-/, $d;
1401 0           ($hour, $min, $sec) = split /:/, $t;
1402             }
1403             else {
1404 0           ($day, $mon, $year) = split /\./, $d;
1405             }
1406             }
1407             elsif ($self->{driver} eq 'mssql') {
1408 0           ($d, $t) = split / /, $idatetime;
1409 0           ($year, $mon, $day) = split /-/, $d;
1410 0 0         if ($t) {
1411 0           ($t) = split /\+/, $t;
1412 0           ($hour, $min, $sec) = split /:/, $t;
1413             }
1414             #($day, $mon, $year) = split /\./, $d;
1415             #($hour, $min, $sec) = split /:/, $t if $t;
1416             }
1417             else { # other drivers not supported
1418 0           $Derror_message = "MODULE ERROR: DBD driver not supported";
1419 0 0         return wantarray ? () : undef;
1420             }
1421              
1422 0 0         if ($t) {
1423 0 0         return wantarray ? ($sec, $min, $hour, $day, $mon, $year) :
1424             sprintf "%02d.%02d.%04d %02d:%02d:%02d",
1425             $day, $mon, $year, $hour, $min, $sec;
1426             }
1427 0 0         return wantarray ? ($day, $mon, $year) :
1428             sprintf "%02d.%02d.%04d", $day, $mon, $year;
1429              
1430             } # db2date
1431              
1432             ###########################################################################
1433             sub ping {
1434 0     0 1   my $self = shift;
1435              
1436 0           my $result = $self->{conn}->ping();
1437 0 0         return 1 if $result eq '0 but true';
1438 0           return $result;
1439             }
1440              
1441             ###########################################################################
1442             sub get_driver {
1443              
1444 0     0 0   my $driver = shift;
1445 0           my @drv_arr = DBI->available_drivers;
1446              
1447 0 0         if ( ! $driver) {
1448 0           return @drv_arr;
1449             }
1450 0 0 0       return 'mssql' if grep 'Sybase' eq $_, @drv_arr and $driver eq 'mssql';
1451 0 0         return $driver if grep $driver eq $_, @drv_arr;
1452 0           return undef;
1453              
1454             } # get_driver
1455              
1456             ###########################################################################
1457             sub get_source {
1458              
1459 0     0 0   my $self = shift;
1460 0           my $driver = shift;
1461              
1462 0 0 0       return undef if ! $driver or ! get_driver($driver);
1463 0           my $source = shift;
1464 0           my @src_arr;
1465 0 0 0       if ($driver ne 'Oracle' and $driver ne 'mssql' and $driver ne 'Solid') {
    0 0        
    0          
    0          
1466 0           @src_arr = DBI->data_sources($driver);
1467 0 0 0       if ($driver eq 'Informix' and $source !~ /@/) {
1468 0           for (my $i = 0; $i < scalar @src_arr; $i++) {
1469 0           $src_arr[$i] =~ s/@.*//;
1470             }
1471             }
1472             }
1473             elsif ($driver eq 'Oracle') {
1474 0           @src_arr = ("dbi:Oracle:$source", $source, "dbi:Oracle:");
1475             }
1476             elsif ($driver eq 'mssql') {
1477 0           @src_arr = ("dbi:Sybase:", $source, "dbi:Sybase:");
1478             }
1479             elsif ($driver eq 'Solid') {
1480 0           @src_arr = ("dbi:Solid:$source", $source, "dbi:Solid:");
1481             }
1482 0 0         return @src_arr if ! defined $source;
1483 0           SWITCH: for ($driver) {
1484 0 0         /Pg/ && do {
1485 0 0         $source = 'dbi:Pg:dbname=' . $source if $source !~ /dbi:Pg:dbname=/;
1486 0 0         $source .= ';host=' . $self->{host} if $self->{host};
1487 0 0         $source .= ';port=' . $self->{port} if $self->{port};
1488 0           last SWITCH;};
1489 0 0         /Oracle/ && do {
1490 0 0         $source = 'dbi:Oracle:' . $source if $source !~ /dbi:Oracle:/;
1491 0           last SWITCH;};
1492 0 0         /Informix/ && do {
1493 0 0         $source = 'dbi:Informix:' . $source if $source !~ /dbi:Informix:/;
1494 0           last SWITCH;};
1495 0 0         /DB2/ && do {
1496 0 0         $source = 'dbi:DB2:' . $source if $source !~ /dbi:DB2:/;
1497 0           last SWITCH;};
1498 0 0         /mysql/ && do {
1499 0           $source = 'dbi:mysql:database=' . $source;
1500 0 0         $source .= ';host=' . $self->{host} if $self->{host};
1501 0           last SWITCH;};
1502 0 0         /mssql/ && do {
1503 0           $source = 'dbi:Sybase:database=' . $source;
1504 0 0         $source .= ';server=' . $self->{host} if $self->{host};
1505 0           $source .= ';language=czech';
1506 0           last SWITCH;};
1507 0 0         /Solid/ && do {
1508 0 0         $source = 'dbi:Solid:' . $source if $source !~ /dbi:Solid:/;
1509 0           last SWITCH;};
1510             # Default (not supported)
1511 0           return undef;
1512             }
1513             #if ($Dconnecttype[$sid] eq 'PROXY') {
1514             # $driver = "dsn=$source";
1515             # $source = "dbi:Proxy:hostname=$Dhost[$sid];port=$Dport[$sid];";
1516             # $source .= "cipher=$Dcipher[$sid];key=$Dkey[$sid];" if $Dkey[$sid];
1517             # $source .= "usercipher=$Dusercipher[$sid];userkey=$Duserkey[$sid];"
1518             # if $Duserkey[$sid];
1519             # $source .= $driver;
1520             #}
1521              
1522             #return $source if $Dconnecttype[$sid] eq 'PROXY' or grep $source eq $_, @src_arr;
1523 0           return $source;
1524 0           return undef;
1525              
1526             } # get_source
1527              
1528             ###########################################################################
1529             sub trace_on {
1530             #
1531             # Enable trace
1532             #
1533              
1534 0     0 1   my (undef, $level, $file) = @_;
1535 0           DBI->trace($level, $file);
1536              
1537             } # trace_on
1538              
1539             ###########################################################################
1540             sub trace_off {
1541             #
1542             # Disable trace
1543             #
1544              
1545 0     0 1   DBI->trace(0);
1546              
1547             } # trace_off
1548              
1549             ###########################################################################
1550             sub trace_level {
1551              
1552 0     0 0   my $self = shift;
1553              
1554 0           $self->{trace} = shift;
1555             }
1556              
1557             ###########################################################################
1558             sub _trace {
1559            
1560 0     0     my $self = shift;
1561              
1562 0           my $errnum = '';
1563 0 0         $errnum = $Dcmdstatus if $Dcmdstatus;
1564 0 0         $errnum = $Dsqlstatus if $Dsqlstatus;
1565 0 0         $errnum = " [$errnum]" if $errnum;
1566 0           my $msg = "DB$errnum: $Derror_message";
1567 0 0         if ($self->{trace} > 1) {
1568 0 0         $msg .= " ($Dstr_command)" if defined $Dstr_command;
1569 0 0         if ($#_ >= 0) { # doplneni dat
1570 0 0         $msg .= " [data: ".join(',',map {defined $_ ? $_ : 'undef'} @_)."]";
  0            
1571             }
1572             }
1573 0           trace('E', $msg);
1574              
1575             } # END _trace
1576              
1577             ###########################################################################
1578             sub _trace_msg {
1579              
1580 0     0     my $self = shift;
1581 0           my $msg = shift;
1582              
1583 0           trace('E', $msg);
1584             } # END _trace_msg
1585              
1586             ###########################################################################
1587             sub _set_app {
1588              
1589 0     0     my $self = shift;
1590 0           my $app = shift;
1591              
1592 0           $self->{app} = $app;
1593             }
1594              
1595             ###########################################################################
1596             sub _replace_values {
1597              
1598 0     0     my $self = shift;
1599 0           my $sql = shift;
1600 0           my @val = @_;
1601              
1602 0           foreach (@val) {
1603 0 0         $_ = 'null' if !defined $_;
1604 0 0         ($_) = $self->quote($_) if ! /^[0-9.]+$/;
1605 0           $sql =~ s/\?/$_/;
1606             }
1607              
1608 0           return $sql;
1609             }
1610              
1611             ###########################################################################
1612             sub DESTROY {
1613              
1614 0     0     my $self = shift;
1615              
1616 0           $self->close();
1617             }
1618              
1619             ###########################################################################
1620             sub _stat_start {
1621              
1622 0     0     my $self = shift;
1623              
1624 0           my ($type, $sql, $param, $name) = @_;
1625 0 0         if ($self->{stat_type} eq 'none') { return; }
  0            
1626              
1627 0           $self->{stat_act}{start} = [gettimeofday()];
1628 0           $self->{stat_act}{type} = $type;
1629 0           $self->{stat_act}{sql} = $sql;
1630 0           $self->{stat_act}{par} = $param;
1631 0   0       $self->{stat_act}{name} = $name || '';
1632             }
1633              
1634             ###########################################################################
1635             sub _stat_end {
1636              
1637 0     0     my $self = shift;
1638              
1639 0           my $status = shift;
1640 0 0         if ($self->{stat_type} eq 'none') { return; }
  0            
1641              
1642             # celkovy cas
1643 0           my $time = tv_interval($self->{stat_act}{start});
1644              
1645             # soucty vzdy
1646 0           $self->{stat_all}{total_time} += $time;
1647 0           $self->{stat_all}{total_comm}++;
1648 0 0         $self->{stat_all}{total_err}++ if $status eq 'ERROR';
1649              
1650 0 0         if ($self->{stat_type} eq 'sums') { return; }
  0            
1651              
1652             # info o prikaze
1653 0           my $tmp = { time => $time, type => $self->{stat_act}{type},
1654             sql => $self->{stat_act}{sql}, par => $self->{stat_act}{par},
1655             name => $self->{stat_act}{name} };
1656 0 0         if ($status eq 'ERROR') {
1657 0           $tmp->{error} = $Derror_message;
1658             }
1659              
1660             # tri nejdelsi
1661 0           push @{$self->{stat_all}{high}}, $tmp;
  0            
1662             # setridit
1663 0           @{$self->{stat_all}{high}} =
  0            
1664 0           sort { $b->{time} <=> $a->{time} }
1665 0           @{$self->{stat_all}{high}};
1666 0 0         if (scalar @{$self->{stat_all}{high}} > $self->{stat_max_high}) {
  0            
1667             # posledni pryc
1668 0           pop @{$self->{stat_all}{high}};
  0            
1669             }
1670              
1671 0 0         if ($self->{stat_type} eq 'high') { return; }
  0            
1672              
1673             # info o vsech prikazech
1674 0           push @{$self->{stat_all}{all}}, $tmp
  0            
1675 0 0 0       if (!$self->{stat_all}{all} or scalar @{$self->{stat_all}{all}} < $self->{stat_max_all});
1676             }
1677              
1678             ###########################################################################
1679             sub set_stat {
1680            
1681 0     0 1   my $self = shift;
1682              
1683 0           $self->{stat_type} = shift;
1684 0           my ($max_high, $max_all) = @_;
1685 0 0         $self->{stat_max_high} = $max_high if $max_high;
1686 0 0         $self->{stat_max_all} = $max_all if $max_all;
1687             }
1688              
1689             ###########################################################################
1690             sub reset_stat {
1691              
1692 0     0 1   my $self = shift;
1693              
1694 0           $self->{stat_all}{total_time} = 0;
1695 0           $self->{stat_all}{total_comm} = 0;
1696 0           $self->{stat_all}{total_err} = 0;
1697              
1698 0           $self->{stat_all}{high} = [];
1699 0           $self->{stat_all}{all} = [];
1700             }
1701              
1702             ###########################################################################
1703             sub get_stat {
1704              
1705 0     0 1   my $self = shift;
1706              
1707 0   0       my $total_time = $self->{stat_all}{total_time} || 0;
1708 0   0       my $total_comm = $self->{stat_all}{total_comm} || 0;
1709 0   0       my $total_err = $self->{stat_all}{total_err} || 0;
1710              
1711 0           my $ref_high = $self->{stat_all}{high};
1712 0           my $ref_all = $self->{stat_all}{all};
1713              
1714 0           return ($total_time, $total_comm, $total_err, $ref_high, $ref_all);
1715             }
1716              
1717             ###########################################################################
1718             sub test_err {
1719              
1720 0     0 1   my $self = shift;
1721 0           my $teste = shift;
1722 0           my @teste = ();
1723 0           my $rete = -1;
1724              
1725 0           while (defined $teste) {
1726 0           $teste = uc($teste);
1727 0 0 0       if ($teste eq 'TABLE_NOTEXIST' or $teste eq '1') { push @teste, 1;}
  0 0 0        
    0 0        
    0 0        
    0 0        
1728 0           elsif ($teste eq 'TABLE_EXIST' or $teste eq '2') { push @teste, 2;}
1729 0           elsif ($teste eq 'REC_EXIST' or $teste eq '3') { push @teste, 3;}
1730 0           elsif ($teste eq 'SCHEMA_NOTEXIST' or $teste eq '4') { push @teste, 4;}
1731 0           elsif ($teste eq 'SCHEMA_EXIST' or $teste eq '5') { push @teste, 5;}
1732 0           else { return 0; }
1733 0           $teste = shift;
1734             }
1735 2     2   22 no warnings "uninitialized";
  2         4  
  2         1662  
1736 0 0         if ($self->{driver} eq 'Pg') {
    0          
    0          
    0          
    0          
    0          
    0          
1737 0 0 0       if ($Dsqlstatus eq '7' && $Derror_message =~ /(Relation|relation|table) .* does not exist/) { $rete = 1; }
  0 0 0        
    0 0        
    0 0        
    0 0        
1738 0           elsif ($Dsqlstatus eq '7' && $Derror_message =~ /(R|r)elation .* already exists/) { $rete = 2; }
1739 0           elsif ($Dsqlstatus eq '7' && $Derror_message =~ /duplicate key/) { $rete = 3; }
1740 0           elsif ($Dsqlstatus eq '7' && $Derror_message =~ /(Namespace|Schema|schema) .* does not exist/) { $rete = 4; }
1741 0           elsif ($Dsqlstatus eq '7' && $Derror_message =~ /(namespace|schema) .* already exists/) { $rete = 5; }
1742             }
1743             elsif ($self->{driver} eq 'Oracle') {
1744 0 0 0       if ($Dsqlstatus eq '942' || $Dsqlstatus eq '4043') { $rete = 1; }
  0 0          
    0          
1745 0           elsif ($Dsqlstatus eq '955') { $rete = 2; }
1746 0           elsif ($Dsqlstatus eq '1') { $rete = 3; }
1747             }
1748             elsif ($self->{driver} eq 'Informix') {
1749 0 0         if ($Dsqlstatus eq '-206') { $rete = 1; }
  0 0          
    0          
1750 0           elsif ($Dsqlstatus eq '-310') { $rete = 2; }
1751 0           elsif ($Dsqlstatus eq '-239') { $rete = 3; }
1752             }
1753             elsif ($self->{driver} eq 'DB2') {
1754 0 0 0       if (($Dsqlstatus eq '-204' && $Derror_message =~ /"[^\.]+\.[^\.]+"/)
    0 0        
    0 0        
    0 0        
    0 0        
      0        
1755 0           || ($Dsqlstatus eq '-99999' && $Derror_message =~ /CLI0125E/)) { $rete = 1; }
1756 0           elsif ($Dsqlstatus eq '-601' && $Derror_message =~ /type "TABLE"/) { $rete = 2; }
1757 0           elsif ($Dsqlstatus eq '-803') { $rete = 3; }
1758 0           elsif ($Dsqlstatus eq '-204' && $Derror_message =~ /"[^\.]+"/) { $rete = 4; }
1759 0           elsif ($Dsqlstatus eq '-601' && $Derror_message =~ /type "SCHEMA"/) { $rete = 5; }
1760             }
1761             elsif ($self->{driver} eq 'mysql') {
1762 0 0 0       if ($Dsqlstatus eq '1051' || $Dsqlstatus eq '1146') { $rete = 1; }
  0 0          
    0          
1763 0           elsif ($Dsqlstatus eq '1050') { $rete = 2; }
1764 0           elsif ($Dsqlstatus eq '1062') { $rete = 3; }
1765             }
1766             elsif ($self->{driver} eq 'mssql') {
1767 0 0 0       if ($Dsqlstatus eq '3701' || $Dsqlstatus eq '208') { $rete = 1; }
  0 0          
    0          
1768 0           elsif ($Dsqlstatus eq '2714') { $rete = 2; }
1769 0           elsif ($Dsqlstatus eq '2601') { $rete = 3; }
1770             }
1771             elsif ($self->{driver} eq 'Solid') {
1772 0 0 0       if ($Dsqlstatus eq '13011') { $rete = 1; }
  0 0 0        
    0          
    0          
    0          
1773 0           elsif ($Dsqlstatus eq '13013') { $rete = 2; }
1774 0           elsif ($Dsqlstatus eq '10005' || $Dsqlstatus eq '10033') { $rete = 3; }
1775 0           elsif ($Dsqlstatus eq '13141' || $Dsqlstatus eq '13046') { $rete = 4; }
1776 0           elsif ($Dsqlstatus eq '13142') { $rete = 5; }
1777             }
1778             else {
1779 0 0         return -1 if !scalar @teste;
1780 0           return 0;
1781             }
1782              
1783 0 0         return $rete if ! scalar @teste;
1784 0 0         return (grep({$rete == $_} @teste) ? $rete : 0);
  0            
1785            
1786             } # test_err
1787              
1788             ###########################################################################
1789             sub imix_number_correct {
1790              
1791 0     0 0   my $self = shift;
1792 0           my $arg = shift;
1793              
1794 0           $self->{imix_number_correct} = $arg;
1795              
1796             } # imix_number_correct()
1797              
1798             #######################################################################
1799             # Initialization code of module
1800             #######################################################################
1801              
1802             1;
1803              
1804             =head1 NAME
1805              
1806             DeltaX::Database - Perl module which hiddens DB differences on DBI level
1807              
1808             _____
1809             / \ _____ ______ ______ ___________
1810             / \ / \\__ \ / ___// ___// __ \_ __ \
1811             / Y \/ __ \_\___ \ \___ \\ ___/| | \/
1812             \____|__ (____ /____ >____ >\___ >__|
1813             \/ \/ \/ \/ \/ project
1814              
1815              
1816             Supported drivers:
1817             Oracle [Oracle]
1818             PostgreSQL [Pg]
1819             MySQL [mysql]
1820             Sybase [Sybase] [not tested]
1821             MS SQL [mssql] [using Sybase driver]
1822             DB2 [DB2]
1823             Solid [Solid]
1824              
1825             =head1 SYNOPSIS
1826              
1827             =head2 Public functions
1828              
1829             new - New DB connect
1830             close - Close DB connect
1831             check - DB connect check
1832             transaction_begin - Begin transaction
1833             transaction_end - End transaction
1834             select - Performing SQL select
1835             open_cursor - Cursor openning
1836             fetch_cursor - Get row by opened cursor
1837             close_cursor - Close cursor
1838             exists_cursor - Checks existence of cursor
1839             insert - Performing SQL insert
1840             delete - Performing SQL delete
1841             update - Performing SQL update
1842             command - Performing any SQL command
1843             open_statement - Prepare statement (for bind values)
1844             perform_statement - Perform prepared statement
1845             close_statement - Close prepared statement
1846             exists_statement - Checks existence of statement
1847             quote - Quotting string
1848             date2db - Converting datetime to db format
1849             db2date - Converting db format of date to datetime
1850             nextval - Select next value from sequence
1851             func - Performs DBD specific function
1852             const - Sets DBD specific constant
1853             ping - Checks DB connect
1854             trace - set trace level
1855             trace_on - DBI trace ON
1856             trace_off - DBI trace OFF
1857             set_stat - set statistics type
1858             reset_stat - reset statistics
1859             get_stat - get statistics
1860             test_err - test sqlerror
1861              
1862             =head2 Public variables
1863              
1864             $Dsqlstatus - SQL status (error) code
1865             $Dcmdstatus - Command status (error) code
1866             $Derror_message - Actual error message
1867             $VERSION - Module wersion
1868             $Dstr_command - last used SQL command
1869              
1870             =head2 Private functions
1871              
1872             get_driver - Returns DBD driver
1873             get_source - Returns DBD specific connect string
1874             _trace - Error trace (using DeltaX::Trace)
1875             _trace_msg - Error trace (using DeltaX::Trace)
1876             _set_app - Sets application prefix (for statements)
1877             _replace_values - replaces values for placeholders
1878              
1879             =head2 Private variables
1880              
1881              
1882             =head1 DESCRIPTION
1883              
1884             =head2 new
1885              
1886             Connects to DB and creates new object which handles it.
1887             Parameters are given in key => value form.
1888            
1889             Possible parameters:
1890             driver [required] - DB driver to use (eg. Oracle, Pg, ...)
1891             dbname [required] - database name
1892             host [def: none] - host on which database resides
1893             user [required] - user to connect to DB
1894             auth - password to connect to DB
1895             autocommit [def: 0] - use autocommit?
1896             datestyle [def: none] - DB specific datestyle
1897             (eg. PGDATESTYLE for PostgreSQL, NLS_DATE_FORMAT for Oracle,
1898             DBDATE for Informix)
1899             close_curs [def: 0] - close cursors when ending transaction?
1900             cursor_type [def: INTERNAL]
1901             - default cursor type
1902             trace [def: 0] - tracing: 0 - none, 1 - errors, 2 - with SQL string
1903             app [def: none] - application prefix for
1904              
1905             Returns:
1906             undef in case of error (check $Derror_message for reason)
1907             otherwise returns new DeltaX::Database object
1908              
1909             =head2 close
1910              
1911             Closes DB connect
1912              
1913             Returns: -nothing-
1914              
1915             =head2 check
1916              
1917             Checks DB connect (via ping()).
1918              
1919             Syntax:
1920             check()
1921              
1922             Args:
1923             -none-
1924              
1925             Returns:
1926             -1 - error
1927             0 - ok/connected
1928              
1929             =head2 ping
1930              
1931             Interface to DBH->ping().
1932              
1933             Syntax:
1934             ping()
1935              
1936             Args:
1937             -none-
1938              
1939             Returns:
1940             value returned by DBH->ping().
1941              
1942             =head2 transaction_begin
1943              
1944             Starts new transaction by performing COMMIT ($type == 1, it's default)
1945             or ROLLBACK ($type == 0).
1946            
1947             Syntax:
1948             transaction_begin([$type])
1949            
1950             Args:
1951             $type [def: 1] - see above
1952              
1953             Returns:
1954             1 - ok
1955             0 - SQL command failed (see $Derror_message)
1956             -1 - autocommit is enabled
1957             -2 - not connected
1958              
1959             Note:
1960             It erases all cursors if close_curs enabled (see L<"new">).
1961              
1962             =head2 transaction_end
1963              
1964             Ends transaction by performing COMMIT ($type == 1, it's default) or
1965             ROLLBACK ($type == 0).
1966              
1967             Syntax:
1968             transaction_begin([$type])
1969              
1970             Args:
1971             $type [def: 0] - see above
1972              
1973             Returns:
1974             1 - ok
1975             0 - SQL command failedc (see $Derror_message)
1976             -1 - autocommit is enabled
1977             -2 - not connected
1978              
1979             Note:
1980             It erases all cursors if close_curs enabled (see L<"new">).
1981              
1982             =head2 select
1983              
1984             Performs SQL command (SELECT assumed) and returns array with first returned
1985             row.
1986              
1987             Syntax:
1988             select($select_str)
1989              
1990             Args:
1991             $select_str - SELECT command string
1992              
1993             Returns:
1994             array, first value:
1995             0 - no records found
1996             >0 - record found (on index 1 starts selected row values)
1997             -1 - SQL error (see $Derror_message)
1998             -2 - bad parameters
1999             -3 - not connected
2000              
2001             Note:
2002             If transaction not started, it performs transaction_end(0)
2003              
2004             =head2 open_cursor
2005              
2006             Opens new cursor $cursor_name. For fetching rows use fetch_cursor().
2007              
2008             Syntax:
2009             open_cursor($cursor_name, {$select_str | $prepared_name, [$cursor_type,] [@bind_values]})
2010              
2011             Args:
2012             $cursor_name [required] - cursor name (existing cursor with the same name will
2013             be replaced)
2014             $select_str - SQL SELECT command
2015             - or -
2016             $prepared_name - name of prepared statement
2017             $cursor_type - INTERNAL [emulated], EXTERNAL [by DBI - DB]
2018             @bind_values - values for prepared statement
2019              
2020             Returns:
2021             0 - no rows found
2022             >0 - ok, for INTERNAL returns number of rows, for EXTERNAL DBD specific value
2023             -1 - SQL command failed (see $Derror_message)
2024             -2 - bad parameters
2025             -3 - not connected
2026              
2027             Note:
2028             Cursor from prepared statement is always INTERNAL.
2029              
2030             Note:
2031             For MS SQL, cursor is always INTERNAL.
2032              
2033             =head2 fetch_cursor
2034              
2035             Returns next row from cursor.
2036              
2037             Syntax:
2038             fetch_cursor($cursor_name, [$num_row])
2039              
2040             Args:
2041             $cursor_name [required] - cursor name
2042             $num_row [def: next] - position of required row (from 0, for INTERNAL
2043             cursors only!)
2044              
2045             Returns:
2046             array with result, first value indicates status:
2047             0 - last row, next fetch_cursor() returns first row again
2048             >0 - next row, not last
2049             -1 - SQL error (see $Derror_message)
2050             -2 - bad parameters
2051             -3 - cursor doesn't exist
2052             -4 - not connected
2053              
2054             =head2 close_cursor
2055              
2056             Closes cursor and releases data from it.
2057              
2058             Syntax:
2059             close_cursor($cursor_name)
2060              
2061             Args:
2062             $cursor_name [required] - cursor name to close
2063              
2064             Returns:
2065             0 - cursor closed
2066             -1 - bad paramaters
2067             -2 - cursor doesn't exist
2068             -3 - not connected
2069              
2070             =head2 exists_cursor
2071              
2072             Check existence of cursor of given name.
2073              
2074             Syntax:
2075             exists_cursor($cursor_name)
2076              
2077             Args:
2078             $cursor_name [required] - cursor name
2079              
2080             Returns:
2081             0 - not exists
2082             1 - exists
2083              
2084             =head2 open_statement
2085              
2086             Prepares SQL command, which can bind variables and can be repeatly exexuted
2087             (using L<"perform_statement"> or L<"open_cursor">).
2088              
2089             Syntax:
2090             open_statement($stmt_name, $sql_string, $num_binds)
2091              
2092             Args:
2093             $stmt_name [required] - statement name, if exists will be replaced
2094             $sql_string [required] - SQL command to prepare
2095             $num_binds [optional] - number of binded values (for check only)
2096              
2097             Returns:
2098             >0 - number of binded variables [ok]
2099             0 - no bind values [ok]
2100             -1 - SQL command failed [not supported by all drivers]
2101             -2 - bad parameters
2102             -3 - bad number of binded variables
2103             -4 - not connected
2104              
2105             Note:
2106             Use only question marks, no :a form!
2107              
2108             Note:
2109             [Oracle only] For BLOBs use exclamation marks or ?B instead of question marks.
2110             [Oracle only] For CLOBs use ?C instead of question marks.
2111              
2112             =head2 perform_statement
2113              
2114             Performs prepared statement.
2115              
2116             Syntax:
2117             perform_statement($stmt_name, [@bind_values])
2118              
2119             Args:
2120             $stmt_name [required] - statement name (must be prepared using
2121             prepare_statement())
2122             @bind_values - values which will be binded to statement,
2123             there must be not less values than there is in prepared statement,
2124             redundant will be ignored
2125              
2126             Returns:
2127             array, first value indicates status:
2128             0 - no row returned/affected, but success
2129             >0 - ok, number of returned/affected rows
2130             (for SELECT it returns just one row (see select()), for
2131             INSERT/UPDATE/DELETE returns number of affected rows)
2132             -1 - SQL error (see $Derror_message)
2133             -2 - bad parameters
2134             -3 - statement doesn't exist
2135             -4 not connected
2136             for SELECT other values in array represents returned row
2137              
2138             =head2 close_statement
2139              
2140             Closes (destroys) prepared statement.
2141              
2142             Syntax:
2143             close_statement($stmt_name)
2144              
2145             Args:
2146             $stmt_name [required] - statement name to close
2147              
2148             Returns:
2149             0 - closed
2150             -2 - bad parameters
2151             -3 - statement doesn't exist
2152             -4 - not connected
2153              
2154             =head2 exists_statement
2155              
2156             Checks existence of statement of given name.
2157              
2158             Syntax:
2159             exists_statement($stmt_name)
2160              
2161             Args:
2162             $stmt_name [required] - statement name to check
2163              
2164             Returns:
2165             1 - exists
2166             0 - not exists or no statement name given
2167              
2168             =head2 insert
2169              
2170             Performs SQL command (assumes INSERT) and returns number of inserted rows.
2171              
2172             Syntax:
2173             insert($insert_string)
2174              
2175             Args:
2176             $insert_string [required] - the SQL command (INSERT)
2177              
2178             Returns:
2179             >=0 - number of inserted rows
2180             -1 - sql command failed (check Dsqlstatus, Dcmdstatus, Derror_message
2181             -2 - bad parameter
2182             -3 - not connected
2183              
2184             =head2 delete
2185              
2186             Performs SQL command (assumes DELETE) and returns number of deleted rows.
2187              
2188             Syntax:
2189             delete($delete_string)
2190              
2191             Args:
2192             $delete_string [required] - the SQL command (DELETE)
2193              
2194             Returns:
2195             >=0 - number of deleted rows
2196             -1 - sql command failed (check Dsqlstatus, Dcmdstatus, Derror_message)
2197             -2 - bad parameter
2198             -3 - not connected
2199              
2200             =head2 update
2201              
2202             Performs SQL command (assumes UPDATE) and returns number of updated rows.
2203              
2204             String:
2205             update($update_string)
2206              
2207             Args:
2208             $update_str [required] - the SQL command (UPDATE)
2209              
2210             Returns:
2211             >=0 - number of updated rows
2212             -1 - sql command failed (check Dsqlstatus, Dcmdstatus, Derror_message)
2213             -2 - bad parameter
2214             -3 - not connected
2215              
2216             =head2 command
2217              
2218             Performs generic command.
2219              
2220             String:
2221             command($command_string)
2222              
2223             Args:
2224             $command_string [required] - SQL command
2225              
2226             Returns:
2227             >0 - ok
2228             -1 - sql command failed (check Dsqlstatus, Dcmdstatus, Derror_message)
2229             -2 - bad parameter
2230             -3 - not connected
2231              
2232             =head2 func
2233              
2234             Interface to DBH->func().
2235              
2236             Syntax:
2237             func(@func_params)
2238              
2239             Args:
2240             @func_params - parameters for func()
2241              
2242             Returns:
2243             value(s) returned by DBH->func()
2244              
2245             =head2 const
2246              
2247             Interface to DBH->constants.
2248              
2249             Syntax:
2250             const($const_name[, $value])
2251              
2252             Args:
2253             $const_name [required] - constant name
2254             $value - if defined, set constant to this value
2255              
2256             Returns:
2257             constant $const_name value
2258              
2259             =head2 nextval
2260              
2261             Returns next value from sequence.
2262              
2263             Syntax:
2264             nextval($seq_name)
2265              
2266             Args:
2267             $seq_name [required] - sequence name
2268              
2269             Returns:
2270             >0 - next value from sequence
2271             -1 - SQL error (see Derror_message)
2272             -2 - bad parameters
2273             -3 - not connected
2274              
2275             =head2 quote
2276              
2277             Quotes given string(s).
2278              
2279             Note: You should not quote values used in prepared statements.
2280              
2281             Syntax:
2282             quote(@array)
2283              
2284             Args:
2285             @array - array of strings to quote
2286              
2287             Returns:
2288             array with quoted strings
2289              
2290             =head2 date2db
2291              
2292             Formats string (date or datetime) to DB format.
2293              
2294             String:
2295             date2db([$format_type][, @date_value])
2296              
2297             Args:
2298             $format_type - DB format type COMMON [default] or PREPARED [for prepared
2299             statements]
2300             -other parameters are optional, default is now-
2301             1. param - date [dd.mm.yyyy] or datetime [dd.mm.yyyy hh:mm:ss] or seconds
2302             or ! now (date) !! now (datetime)
2303             2. param - minutes
2304             3. param - hours
2305             4. param - day in month
2306             5. param - month (0 will be replaced to 1)
2307             6. param - year (if <1000, 1900 will be added)
2308              
2309             Returns:
2310             according to number of arguments without $format_type if given:
2311             0 - current datetime
2312             1 - input is date(time) string, output date(time)
2313             2 - input is month and year, returns date with last day in month
2314             3 - date
2315             >3 - datetime
2316             undef - bad parameters
2317              
2318             Returned: see above
2319             undef - bad parameters or not connected
2320              
2321             Note:
2322             For driver Must be set To
2323             Pg DBDATESTYLE ISO *)
2324             Oracle NLS_DATE_FORMAT dd.mm.yyyy hh24:mi:ss *)
2325             Informix DBDATE dmy4. *)
2326             Sybase [freedts.conf]
2327             mssql [freedts.conf]
2328              
2329             *) You can use datestyle parameter of L<"new">.
2330              
2331             =head2 db2date
2332              
2333             Formats string from DB format.
2334              
2335             Syntax:
2336             db2date($datetime)
2337              
2338             Args:
2339             $datetime [required] - date(time) from DB
2340              
2341             Returns:
2342             - in the scalar context is returned datetime string
2343             - in the array context is returned array
2344             ($sec, $min, $hour, $day, $mon, $year)
2345             undef or () depend on context
2346             bad parameters or not connected
2347              
2348             Note:
2349             For driver Must be set To
2350             Pg DBDATESTYLE ISO *)
2351             Oracle NLS_DATE_FORMAT dd.mm.yyyy hh24:mi:ss *)
2352             Informix DBDATE dmy4. *)
2353             Sybase [freedts/locales.conf]
2354             mssql [freedts/locales.conf]
2355              
2356             *) You can use datestyle parameter of L<"new">.
2357              
2358             =head2 trace_on
2359              
2360             Interface to DBI->trace().
2361              
2362             Syntax:
2363             trace_on($level, $file)
2364              
2365             Args:
2366             $level - trace level
2367             $file - filename to store log
2368              
2369             Returns:
2370             -nothing-
2371              
2372             Note: See DBI manpage.
2373              
2374             =head2 trace_off
2375              
2376             Stops tracing started by trace_on().
2377              
2378             Syntax:
2379             trace_off()
2380              
2381             Args:
2382             -none-
2383              
2384             Returns:
2385             -nothing-
2386              
2387             =head2 _set_app
2388              
2389             Sets application prefix.
2390              
2391             Syntax:
2392             _set_app($prefix)
2393              
2394             Args:
2395             $prefix - used for statements and cursors
2396              
2397             Returns:
2398             -nothing-
2399              
2400             Note: Default prefix is empty, to set it to this default just call _set_app('').
2401              
2402             =head2 set_stat
2403              
2404             Sets statistics.
2405              
2406             Syntax:
2407             set_stat(type[,max_high[,max_all]])
2408              
2409             Args:
2410             type - type of statistics:
2411             none - no statistics
2412             sums - only sumaries
2413             high - sums & top statements
2414             all - high & all statements
2415             max_high - max. number of stored top statements (default: 3)
2416             max_all - max. number of stored all statements (default: 1000)
2417              
2418             Returns:
2419             -nothing-
2420              
2421             =head2 reset_stat
2422              
2423             Resets statistic counters and arrays.
2424              
2425             Syntax:
2426             reset_stat()
2427              
2428             Args:
2429             -none-
2430              
2431             Returns:
2432             -nothing-
2433              
2434             =head2 get_stat
2435              
2436             Gets module statistics.
2437              
2438             Syntax:
2439             get_stat()
2440              
2441             Args:
2442             -none-
2443              
2444             Returns:
2445             array with statistics:
2446             field 0 ... total time for statements (sums, high, all)
2447             field 1 ... number of performed statements (sums, high, all)
2448             field 2 ... number of errors (sums, high, all)
2449             field 3 ... reference to array with top statements (high, all)
2450             field 4 ... reference to array with all statements (all)
2451              
2452             For field 3 and 4: it's an array of references to hashes with these keys:
2453             type - action performed (SELECT, INSERT, UPDATE, DELETE, COMMAND, PERFORM,
2454             CURSOR_PERFORM, CURSOR_SQL)
2455             sql - SQL command
2456             name - statement name (if any)
2457             par - reference to an array with parameters (if any)
2458             time - time needed to perform statement
2459             error- error string in case of error
2460              
2461             =head2 reset_stat
2462              
2463             Resets local statistics (global leaves untouched).
2464              
2465             Syntax:
2466             reset_stat()
2467              
2468             Args:
2469             -none-
2470              
2471             Returns:
2472             -nothing-
2473              
2474             =head2 test_err
2475              
2476             Test last sqlerror.
2477              
2478             Syntax:
2479             test_err(supp_errs)
2480              
2481             Args:
2482             supp_errs (optional) - list of supp_error (below)
2483             supp_error (optional) - supposed error.
2484             May be: 1 or TABLE_NOEXIST - not existing table (objects)
2485             2 or TABLE_EXIST - table (object) already exists
2486             3 or REC_EXIST - duplicate value in unique key
2487             4 or SCHEMA_NOTEXIST - not existing schema
2488             5 or SCHEMA_EXIST - schema already exists
2489              
2490             4 and 5 are not sopported by some drivers (Oracle, Informix, mysql, mssql).
2491              
2492             Returns:
2493             Without args returns error number 1,2,3,4,5 or -1 (unknown).
2494             With args return the (args) error number (if equal with any) or 0.
2495              
2496              
2497             =head1 AUTHOR
2498              
2499             Originally created by Martin Kula
2500              
2501             Rewritten to object model by Jakub Spicak for masser.
2502              
2503             Delta E.S., Brno (c) 2000-2002.
2504              
2505             =cut