File Coverage

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