File Coverage

blib/lib/Dimedis/SqlDriver/Informix.pm
Criterion Covered Total %
statement 18 179 10.0
branch 0 54 0.0
condition 0 6 0.0
subroutine 6 20 30.0
pod 0 14 0.0
total 24 273 8.7


line stmt bran cond sub pod time code
1             package Dimedis::SqlDriver::Informix;
2              
3 1     1   1045 use strict;
  1         2  
  1         43  
4 1     1   5 use vars qw($VERSION @ISA);
  1         2  
  1         85  
5              
6             $VERSION = '0.10';
7             @ISA = qw(Dimedis::Sql); # Vererbung von Dimedis::Sql
8              
9 1     1   6 use Carp;
  1         2  
  1         81  
10 1     1   6 use File::Copy;
  1         2  
  1         717  
11 1     1   7 use FileHandle;
  1         2  
  1         65  
12              
13             my $exc = "Dimedis::SqlDriver::Informix:"; # Exception Prefix
14              
15             # offizielles Dimedis::SqlDriver Interface ===========================
16              
17             # install ------------------------------------------------------------
18              
19             sub db_install {
20 0     0 0   my $self = shift;
21            
22 0           return 1; # wg. blob update mit temp table
23              
24 0 0         $self->{debug} && print STDERR "$exc:install\tblob Methode ohne temp. table\n";
25              
26             # erstmal alles löschen
27 0           eval {
28 0           $self->do (
29             sql => "drop table dim_blob_insert"
30             );
31             };
32            
33             # Anlegen der INSERT Dummy Tabelle
34            
35 0           $self->do (
36             sql => "create table dim_blob_insert (".
37             " id serial not null primary key,".
38             " myblob byte, myclob text )"
39             );
40            
41 0           1;
42             }
43              
44             # insert -------------------------------------------------------------
45              
46             sub db_insert {
47 0     0 0   my $self = shift;
48              
49 0           my ($par)= @_;
50 0           $par->{db_action} = "insert";
51            
52 0           $self->db_insert_or_update ($par);
53             }
54              
55             # update -------------------------------------------------------------
56              
57             sub db_update {
58 0     0 0   my $self = shift;
59              
60 0           my ($par)= @_;
61 0           $par->{db_action} = "update";
62            
63 0           $self->db_insert_or_update ($par);
64             }
65              
66             # blob_read ----------------------------------------------------------
67              
68             sub db_blob_read {
69 0     0 0   my $self = shift;
70            
71 0           my ($par) = @_;
72              
73 0           my $filename = $par->{filename};
74 0           my $filehandle = $par->{filehandle};
75            
76 0           my $dbh = $self->{dbh};
77            
78             # das ist einfach! rausSELECTen halt...
79              
80 0 0         my $sth = $dbh->prepare (
81             "select $par->{col}
82             from $par->{table}
83             where $par->{where}"
84             ) or croak "$DBI::errstr";
85            
86 0 0         $sth->execute(@{$par->{params}}) or croak $DBI::errstr;
  0            
87              
88             # Blob lesen
89              
90 0           my $ar = $sth->fetchrow_arrayref;
91 0 0         croak $DBI::errstr if $DBI::errstr;
92 0 0         if ( not defined $ar ) {
93 0           return \"";
94             }
95              
96 0           my $blob = $ar->[0];
97              
98 0 0         $sth->finish or croak $DBI::errstr;
99            
100             # und nun ggf. irgendwo hinschreiben...
101            
102 0 0         if ( $filename ) {
    0          
103 0 0         open (BLOB, "> $filename") or croak "can't write $filename";
104 0           binmode BLOB;
105 0           print BLOB $blob;
106 0           close BLOB;
107 0           $blob = ""; # Speicher wieder freigeben
108             } elsif ( $filehandle ) {
109 0           binmode $filehandle;
110 0           print $filehandle $blob;
111 0           $blob = ""; # Speicher wieder freigeben
112             }
113            
114 0           return \$blob;
115             }
116              
117             # left_outer_join ----------------------------------------------------
118             {
119             my $from;
120             my $where;
121              
122             sub db_left_outer_join {
123 0     0 0   my $self = shift;
124            
125             # static Variablen initialisieren
126            
127 0           $from = "";
128 0           $where = "";
129              
130             # Rekursionsmethode anwerfen
131              
132 0           $self->db_left_outer_join_rec ( @_ );
133            
134             # Dreck bereinigen
135              
136 0           $from =~ s/,$//;
137 0           $from =~ s/,\)/)/g;
138 0           $where =~ s/ AND $//;
139              
140 0           return ($from, $where);
141             }
142              
143             sub db_left_outer_join_rec {
144 0     0 0   my $self = shift;
145              
146 0           my ($lref) = @_;
147            
148             # linke Tabelle in die FROM Zeile
149              
150 0           $from .= $lref->[0].",";
151            
152 0 0         if ( ref $lref->[1] ) {
153             # aha, Outer Join
154 0 0         if ( @{$lref->[1]} > 1 ) {
  0            
155             # kein einfacher Outer Join
156             # (verschachtelt oder outer join gegen
157             # simple join, Fall II/III)
158 0           $from .= "outer (";
159 0           $self->db_left_outer_join_rec ($lref->[1]);
160 0           $from .= ")";
161 0           $where .= $lref->[2]." AND ";
162             } else {
163             # Fall I, outer join einer linken Tabelle
164             # gegen eine oder mehrere rechte Tabellen
165 0           my $i = 1;
166 0           while ($i < @{$lref}) {
  0            
167 0           $from .= " outer ".$lref->[$i]->[0].",";
168 0           $where .= $lref->[$i+1]." AND ";
169 0           $i += 2;
170             }
171             }
172             } else {
173             # noe, kein Outer join
174 0           croak "$exc:db_left_outer_join\tcase III does not exist anymore";
175 0           $from .= $lref->[1];
176 0           $where .= $lref->[2]." AND ";
177             }
178             }
179             }
180              
181             # cmpi ---------------------------------------------------------------
182              
183             sub db_cmpi {
184 0     0 0   my $self = shift;
185 0           my ($par)= @_;
186              
187 1     1   2930 use locale;
  1         2  
  1         8  
188              
189 0           my $val = lc $par->{val};
190 0           $val =~ s/(\w)/"[$1".uc($1)."]"/eg;
  0            
191 0           $val =~ s/\%/*/g;
192 0 0         my $not = $par->{op} eq '!=' ? 'not ' : '';
193              
194 0           return "$not$par->{col} matches ".
195             $self->{dbh}->quote ($val);
196             }
197              
198             # contains -----------------------------------------------------------
199              
200             sub db_contains {
201 0     0 0   my $self = shift;
202            
203 0           my ($par) = @_;
204 0           my $cond;
205              
206             # bei Informix z.Zt. nicht unterstüzt, deshalb undef returnen
207              
208 0           return $cond;
209             }
210              
211             # db_prefix ----------------------------------------------------------
212              
213             sub db_db_prefix {
214 0     0 0   my $self = shift;
215            
216 0           my ($par)= @_;
217              
218 0           return $par->{db}.':';
219              
220 0           1;
221             }
222              
223             # get_features -------------------------------------------------------
224              
225             sub db_get_features {
226 0     0 0   my $self = shift;
227            
228             return {
229 0           serial => 1,
230             blob_read => 1,
231             blob_write => 1,
232             left_outer_join => {
233             simple => 1,
234             nested => 1
235             },
236             cmpi => 1,
237             contains => 0
238             };
239             }
240              
241             # Driverspezifische Hilfsmethoden ====================================
242              
243             # Insert bzw. Update durchführen -------------------------------------
244              
245             sub db_insert_or_update {
246 0     0 0   my $self = shift;
247              
248 0           my ($par) = @_;
249 0           my $type_href = $par->{type};
250              
251 0           my $serial; # evtl. Serial Wert
252 0           my (@columns, @values); # Spaltennamen und -werte
253 0           my $return_value; # serial bei insert,
254             # modified bei update
255            
256             # Parameter aufbereiten
257              
258 0           my ($col, $val);
259 0           my $qm; # Fragezeichen für Parameterbinding
260 0           my %blobs; # Hier werden BLOB Spalten abgelegt, die
261             # nach dem INSERT eingefügt werden
262 0           my $blob_found;
263 0           my $primary_key; # Name der primary key Spalte
264            
265 0           while ( ($col,$val) = each %{$par->{data}} ) {
  0            
266 0           my $type = $type_href->{$col};
267 0           $type =~ s/\[.*//;
268              
269 0 0 0       if ( $type eq 'serial' ) {
    0          
270             # serial Typ bearbeiten
271              
272 0 0         if ( not defined $val ) {
273 0           $serial = 0;
274             } else {
275 0           $serial = $val;
276             }
277 0           push @columns, $col;
278 0           push @values, $serial;
279 0           $qm .= "?,";
280 0           $primary_key = $col;
281            
282             } elsif ( $type eq 'blob' or $type eq 'clob' ) {
283              
284             # Blob muß in jedem Fall im Speicher vorliegen
285            
286 0           $val = $self->db_blob2memory($val);
287              
288 0 0         if ( $par->{db_action} eq 'insert' ) {
289             # Blobs können inline geinsertet werden
290 0           push @columns, $col;
291 0           push @values, $$val;
292 0           $qm .= "?,";
293             } else {
294             # zum Updaten wirds komplizierter!
295             # das machen wir später...
296 0           $blob_found = 1;
297 0           $blobs{$col} = $val;
298             }
299             } else {
300             # alle übrigen Typen werden as is eingefügt
301 0           push @columns, $col;
302 0           push @values, $val;
303 0           $qm .= "?,";
304             }
305             }
306 0           $qm =~ s/,$//; # letztes Komma bügeln
307            
308             # Insert oder Update durchführen
309            
310 0 0         if ( $par->{db_action} eq 'insert' ) {
311             # insert ausführen
312              
313 0           $self->do (
314             sql => "insert into $par->{table} (".
315             join (",",@columns).
316             ") values ($qm)",
317             params => \@values
318             );
319 0           $return_value = $self->{dbh}->{ix_sqlerrd}->[1];
320             } else {
321             # Parameter der where Klausel in @value pushen
322 0           push @values, @{$par->{params}};
  0            
323            
324             # update ausführen, wenn columns da sind
325             # (bei einem reinen BLOB updated passiert es,
326             # daß keine 'normalen' Spalten upgedated werden)
327            
328 0 0         if ( @columns ) {
329 0           $return_value = $self->do (
330             sql => "update $par->{table} set ".
331             join(",", map("$_=?", @columns)).
332             " where $par->{where}",
333             params => \@values
334             );
335             }
336             }
337              
338             # nun evtl. BLOBs verarbeiten (kann nur beim Update passieren)
339            
340 0 0         if ( $blob_found ) {
341 0           while ( ($col,$val) = each %blobs ) {
342 0           $self->db_update_blob (
343             $par->{table},
344             $par->{where},
345             $col, $val,
346             $type_href,
347             $par->{params}
348             );
349             }
350             }
351              
352 0           return $return_value;
353             }
354              
355             # BLOB ins Memory holen, wenn nicht schon da -------------------------
356              
357             sub db_blob2memory {
358 0     0 0   my $self = shift;
359              
360 0           my ($val) = @_;
361              
362 0           my $blob;
363 0 0 0       if ( ref $val and ref $val ne 'SCALAR' ) {
    0          
364             # Referenz und zwar keine Scalarreferenz
365             # => das ist ein Filehandle
366             # => reinlesen den Kram
367 0           binmode $val;
368 0           $$blob = join ("", <$val>);
369             } elsif ( not ref $val ) {
370             # keine Referenz
371             # => Dateiname
372             # => reinlesen den Kram
373 0           my $fh = new FileHandle;
374 0 0         open ($fh, $val) or croak "can't open $val";
375 0           binmode $fh;
376 0           $$blob = join ("", <$fh>);
377 0 0         $self->{debug} && print STDERR "$exc:db_blob2memory: blob_size ($val): ", length($$blob), "\n";
378 0           close $fh;
379             } else {
380             # andernfalls ist val eine Skalarreferenz mit dem Blob
381             # => nix tun
382 0           $blob = $val;
383             }
384              
385 0           return $blob;
386             }
387              
388             # BLOB updaten -------------------------------------------------------
389              
390             sub db_update_blob {
391 0     0 0   my $self = shift;
392              
393 0 0         $self->{debug} && print STDERR "$exc:db_update_blob tmp table entered\n";
394              
395 0           my ($table, $where, $col, $val, $type_href, $param_lref) = @_;
396              
397             # blob oder clob?
398            
399 0 0         my $blob_col = $type_href->{$col} eq 'blob' ? 'myblob' : 'myclob';
400              
401             # temp table anlegen
402            
403 0           $self->do (
404             sql => "create temp table dim_blob_insert (".
405             " myblob byte, myclob text ) with no log"
406             );
407              
408             # dann Blob in temp Table inserten
409              
410 0           $self->do (
411             sql => "insert into dim_blob_insert ($blob_col) ".
412             "values (?)",
413             params => [ $$val ]
414             );
415            
416             # nun von dort aus in die Zieltabelle updaten
417             # FELIX: Einfuegen von Klaus-Fix am 4.8.99.
418             # WHERE clause fehlte...
419            
420 0           $self->do (
421             sql => "update $table set $col = ".
422             "(select $blob_col from dim_blob_insert) where $where",
423             params => $param_lref
424             );
425              
426             # und die temp. Tabelle löschen
427            
428 0           $self->do (
429             sql => "drop table dim_blob_insert"
430             );
431              
432 0           1;
433             }
434              
435             # this is currently disabled
436              
437             sub db_update_blob_with_fix_installed_table {
438 0     0 0   my $self = shift;
439              
440 0 0         $self->{debug} && print STDERR "$exc:db_update_blob entered\n";
441              
442 0           my ($table, $where, $col, $val, $type_href, $param_lref) = @_;
443              
444             # blob oder clob?
445            
446 0 0         my $blob_col = $type_href->{$col} eq 'blob' ? 'myblob' : 'myclob';
447              
448             # erstmal Blob in Dummy Table inserten
449              
450 0           $self->do (
451             sql => "insert into dim_blob_insert (id, $blob_col) ".
452             "values (0, ?)",
453             params => [ $$val ]
454             );
455            
456 0           my $id = $self->{dbh}->{ix_sqlerrd}->[1];
457            
458             # nun von dort aus in die Zieltabelle updaten
459            
460 0           $self->do (
461             sql => "update $table set $col = ".
462             "(select $blob_col from dim_blob_insert ".
463             " where id=$id)"
464             );
465              
466             # und aus der Dummy Tabelle löschen
467            
468 0           $self->do (
469             sql => "delete from dim_blob_insert where id=$id"
470             );
471              
472 0           1;
473             }
474              
475             1;
476              
477             __END__