File Coverage

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


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