File Coverage

blib/lib/Rose/DB/Informix.pm
Criterion Covered Total %
statement 47 344 13.6
branch 0 172 0.0
condition 1 75 1.3
subroutine 16 72 22.2
pod 26 51 50.9
total 90 714 12.6


line stmt bran cond sub pod time code
1             package Rose::DB::Informix;
2              
3 16     16   116 use strict;
  16         38  
  16         552  
4              
5 16     16   100 use Rose::DateTime::Util();
  16         34  
  16         754  
6              
7             our $VERSION = '0.774';
8              
9             our $Debug = 0;
10              
11             use Rose::Class::MakeMethods::Generic
12             (
13 16         133 inheritable_scalar =>
14             [
15             'max_array_characters',
16             'default_supports_limit_with_offset',
17             ],
18 16     16   94 );
  16         38  
19              
20             __PACKAGE__->max_array_characters(255);
21              
22             #
23             # Object methods
24             #
25              
26             sub build_dsn
27             {
28 10     10 0 87 my($self_or_class, %args) = @_;
29 10   33     152 return "dbi:Informix:" . ($args{'db'} || $args{'database'});
30             }
31              
32 0 0   0 0   sub last_insertid_from_sth { $_[1]->{'ix_sqlerrd'}[1] || $_[1]->{'ix_serial8'} }
33              
34 0     0 0   sub likes_lowercase_table_names { 1 }
35 0     0 0   sub generate_primary_key_values { return; } # old perls seem to like this...
36              
37             sub generate_primary_key_placeholders
38             {
39 0 0 0 0 0   (@_ == 1 || (@_ > 1 && $_[1] == 1)) ? 0 : ((undef) x $_[1])
40             }
41              
42             # Informix doesn't like anything to be quoted and appears to
43             # accept everything without quotes.
44 0     0 0   sub is_reserved_word { 0 }
45              
46             sub refine_dbi_column_info
47             {
48 0     0 0   my($self, $col_info, $meta) = @_;
49              
50 0           my $method = ref($self)->parent_class . '::refine_dbi_column_info';
51              
52 16     16   7190 no strict 'refs';
  16         42  
  16         31842  
53 0           $self->$method($col_info);
54              
55 0           my $type_name = $col_info->{'TYPE_NAME'};
56              
57             # Handle "INT8" big integers
58 0 0 0       if($type_name eq 'int' && $col_info->{'informix_collength'} == 10)
59             {
60 0           $col_info->{'TYPE_NAME'} = 'bigint';
61             }
62              
63 0           return;
64             }
65              
66             # Boolean formatting and parsing
67              
68 0 0   0 0   sub format_boolean { $_[1] ? 't' : 'f' }
69              
70             sub parse_boolean
71             {
72 0     0 1   my($self, $value) = @_;
73 0 0 0       return $value if($self->validate_boolean_keyword($_[1]) ||
      0        
74             ($self->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/));
75 0 0         return 1 if($value =~ /^[t1]$/i);
76 0 0         return 0 if($value =~ /^[f0]$/i);
77              
78 0           $self->error("Invalid boolean value: '$value'");
79 0           return undef;
80             }
81              
82             # Date formatting
83              
84             sub format_date
85             {
86 0 0   0 1   return $_[1] if($_[0]->validate_date_keyword($_[1]));
87 0           return Rose::DateTime::Util::format_date($_[1], '%m/%d/%Y');
88             }
89              
90             sub format_datetime
91             {
92 0 0   0 1   return $_[1] if($_[0]->validate_datetime_keyword($_[1]));
93 0           return Rose::DateTime::Util::format_date($_[1], '%Y-%m-%d %H:%M:%S');
94             }
95              
96             sub format_datetime_year_to_second
97             {
98 0 0   0 1   return $_[1] if($_[0]->validate_datetime_keyword($_[1]));
99 0           return Rose::DateTime::Util::format_date($_[1], '%Y-%m-%d %H:%M:%S');
100             }
101              
102             sub format_datetime_year_to_minute
103             {
104 0 0   0 1   return $_[1] if($_[0]->validate_datetime_keyword($_[1]));
105 0           return Rose::DateTime::Util::format_date($_[1], '%Y-%m-%d %H:%M');
106             }
107              
108             sub format_datetime_year_to_month
109             {
110 0 0   0 1   return $_[1] if($_[0]->validate_datetime_keyword($_[1]));
111 0           return Rose::DateTime::Util::format_date($_[1], '%Y-%m');
112             }
113              
114             # sub format_time
115             # {
116             # return $_[1] if($_[0]->validate_time_keyword($_[1]));
117             # return Rose::DateTime::Util::format_date($_[1], '%H:%M:%S');
118             # }
119              
120             sub format_timestamp
121             {
122 0 0   0 1   return $_[1] if($_[0]->validate_timestamp_keyword($_[1]));
123 0           return Rose::DateTime::Util::format_date($_[1], '%Y-%m-%d %H:%M:%S.%5N');
124             }
125              
126             sub format_datetime_year_to_fraction
127             {
128 0     0 1   my($self, $dt, $fraction) = @_;
129              
130 0   0       $fraction ||= 3;
131              
132 0 0         return $dt if($self->validate_datetime_year_to_fraction_keyword($dt));
133 0           return Rose::DateTime::Util::format_date($dt, "%Y-%m-%d %H:%M:%S.%${fraction}N");
134             }
135              
136 0     0 0   sub format_datetime_year_to_fraction_1 { format_datetime_year_to_fraction(@_, 1) }
137 0     0 0   sub format_datetime_year_to_fraction_2 { format_datetime_year_to_fraction(@_, 2) }
138 0     0 0   sub format_datetime_year_to_fraction_3 { format_datetime_year_to_fraction(@_, 3) }
139 0     0 0   sub format_datetime_year_to_fraction_4 { format_datetime_year_to_fraction(@_, 4) }
140 0     0 0   sub format_datetime_year_to_fraction_5 { format_datetime_year_to_fraction(@_, 5) }
141              
142             # Date parsing
143              
144             sub parse_date
145             {
146 0     0 1   my($self, $value) = @_;
147              
148 0 0 0       if(UNIVERSAL::isa($value, 'DateTime') ||
149             $self->validate_date_keyword($value))
150             {
151 0           return $value;
152             }
153              
154 0           my($error, $dt);
155              
156             TRY:
157             {
158 0           local $@;
  0            
159 0           eval { $dt = Rose::DateTime::Util::parse_date($value) };
  0            
160 0           $error = $@;
161             }
162              
163 0 0         if($error)
164             {
165 0           $self->error("Could not parse date '$value' - $error");
166 0           return undef;
167             }
168              
169 0           return $dt;
170             }
171              
172             sub parse_datetime
173             {
174 0     0 1   my($self, $value) = @_;
175              
176 0 0 0       if(UNIVERSAL::isa($value, 'DateTime') ||
177             $self->validate_datetime_keyword($value))
178             {
179 0           return $value;
180             }
181              
182 0           my($error, $dt);
183              
184             TRY:
185             {
186 0           local $@;
  0            
187 0           eval { $dt = Rose::DateTime::Util::parse_date($value) };
  0            
188 0           $error = $@;
189             }
190              
191 0 0         if($error)
192             {
193 0           $self->error("Could not parse datetime '$value' - $error");
194 0           return undef;
195             }
196              
197 0           return $dt;
198             }
199              
200             sub parse_datetime_year_to_second
201             {
202 0     0 1   my($self, $value) = @_;
203              
204 0 0 0       if(UNIVERSAL::isa($value, 'DateTime') ||
205             $self->validate_datetime_year_to_second_keyword($value))
206             {
207 0           return $value;
208             }
209              
210 0           my($error, $dt);
211              
212             TRY:
213             {
214 0           local $@;
  0            
215 0           eval { $dt = Rose::DateTime::Util::parse_date($value) };
  0            
216 0           $error = $@;
217             }
218              
219 0 0         if($error)
220             {
221 0           $self->error("Could not parse datetime year to second '$value' - $error");
222 0           return undef;
223             }
224              
225 0 0         $dt->truncate(to => 'second') if(ref $dt);
226              
227 0           return $dt;
228             }
229              
230             sub parse_datetime_year_to_fraction
231             {
232 0     0 1   my($self, $arg, $fraction) = @_;
233              
234 0 0         return $arg if($self->validate_datetime_year_to_fraction_keyword($arg));
235              
236 0   0       $fraction ||= 3;
237              
238 0           my($error, $dt);
239              
240             TRY:
241             {
242 0           local $@;
  0            
243 0           eval { $dt = Rose::DateTime::Util::parse_date($arg) };
  0            
244 0           $error = $@;
245             }
246              
247 0 0         if($error)
248             {
249 0           $self->error("Could not parse datetime year to fraction '$arg' - $error");
250 0           return undef;
251             }
252              
253 0 0         if(ref $dt)
254             {
255             # Truncate nanosecs to correct fraction. (Yes, using strings. I am lame.)
256 0           my $n = sprintf('%09d', $dt->nanosecond);
257 0           $n = substr($n, 0, $fraction);
258              
259 0 0         if(length $n < 9)
260             {
261 0           $n .= ('0' x (9 - length $n));
262             }
263              
264 0           $dt->set_nanosecond($n);
265             }
266              
267 0           return $dt;
268             }
269              
270 0     0     *parse_datetime_year_to_fraction_1 = sub { parse_datetime_year_to_fraction(@_, 1) };
271 0     0     *parse_datetime_year_to_fraction_2 = sub { parse_datetime_year_to_fraction(@_, 2) };
272 0     0     *parse_datetime_year_to_fraction_3 = sub { parse_datetime_year_to_fraction(@_, 3) };
273 0     0     *parse_datetime_year_to_fraction_4 = sub { parse_datetime_year_to_fraction(@_, 4) };
274 0     0     *parse_datetime_year_to_fraction_5 = sub { parse_datetime_year_to_fraction(@_, 5) };
275              
276             sub parse_datetime_year_to_minute
277             {
278 0     0 1   my($self, $value) = @_;
279              
280 0 0 0       if(UNIVERSAL::isa($value, 'DateTime') ||
281             $self->validate_datetime_year_to_minute_keyword($value))
282             {
283 0           return $value;
284             }
285              
286 0           my($error, $dt);
287              
288             TRY:
289             {
290 0           local $@;
  0            
291 0           eval { $dt = Rose::DateTime::Util::parse_date($value) };
  0            
292 0           $error = $@;
293             }
294              
295 0 0         if($error)
296             {
297 0           $self->error("Could not parse datetime year to minute '$value' - $error");
298 0           return undef;
299             }
300              
301 0 0         $dt->truncate(to => 'minute') if(ref $dt);
302              
303 0           return $dt;
304             }
305              
306             sub parse_datetime_year_to_month
307             {
308 0     0 1   my($self, $value) = @_;
309              
310 0 0 0       if(UNIVERSAL::isa($value, 'DateTime') ||
311             $self->validate_datetime_year_to_month_keyword($value))
312             {
313 0           return $value;
314             }
315              
316 0 0         if($value =~ m{^(\d\d?)/(\d{4})$})
    0          
317             {
318             # Add day to MM/YYYY
319 0           $value = "$1/01/$2";
320             }
321             elsif($value =~ /^\d{4}-\d\d$/)
322             {
323             # Append day to YYYY-MM
324 0           $value .= '-01';
325             }
326              
327 0           my($error, $dt);
328              
329             TRY:
330             {
331 0           local $@;
  0            
332 0           eval { $dt = Rose::DateTime::Util::parse_date($value) };
  0            
333 0           $error = $@;
334             }
335              
336 0 0         if($error)
337             {
338 0           $self->error("Could not parse datetime year to month '$value' - $error");
339 0           return undef;
340             }
341              
342 0 0         $dt->truncate(to => 'month') if(ref $dt);
343              
344 0           return $dt;
345             }
346              
347             sub parse_timestamp
348             {
349 0     0 1   my($self, $value) = @_;
350              
351 0 0 0       if(UNIVERSAL::isa($value, 'DateTime') ||
352             $self->validate_timestamp_keyword($value))
353             {
354 0           return $value;
355             }
356              
357 0           my($error, $dt);
358              
359             TRY:
360             {
361 0           local $@;
  0            
362 0           eval { $dt = Rose::DateTime::Util::parse_date($value) };
  0            
363 0           $error = $@;
364             }
365              
366 0 0         if($error)
367             {
368 0           $self->error("Could not parse timestamp '$value' - $error");
369 0           return undef;
370             }
371              
372 0           return $dt;
373             }
374              
375             sub validate_date_keyword
376             {
377 16     16   153 no warnings;
  16         66  
  16         3169  
378 0 0 0 0 1   $_[1] =~ /^(?:current|today)$/i ||
379             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
380             }
381              
382             sub validate_time_keyword
383             {
384 16     16   136 no warnings;
  16         33  
  16         2344  
385 0 0 0 0 0   lc $_[1] eq 'current' ||
386             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
387             }
388              
389             sub validate_timestamp_keyword
390             {
391 16     16   133 no warnings;
  16         30  
  16         3346  
392 0 0 0 0 1   $_[1] =~ /^(?:current(?: +year +to +(?:fraction(?:\([1-5]\))?|second|minute|hour|day|month))?|today)$/i ||
393             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
394             }
395              
396             sub validate_datetime_year_to_fraction_keyword
397             {
398 16     16   126 no warnings;
  16         52  
  16         3559  
399 0 0 0 0 1   $_[1] =~ /^(?:current(?: +year +to +(?:fraction(?:\([1-5]\))?|second|minute|hour|day|month))?|today)$/i ||
400             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
401             }
402              
403             sub validate_datetime_keyword
404             {
405 16     16   127 no warnings;
  16         34  
  16         3029  
406 0 0 0 0 1   $_[1] =~ /^(?:current(?: +year +to +(?:second|minute|hour|day|month))?|today)$/i ||
407             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
408             }
409              
410             sub validate_datetime_year_to_second_keyword
411             {
412 16     16   129 no warnings;
  16         39  
  16         3038  
413 0 0 0 0 1   $_[1] =~ /^(?:current(?: +year +to +(?:second|minute|hour|day|month))?|today)$/i ||
414             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
415             }
416              
417             sub validate_datetime_year_to_minute_keyword
418             {
419 16     16   124 no warnings;
  16         37  
  16         2987  
420 0 0 0 0 1   $_[1] =~ /^(?:current(?: +year +to +(?:second|minute|hour|day|month))?|today)$/i ||
421             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
422             }
423              
424             sub validate_datetime_year_to_month_keyword
425             {
426 16     16   124 no warnings;
  16         42  
  16         4853  
427 0 0 0 0 1   $_[1] =~ /^(?:current(?: +year +to +(?:second|minute|hour|day|month))?|today)$/i ||
428             ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/);
429             }
430              
431 0     0 0   sub should_inline_date_keyword { 1 }
432 0     0 0   sub should_inline_datetime_keyword { 1 }
433 0     0 0   sub should_inline_time_keyword { 1 }
434 0     0 0   sub should_inline_timestamp_keyword { 1 }
435              
436             sub parse_set
437             {
438 0     0 1   my($self) = shift;
439              
440 0 0         return $_[0] if(ref $_[0] eq 'ARRAY');
441              
442 0 0 0       if(@_ > 1 && !ref $_[1])
443             {
444 0           pop(@_);
445 0           return [ @_ ];
446             }
447              
448 0           my $val = $_[0];
449              
450 0 0         return undef unless(defined $val);
451              
452 0 0         my $options = ref $_[-1] eq 'HASH' ? $_[-1] : {};
453              
454 16     16   135 no warnings 'uninitialized';
  16         43  
  16         16644  
455             my $numeric =
456 0 0         ($options->{'value_type'} =~ /^(?:(?:big)?(?:float|int(?:eger)?|num(?:eric)?)|decimal)$/i) ? 1 : 0;
457              
458 0 0         return undef unless(defined $val);
459              
460 0           $val =~ s/^SET\{(.*)\}$/$1/;
461              
462 0           my @set;
463              
464 0           while($val =~ s/(?:'((?:[^'\\]+|\\.)*)'|([^',]+))(?:,|$)//)
465             {
466 0 0         push(@set, (defined $1) ? $1 : $2);
467              
468 0 0         if($numeric)
469             {
470 0           $set[-1] =~ s/\s+//g;
471             }
472             }
473              
474 0           return \@set;
475             }
476              
477             sub format_set
478             {
479 0     0 1   my($self) = shift;
480              
481 0 0         my @set = (ref $_[0]) ? @{$_[0]} : @_;
  0            
482              
483 0 0 0       return undef unless(@set && defined $set[0]);
484              
485             return 'SET{' . join(',', map
486             {
487 0 0         if(!defined $_)
  0 0          
488             {
489 0           Carp::croak 'Undefined value found in array or list passed to ',
490             __PACKAGE__, '::format_set()';
491             }
492             elsif(/^[-+]?\d+(?:\.\d*)?$/)
493             {
494 0           $_
495             }
496             else
497             {
498 0           s/\\/\\\\/g;
499 0           s/'/\\'/g;
500 0           qq('$_')
501             }
502             } @set) . '}';
503             }
504              
505             sub parse_array
506             {
507 0     0 1   my($self) = shift;
508              
509 0 0         return $_[0] if(ref $_[0]);
510 0 0         return [ @_ ] if(@_ > 1);
511              
512 0           my $val = $_[0];
513              
514 0 0         return undef unless(defined $val);
515              
516 0           $val =~ s/^\{(.*)\}$/$1/;
517              
518 0           my @array;
519              
520 0           while($val =~ s/(?:"((?:[^"\\]+|\\.)*)"|([^",]+))(?:,|$)//)
521             {
522 0 0         push(@array, (defined $1) ? $1 : $2);
523             }
524              
525 0           return \@array;
526             }
527              
528             sub format_array
529             {
530 0     0 1   my($self) = shift;
531              
532 0 0         my @array = (ref $_[0]) ? @{$_[0]} : @_;
  0            
533              
534 0 0 0       return undef unless(@array && defined $array[0]);
535              
536             my $str = '{' . join(',', map
537             {
538 0 0         if(!defined $_)
  0 0          
539             {
540 0           Carp::croak 'Undefined value found in array or list passed to ',
541             __PACKAGE__, '::format_array()';
542             }
543             elsif(/^[-+]?\d+(?:\.\d*)?$/)
544             {
545 0           $_
546             }
547             else
548             {
549 0           s/\\/\\\\/g;
550 0           s/"/\\"/g;
551 0           qq("$_")
552             }
553             } @array) . '}';
554              
555 0 0         if(length($str) > $self->max_array_characters)
556             {
557 0           Carp::croak "Array string is longer than ", ref($self),
558             "->max_array_characters (", $self->max_array_characters,
559             ") characters long: $str";
560             }
561              
562 0           return $str;
563             }
564              
565             sub next_value_in_sequence
566             {
567 0     0 0   my($self, $seq) = @_;
568              
569 0 0         my $dbh = $self->dbh or return undef;
570              
571 0           my($error, $id);
572              
573             TRY:
574             {
575 0           local $@;
  0            
576              
577             eval
578 0           {
579 0           my $sth = $dbh->prepare(qq(SELECT nextval('$seq')));
580 0           $sth->execute;
581 0           $id = ${$sth->fetchrow_arrayref}[0];
  0            
582             };
583              
584 0           $error = $@;
585             }
586              
587 0 0         if($error)
588             {
589 0           $self->error("Could not get the next value in the sequence '$seq' - $error");
590 0           return undef;
591             }
592              
593 0           return $id;
594             }
595              
596 16         1401 use constant VERSION_SQL =>
597 16     16   141 q(SELECT FIRST 1 DBINFO('version', 'major') from 'informix'.systables);
  16         41  
598              
599             our %Major_Version_Cache;
600              
601 16     16   146 use constant MAX_TO_CACHE => 500;
  16         41  
  16         17254  
602              
603             sub supports_limit_with_offset
604             {
605 0     0 0   my($self) = shift;
606              
607 0           my $ok = ref($self)->default_supports_limit_with_offset;
608 0 0         return $ok if(defined $ok);
609              
610 0 0         my $dbh = $self->dbh or return 0;
611              
612 0 0         unless(defined $Major_Version_Cache{$dbh})
613             {
614 0           my $version;
615              
616             TRY:
617             {
618 0           local $@;
  0            
619              
620             eval
621 0           {
622 0 0         $Debug && warn VERSION_SQL, "\n";
623 0           my $sth = $dbh->prepare(VERSION_SQL);
624 0           $sth->execute;
625 0           ($version) = $sth->fetchrow_array;
626             };
627              
628             # Intentionally ignore any errors
629             }
630              
631 0 0         %Major_Version_Cache = () if(keys %Major_Version_Cache > MAX_TO_CACHE);
632 0   0       $Major_Version_Cache{$dbh} = $version || 0;
633             }
634              
635 0 0         return $Major_Version_Cache{$dbh} >= 10 ? 1 : 0;
636 0           return 0;
637             }
638              
639              
640             sub format_limit_with_offset
641             {
642 0     0 0   my($self, $limit, $offset, $args) = @_;
643              
644 0           delete $args->{'limit'};
645 0           delete $args->{'offset'};
646              
647 0 0         if(defined $offset)
648             {
649 0           $args->{'limit_prefix'} = "SKIP $offset FIRST $limit";
650             }
651             else
652             {
653 0           $args->{'limit_prefix'} = "FIRST $limit";
654             }
655             }
656              
657 0     0 0   sub supports_select_from_subselect { 0 } # can't handle serial columns in multiset
658 0     0 0   sub format_select_from_subselect { "\nTABLE(MULTISET(($_[1])))\n " }
659              
660             sub format_select_start_sql
661             {
662 0     0 0   my($self, $hints) = @_;
663              
664 0 0         return 'SELECT' unless($hints);
665              
666             my $comment =
667             join(' ', ($hints->{'comment'} ? $hints->{'comment'} : ()),
668 0 0         (map { $hints->{$_} ? uc("+$_") : () } qw(first_rows all_rows)));
  0 0          
669              
670 0           return "SELECT {$comment}";
671             }
672              
673             #
674             # Introspection
675             #
676              
677             sub list_tables
678             {
679 0     0 0   my($self, %args) = @_;
680              
681 0           my(@tables, $error);
682              
683             TRY:
684             {
685 0           local $@;
  0            
686              
687             eval
688 0           {
689 0 0         my $dbh = $self->dbh or die $self->error;
690              
691 0           local $dbh->{'RaiseError'} = 1;
692              
693 0           my @table_info = $dbh->func('user', '_tables');
694              
695 0           my $schema = $self->schema;
696              
697             #if($args{'include_views'})
698             #{
699             # my @view_info = $dbh->func('view', '_tables');
700             # push(@table_info, @view_info);
701             #}
702              
703 0           my %seen;
704              
705 0           foreach my $item (@table_info)
706             {
707             # From DBD::Informix::Metadata:
708             #
709             # The owner name will be enclosed in double quotes; if it contains
710             # double quotes, those will be doubled up as required by SQL. The
711             # table name will only be enclosed in double quotes if it is not a
712             # valid C identifier (meaning, it starts with an alphabetic
713             # character or underscore, and continues with alphanumeric
714             # characters or underscores). If it is enclosed in double quotes,
715             # any embedded double quotes are doubled up.
716             #
717             # "jsiracusa ".test
718              
719 0 0         if($item =~ /^(?: "((?:""|[^"]+)+)" | ([^"]+) ) \. (?: "((?:""|[^"]+)+)" | ([^"]+) )$/x)
720             {
721 0 0         my $user = defined $1 ? $1 : $2;
722 0 0         my $table = defined $3 ? $3 : $4;
723              
724 0           for($user, $table)
725             {
726 0           s/""/"/g;
727             }
728              
729 0 0         next if($seen{$table}++);
730              
731 0 0 0       if(!defined $schema || $schema eq $user)
732             {
733 0           push(@tables, $table);
734             }
735             }
736             else
737             {
738 0           Carp::carp "Could not parse table information: $item";
739             }
740             }
741             };
742              
743 0           $error = $@;
744             }
745              
746 0 0         if($error)
747             {
748 0           Carp::croak "Could not list tables from ", $self->dsn, " - $error";
749             }
750              
751 0 0         return wantarray ? @tables : \@tables;
752             }
753              
754             sub _get_primary_key_column_names
755             {
756 0     0     my($self, $catalog, $schema, $table_arg) = @_;
757              
758 0           require DBD::Informix::Metadata;
759              
760 0 0         my $dbh = $self->dbh or die $self->error;
761              
762 0           local $dbh->{'FetchHashKeyName'} = 'NAME';
763              
764             # We need the table owner. Asking for column information is the only
765             # way I know of to reliably get this information.
766             #
767             # Informix does not support DBI's column_info() method so we have
768             # to get all that into "the hard way."
769             #
770             # Each item in @col_list is a reference to an array of values:
771             #
772             # 0 owner name
773             # 1 table name
774             # 2 column number
775             # 3 column name
776             # 4 data type (encoded)
777             # 5 data length (encoded)
778             #
779 0           my @col_list = DBD::Informix::Metadata::ix_columns($dbh, $table_arg);
780              
781 0           my $owner = $col_list[0][0];
782 0           my $table = $col_list[0][1]; # just in case...
783              
784 0 0         unless(defined $owner)
785             {
786             #die "Could not find owner for table ", $table;
787              
788             # Failure to find an owner is sometimes caused by
789             # DBD::Informix::Metadata's annoying habit of returning
790             # sequences along with the list of tables. So we'll just
791             # say that it has no primary key columns.
792 0           return [];
793             }
794              
795             # Then comes this monster query to get the primary key column names.
796             # I'd love to know a better/easier way to do this...
797 0           my $pk_sth = $dbh->prepare(<<'EOF');
798             SELECT
799             col.colname
800             FROM
801             informix.sysconstraints con,
802             informix.systables tab,
803             informix.sysindexes idx,
804             informix.syscolumns col
805             WHERE
806             constrtype = 'P' AND
807             con.tabid = tab.tabid AND
808             con.tabid = idx.tabid AND
809             con.tabid = col.tabid AND
810             con.idxname = idx.idxname
811             AND
812             (
813             col.colno = idx.part1 OR
814             col.colno = idx.part2 OR
815             col.colno = idx.part3 OR
816             col.colno = idx.part4 OR
817             col.colno = idx.part5 OR
818             col.colno = idx.part6 OR
819             col.colno = idx.part7 OR
820             col.colno = idx.part8 OR
821             col.colno = idx.part9 OR
822             col.colno = idx.part10 OR
823             col.colno = idx.part11 OR
824             col.colno = idx.part12 OR
825             col.colno = idx.part13 OR
826             col.colno = idx.part14 OR
827             col.colno = idx.part15 OR
828             col.colno = idx.part16
829             )
830             AND
831             tab.tabname = ? AND
832             tab.owner = ?
833             EOF
834              
835 0           $pk_sth->execute($table, $owner);
836              
837 0           my(@columns, $column);
838              
839 0           $pk_sth->bind_columns(\$column);
840              
841 0           while($pk_sth->fetch)
842             {
843 0           push(@columns, $column);
844             }
845              
846 0           return \@columns;
847             }
848              
849             1;
850              
851             __END__
852              
853             =head1 NAME
854              
855             Rose::DB::Informix - Informix driver class for Rose::DB.
856              
857             =head1 SYNOPSIS
858              
859             use Rose::DB;
860              
861             Rose::DB->register_db(
862             domain => 'development',
863             type => 'main',
864             driver => 'Informix',
865             database => 'dev_db',
866             host => 'localhost',
867             username => 'devuser',
868             password => 'mysecret',
869             server_time_zone => 'UTC',
870             );
871              
872              
873             Rose::DB->default_domain('development');
874             Rose::DB->default_type('main');
875             ...
876              
877             # Set max length of varchar columns used to emulate the array data type
878             Rose::DB::Informix->max_array_characters(128);
879              
880             $db = Rose::DB->new; # $db is really a Rose::DB::Informix-derived object
881              
882             $dt = $db->parse_datetime_year_to_minute(...);
883             $val = $db->format_datetime_year_to_minute($dt);
884              
885             $dt = $db->parse_datetime_year_to_second(...);
886             $val = $db->format_datetime_year_to_second($dt);
887             ...
888              
889             =head1 DESCRIPTION
890              
891             L<Rose::DB> blesses objects into a class derived from L<Rose::DB::Informix> when the L<driver|Rose::DB/driver> is "informix". This mapping of driver names to class names is configurable. See the documentation for L<Rose::DB>'s L<new()|Rose::DB/new> and L<driver_class()|Rose::DB/driver_class> methods for more information.
892              
893             This class cannot be used directly. You must use L<Rose::DB> and let its L<new()|Rose::DB/new> method return an object blessed into the appropriate class for you, according to its L<driver_class()|Rose::DB/driver_class> mappings.
894              
895             Only the methods that are new or have different behaviors than those in L<Rose::DB> are documented here. See the L<Rose::DB> documentation for the full list of methods.
896              
897             =head1 CLASS METHODS
898              
899             =over 4
900              
901             =item B<default_supports_limit_with_offset [BOOL]>
902              
903             Get or set a boolean value that indicates whether or not all Informix databases that you plan to connect to support the "SELECT SKIP N FIRST M ..." syntax. If undefined, this feature will be looked up on a per-connection basis as needed. The default is undefined.
904              
905             =item B<max_array_characters [INT]>
906              
907             Get or set the maximum length of varchar columns used to emulate the array data type. The default value is 255.
908              
909             Informix does not have a native "ARRAY" data type, but it can be emulated using a "VARCHAR" column and a specially formatted string. The formatting and parsing of this string is handled by the C<format_array()> and C<parse_array()> object methods. The maximum length limit is honored by the C<format_array()> object method.
910              
911             Informix does have a native "SET" data type, serviced by the C<parse_set()> and C<format_set()> object methods. This is a better choice than the emulated array data type if you don't care about the order of the stored values.
912              
913             =back
914              
915             =head1 OBJECT METHODS
916              
917             =head2 Value Parsing and Formatting
918              
919             =over 4
920              
921             =item B<format_array ARRAYREF | LIST>
922              
923             Given a reference to an array or a list of values, return a specially formatted string. Undef is returned if ARRAYREF points to an empty array or if LIST is not passed. The array or list must not contain undefined values.
924              
925             If the resulting string is longer than C<max_array_characters()>, a fatal error will occur.
926              
927             =item B<format_date DATETIME>
928              
929             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATE" data type.
930              
931             =item B<format_datetime DATETIME>
932              
933             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO SECOND" data type.
934              
935             =item B<format_datetime_year_to_fraction DATETIME>
936              
937             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO FRACTION" data type.
938              
939             =item B<format_datetime_year_to_fraction_[1-5] DATETIME>
940              
941             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO FRACTION(N)" data type, where N is an integer from 1 to 5.
942              
943             =item B<format_datetime_year_to_minute DATETIME>
944              
945             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO MINUTE" data type.
946              
947             =item B<format_datetime_year_to_month DATETIME>
948              
949             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO MONTH" data type.
950              
951             =item B<format_datetime_year_to_second DATETIME>
952              
953             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO SECOND" data type.
954              
955             =item B<format_set ARRAYREF | LIST>
956              
957             Given a reference to an array or a list of values, return a string formatted according to the rules of Informix's "SET" data type. Undef is returned if ARRAYREF points to an empty array or if LIST is not passed. If the array or list contains undefined values, a fatal error will occur.
958              
959             =item B<format_timestamp DATETIME>
960              
961             Converts the L<DateTime> object DATETIME into the appropriate format for the "DATETIME YEAR TO FRACTION(5)" data type.
962              
963             =item B<parse_array STRING | LIST | ARRAYREF>
964              
965             Parse STRING and return a reference to an array. STRING should be formatted according to the Informix array data type emulation format returned by C<format_array()>. Undef is returned if STRING is undefined.
966              
967             If a LIST of more than one item is passed, a reference to an array containing the values in LIST is returned.
968              
969             If a an ARRAYREF is passed, it is returned as-is.
970              
971             =item B<parse_boolean STRING>
972              
973             Parse STRING and return a boolean value of 1 or 0. STRING should be formatted according to Informix's native "boolean" data type. Acceptable values are 't', 'T', or '1' for true, and 'f', 'F', or '0' for false.
974              
975             If STRING is a valid boolean keyword (according to L<validate_boolean_keyword|/validate_boolean_keyword>) or if it looks like a function call (matches /^\w+\(.*\)$/) and L<keyword_function_calls|Rose::DB/keyword_function_calls> is true, then it is returned unmodified. Returns undef if STRING could not be parsed as a valid "boolean" value.
976              
977             =item B<parse_date STRING>
978              
979             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATE" data type.
980              
981             If STRING is a valid date keyword (according to L<validate_date_keyword|/validate_date_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATE" value.
982              
983             =item B<parse_datetime STRING>
984              
985             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO SECOND" data type.
986              
987             If STRING is a valid "datetime year to second" keyword (according to L<validate_datetime_year_to_second_keyword|/validate_datetime_year_to_second_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO SECOND" value.
988              
989             =item B<parse_datetime_year_to_fraction STRING>
990              
991             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO FRACTION" data type.
992              
993             If STRING is a valid "datetime year to fraction" keyword (according to L<validate_datetime_year_to_fraction_keyword|/validate_datetime_year_to_fraction_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO FRACTION" value.
994              
995             =item B<parse_datetime_year_to_fraction_[1-5] STRING>
996              
997             These five methods parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO FRACTION(N)" data type, where N is an integer from 1 to 5.
998              
999             If STRING is a valid "datetime year to fraction" keyword (according to L<validate_datetime_year_to_fraction_keyword|/validate_datetime_year_to_fraction_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO FRACTION(N)" value.
1000              
1001             =item B<parse_datetime_year_to_minute STRING>
1002              
1003             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO MINUTE" data type.
1004              
1005             If STRING is a valid "datetime year to minute" keyword (according to L<validate_datetime_year_to_minute_keyword|/validate_datetime_year_to_minute_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO MINUTE" value.
1006              
1007             =item B<parse_datetime_year_to_month STRING>
1008              
1009             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO MINUTE" data type.
1010              
1011             If STRING is a valid "datetime year to month" keyword (according to L<validate_datetime_year_to_month_keyword|/validate_datetime_year_to_month_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO MONTH" value.
1012              
1013             =item B<parse_datetime_year_to_second STRING>
1014              
1015             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO SECOND" data type.
1016              
1017             If STRING is a valid "datetime year to second" keyword (according to L<validate_datetime_year_to_second_keyword|/validate_datetime_year_to_second_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO SECOND" value.
1018              
1019             =item B<parse_set STRING | LIST | ARRAYREF>
1020              
1021             Parse STRING and return a reference to an array. STRING should be formatted according to Informix's "SET" data type. Undef is returned if STRING is undefined.
1022              
1023             If a LIST of more than one item is passed, a reference to an array containing the values in LIST is returned.
1024              
1025             If a an ARRAYREF is passed, it is returned as-is.
1026              
1027             =item B<parse_timestamp STRING>
1028              
1029             Parse STRING and return a L<DateTime> object. STRING should be formatted according to the Informix "DATETIME YEAR TO FRACTION(5)" data type.
1030              
1031             If STRING is a valid timestamp keyword (according to L<validate_timestamp_keyword|/validate_timestamp_keyword>) it is returned unmodified. Returns undef if STRING could not be parsed as a valid "DATETIME YEAR TO FRACTION(5)" value.
1032              
1033             =item B<validate_boolean_keyword STRING>
1034              
1035             Returns true if STRING is a valid keyword for the "boolean" data type of the current data source, false otherwise. Valid (case-insensitive) boolean keywords are:
1036              
1037             TRUE
1038             FALSE
1039              
1040             =item B<validate_date_keyword STRING>
1041              
1042             Returns true if STRING is a valid keyword for the Informix "date", false otherwise. Valid (case-insensitive) date keywords are:
1043              
1044             current
1045             today
1046              
1047             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid date keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1048              
1049             =item B<validate_datetime_keyword STRING>
1050              
1051             Returns true if STRING is a valid keyword for the Informix "datetime year to second" data type, false otherwise. Valid (case-insensitive) datetime keywords are:
1052              
1053             current
1054             current year to second
1055             current year to minute
1056             current year to hour
1057             current year to day
1058             current year to month
1059             today
1060              
1061             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid datetime keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1062              
1063             =item B<validate_datetime_year_to_fraction_keyword STRING>
1064              
1065             Returns true if STRING is a valid keyword for the Informix "datetime year to fraction(n)" data type (where n is an integer from 1 to 5), false otherwise. Valid (case-insensitive) "datetime year to fraction" keywords are:
1066              
1067             current
1068             current year to fraction
1069             current year to fraction(1)
1070             current year to fraction(2)
1071             current year to fraction(3)
1072             current year to fraction(4)
1073             current year to fraction(5)
1074             current year to second
1075             current year to minute
1076             current year to hour
1077             current year to day
1078             current year to month
1079             today
1080              
1081             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid "datetime year to fraction" keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1082              
1083             =item B<validate_datetime_year_to_minute_keyword STRING>
1084              
1085             Returns true if STRING is a valid keyword for the Informix "datetime year to minute" data type, false otherwise. Valid (case-insensitive) "datetime year to minute" keywords are:
1086              
1087             current
1088             current year to second
1089             current year to minute
1090             current year to hour
1091             current year to day
1092             current year to month
1093             today
1094              
1095             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid "datetime year to minute" keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1096              
1097             =item B<validate_datetime_year_to_month_keyword STRING>
1098              
1099             Returns true if STRING is a valid keyword for the Informix "datetime year to month" data type, false otherwise. Valid (case-insensitive) "datetime year to month" keywords are:
1100              
1101             current
1102             current year to second
1103             current year to minute
1104             current year to hour
1105             current year to day
1106             current year to month
1107             today
1108              
1109             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid "datetime year to month" keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1110              
1111             =item B<validate_datetime_year_to_second_keyword STRING>
1112              
1113             Returns true if STRING is a valid keyword for the Informix "datetime year to second" data type, false otherwise. Valid (case-insensitive) datetime keywords are:
1114              
1115             current
1116             current year to second
1117             current year to minute
1118             current year to hour
1119             current year to day
1120             current year to month
1121             today
1122              
1123             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid "datetime year to second" keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1124              
1125             =item B<validate_timestamp_keyword STRING>
1126              
1127             Returns true if STRING is a valid keyword for the Informix "timestamp" data type, false otherwise. Valid (case-insensitive) timestamp keywords are:
1128              
1129             current
1130             current year to fraction
1131             current year to fraction(1)
1132             current year to fraction(2)
1133             current year to fraction(3)
1134             current year to fraction(4)
1135             current year to fraction(5)
1136             current year to second
1137             current year to minute
1138             current year to hour
1139             current year to day
1140             current year to month
1141             today
1142              
1143             The keywords are not case sensitive. Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid timestamp keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
1144              
1145             =back
1146              
1147             =head1 AUTHOR
1148              
1149             John C. Siracusa (siracusa@gmail.com)
1150              
1151             =head1 LICENSE
1152              
1153             Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is
1154             free software; you can redistribute it and/or modify it under the same terms
1155             as Perl itself.