File Coverage

blib/lib/Rose/DB/Object/Loader.pm
Criterion Covered Total %
statement 75 473 15.8
branch 0 312 0.0
condition 0 73 0.0
subroutine 25 54 46.3
pod 14 21 66.6
total 114 933 12.2


line stmt bran cond sub pod time code
1             package Rose::DB::Object::Loader;
2              
3 29     29   18733477 use strict;
  29         241  
  29         976  
4              
5 29     29   242 use Cwd;
  29         545  
  29         2047  
6 29     29   197 use File::Path;
  29         69  
  29         2186  
7 29     29   207 use File::Spec;
  29         57  
  29         765  
8 29     29   1772 use DBI;
  29         18854  
  29         1301  
9 29     29   176 use Carp;
  29         65  
  29         1630  
10              
11 29     29   1067 use Rose::DB;
  29         587414  
  29         818  
12 29     29   16399 use Rose::DB::Object;
  29         98  
  29         1113  
13 29     29   217 use Rose::DB::Object::ConventionManager;
  29         65  
  29         816  
14 29     29   171 use Rose::DB::Object::Metadata::Util qw(perl_hashref);
  29         76  
  29         1646  
15 29     29   20788 use Rose::DB::Object::Metadata::Auto;
  29         83  
  29         1103  
16              
17 29     29   224 use Rose::Object;
  29         74  
  29         3086  
18             our @ISA = qw(Rose::Object);
19              
20             our $VERSION = '0.799';
21              
22             our $Debug = 0;
23              
24             use Rose::Object::MakeMethods::Generic
25             (
26 29         352 scalar =>
27             [
28             'db_catalog',
29             'db_database',
30             'db_schema',
31             'db_username',
32             'db_password',
33             'db_options',
34             'include_tables',
35             'exclude_tables',
36             'filter_tables',
37             'pre_init_hook',
38             'post_init_hook',
39             'module_dir',
40             'module_preamble',
41             'module_postamble',
42             ],
43              
44             'scalar --get_set_init' =>
45             [
46             'with_relationships',
47             ],
48              
49             boolean =>
50             [
51             'using_default_base_class',
52             'require_primary_key' => { default => 1 },
53             'include_views' => { default => 0 },
54             'with_managers' => { default => 1 },
55             'with_foreign_keys' => { default => 1 },
56             'with_unique_keys' => { default => 1 },
57             'convention_manager_was_set' => { default => 0 },
58             'include_predicated_unique_indexes' => { default => 0 },
59             'warn_on_missing_primary_key',
60             'no_auto_sequences' => { default => 0 },
61             ],
62 29     29   193 );
  29         62  
63              
64 0     0 1   sub warn_on_missing_pk { shift->warn_on_missing_primary_key(@_) }
65              
66             CHOOSE_CLONE:
67             {
68             local $@;
69              
70             # Get the best available clone method
71             eval
72             {
73             require Scalar::Util::Clone;
74             *clone = \&Scalar::Util::Clone::clone;
75             };
76              
77             if($@)
78             {
79             require Clone;
80             *clone = \&Clone::clone;
81             }
82             }
83              
84 0     0 0   sub init_with_relationships { 1 }
85              
86             my $Base_Class_Counter = 1;
87              
88             sub generate_object_base_class_name
89             {
90 0     0 0   my($self) = shift;
91              
92 0 0         return ($self->class_prefix ?
93             ($self->class_prefix . 'DB::Object::AutoBase') :
94             'Rose::DB::Object::LoaderGenerated::AutoBase') .
95             $Base_Class_Counter++;
96             }
97              
98             sub generate_db_base_class_name
99             {
100 0     0 0   my($self) = shift;
101              
102 0 0         return ($self->class_prefix ?
103             ($self->class_prefix . 'DB::AutoBase') :
104             'Rose::DB::LoaderGenerated::AutoBase') .
105             $Base_Class_Counter++;
106             }
107              
108             sub generate_manager_class_name
109             {
110 0     0 1   my($self, $object_class, $cm) = @_;
111 0 0         return $cm ? $cm->auto_manager_class_name($object_class) :
112             $self->convention_manager->auto_manager_class_name($object_class);
113             }
114              
115             sub base_classes
116             {
117 0     0 1   my($self) = shift;
118              
119 0 0         unless(@_)
120             {
121 0 0         if(my $bc = $self->{'base_classes'})
122             {
123 0 0         return wantarray ? @$bc : $bc;
124             }
125              
126             # Make new base class
127 0           my $bc = $self->{'base_classes'} = [ $self->generate_object_base_class_name ];
128              
129 0           $self->using_default_base_class(1);
130              
131 29     29   117868 no strict 'refs';
  29         92  
  29         8615  
132 0           @{"$bc->[0]::ISA"} = qw(Rose::DB::Object);
  0            
133              
134 0 0         return wantarray ? @$bc : $bc;
135             }
136              
137 0           my $bc = shift;
138              
139 0 0         unless(ref $bc)
140             {
141 0           $bc = [ $bc ];
142             }
143              
144             #my $found_rdbo = 0;
145              
146 0           foreach my $class (@$bc)
147             {
148 0 0         unless($class =~ /^(?:\w+::)*\w+$/)
149             {
150 0           croak "Illegal base class name: $class";
151             }
152              
153             #$found_rdbo = 1 if(UNIVERSAL::isa($class, 'Rose::DB::Object'));
154             }
155              
156             #unless($found_rdbo)
157             #{
158             # croak "None of the base classes inherit from Rose::DB::Object";
159             #}
160              
161 0           $self->using_default_base_class(0);
162 0           $self->{'base_classes'} = $bc;
163              
164 0 0         return wantarray ? @$bc : $bc;
165             }
166              
167 0     0 1   sub base_class { shift->base_classes(@_) }
168              
169 29     29   289 use constant DEFAULT_MANAGER_BASE_CLASS => 'Rose::DB::Object::Manager';
  29         70  
  29         33148  
170              
171             sub manager_base_classes
172             {
173 0     0 1   my($self) = shift;
174              
175 0 0         if(my $bc = shift)
176             {
177 0 0         unless(ref $bc)
178             {
179 0           $bc = [ $bc ];
180             }
181              
182             #my $found_base = 0;
183              
184 0           foreach my $class (@$bc)
185             {
186 0 0         unless($class =~ /^(?:\w+::)*\w+$/)
187             {
188 0           croak "Illegal manager base class name: $class";
189             }
190              
191             #$found_base = 1 if(UNIVERSAL::isa($class, 'Rose::DB::Object::Manager'));
192             }
193              
194             #unless($found_base)
195             #{
196             # croak "None of the manager base classes inherit from ",
197             # "Rose::DB::Object::Manager";
198             #}
199              
200 0           $self->{'manager_base_classes'} = $bc;
201             }
202              
203 0           my $bc = $self->{'manager_base_classes'};
204              
205 0 0 0       unless(defined $bc && @$bc)
206             {
207 0 0         return wantarray ? DEFAULT_MANAGER_BASE_CLASS : [ DEFAULT_MANAGER_BASE_CLASS ];
208             }
209              
210 0           return wantarray ? @{$self->{'manager_base_classes'}} :
211 0 0         $self->{'manager_base_classes'}
212             }
213              
214 0     0 1   sub manager_base_class { shift->manager_base_classes(@_) }
215              
216             sub convention_manager
217             {
218 0     0 1   my($self) = shift;
219              
220 0 0         if(@_)
221             {
222 0           my $cm = shift;
223              
224 0 0         if(ref $cm)
225             {
226 0 0         unless(UNIVERSAL::isa($cm, 'Rose::DB::Object::ConventionManager'))
227             {
228 0           croak "Not a Rose::DB::Object::ConventionManager-derived object: $cm";
229             }
230              
231 0           $self->{'convention_manager'} = $cm;
232             }
233             else
234             {
235 0 0         unless(UNIVERSAL::isa($cm, 'Rose::DB::Object::ConventionManager'))
236             {
237 0           croak "Not a Rose::DB::Object::ConventionManager-derived class: $cm";
238             }
239              
240 0           $self->{'convention_manager'} = $cm->new;
241             }
242              
243 0           $self->convention_manager_was_set(1);
244             }
245              
246 0   0       return $self->{'convention_manager'} ||= Rose::DB::Object::ConventionManager->new;
247             }
248              
249             sub class_prefix
250             {
251 0     0 1   my($self) = shift;
252              
253 0 0         return $self->{'class_prefix'} unless(@_);
254              
255 0           my $class_prefix = shift;
256              
257 0 0         if(length $class_prefix)
258             {
259 0 0         unless($class_prefix =~ /^(?:\w+::)*\w+(?:::)?$/)
260             {
261 0           croak "Illegal class prefix: $class_prefix";
262             }
263              
264 0 0         $class_prefix .= '::' unless($class_prefix =~ /::$/);
265             }
266              
267 0           return $self->{'class_prefix'} = $class_prefix;
268             }
269              
270             sub force_lowercase
271             {
272 0     0 1   my($self) = shift;
273              
274 0 0         if(@_)
275             {
276 0           my $value = shift;
277             # Important: allow this attribute to be set to undef, unlike
278             # most "normal" boolean attributes.
279 0 0         return $self->{'force_lowercase'} = undef unless(defined $value);
280 0 0         return $self->{'force_lowercase'} = $value ? 1 : 0;
281             }
282              
283 0           return $self->{'force_lowercase'};
284             }
285              
286             sub db
287             {
288 0     0 1   my($self) = shift;
289              
290 0 0         return $self->{'db'} unless(@_);
291              
292 0           my $db = shift;
293              
294 0 0         unless(UNIVERSAL::isa($db, 'Rose::DB'))
295             {
296 0           croak "Not a Rose::DB-derived object: $db";
297             }
298              
299 0 0         if(defined $db)
300             {
301 0           $self->{'db_class'} = $db->class;
302 0           $self->{'db_dsn'} = undef;
303             }
304              
305 0           return $self->{'db'} = $db;
306             }
307              
308             sub db_dsn
309             {
310 0     0 1   my($self) = shift;
311              
312 0 0         return $self->{'db_dsn'} unless(@_);
313              
314 0           my $db_dsn = shift;
315              
316 0 0         if(my $db = $self->db)
317             {
318 0           $db->db_dsn($db_dsn);
319             }
320              
321 0           return $self->{'db_dsn'} = $db_dsn;
322             }
323              
324 0     0 0   sub dsn { shift->db_dsn(@_) }
325 0     0 0   sub dbi_dsn { shift->db_dsn(@_) }
326              
327             sub db_class
328             {
329 0     0 1   my($self) = shift;
330              
331 0 0         return $self->{'db_class'} unless(@_);
332              
333 0           my $db_class = shift;
334              
335 0 0         unless($db_class =~ /^(?:\w+::)*\w+$/)
336             {
337 0           croak "Illegal class name: $db_class";
338             }
339              
340 0 0         unless(UNIVERSAL::isa($db_class, 'Rose::DB'))
341             {
342 0           my $error;
343              
344             TRY:
345             {
346 0           local $@;
  0            
347 0           eval "require $db_class";
348 0           $error = $@;
349             }
350              
351 29     29   259 no strict 'refs';
  29         77  
  29         49222  
352 0 0 0       if(!$error && @{"${db_class}::ISA"} && !UNIVERSAL::isa($db_class, 'Rose::DB'))
  0   0        
353             {
354 0           croak "Not a Rose::DB-derived class: $db_class";
355             }
356             }
357              
358 0 0         if(my $db = $self->db)
359             {
360 0 0         $self->db(undef) unless($db->class eq $db_class);
361             }
362              
363 0           return $self->{'db_class'} = $db_class;
364             }
365              
366             sub make_modules
367             {
368 0     0 1   my($self, %args) = @_;
369              
370             my $module_dir = exists $args{'module_dir'} ?
371 0 0         delete $args{'module_dir'} : $self->module_dir;
372              
373 0 0         $module_dir = cwd() unless(defined $module_dir);
374              
375 0 0         unless(-d $module_dir)
376             {
377 0           croak "Module directory '$module_dir' does not exist";
378             }
379              
380 0           my(@extra_classes, %extra_info);
381              
382 0           $args{'extra_classes'} = \@extra_classes;
383 0           $args{'extra_info'} = \%extra_info;
384              
385 0           my @classes = $self->make_classes(%args);
386              
387 0           foreach my $class (@classes, @extra_classes)
388             {
389 0           my @path = split('::', $class);
390 0           $path[-1] .= '.pm';
391 0           unshift(@path, $module_dir);
392              
393 0           my $dir = File::Spec->catfile(@path[0 .. ($#path - 1)]);
394              
395 0 0         mkpath($dir) unless(-e $dir);
396              
397 0 0         unless(-d $dir)
398             {
399 0 0         if(-f $dir)
400             {
401 0           croak "Could not create module directory '$module_dir' - a file ",
402             "with the same name already exists";
403             }
404 0           croak "Could not create module directory '$module_dir' - $!";
405             }
406              
407 0           my $file = File::Spec->catfile(@path);
408              
409 0 0         open(my $pm, '>', $file) or croak "Could not create $file - $!";
410              
411             my $preamble = exists $args{'module_preamble'} ?
412 0 0         $args{'module_preamble'} : $self->module_preamble;
413              
414             my $postamble = exists $args{'module_postamble'} ?
415 0 0         $args{'module_postamble'} : $self->module_postamble;
416              
417 0 0         if($class->isa('Rose::DB::Object'))
    0          
    0          
418             {
419 0 0         if($preamble)
420             {
421 0 0         my $this_preamble = ref $preamble eq 'CODE' ?
422             $preamble->($class->meta) : $preamble;
423              
424 0           print {$pm} $this_preamble;
  0            
425             }
426              
427 0 0         if($extra_info{'base_classes'}{$class})
428             {
429 0           print {$pm} _perl_base_class($class, \%extra_info, \%args);
  0            
430             }
431             else
432             {
433 0           print {$pm} _perl_class($class, \%extra_info, \%args);
  0            
434             }
435              
436 0 0         if($postamble)
437             {
438 0 0         my $this_postamble = ref $postamble eq 'CODE' ?
439             $postamble->($class->meta) : $postamble;
440              
441 0           print {$pm} $this_postamble;
  0            
442             }
443             }
444             elsif($class->isa('Rose::DB::Object::Manager'))
445             {
446 0 0         if($preamble)
447             {
448 0 0         my $this_preamble = ref $preamble eq 'CODE' ?
449             $preamble->($class->object_class->meta, $class) : $preamble;
450              
451 0           print {$pm} $this_preamble;
  0            
452             }
453              
454 0           print {$pm} $class->perl_class_definition(%args), "\n";
  0            
455              
456 0 0         if($postamble)
457             {
458 0 0         my $this_postamble = ref $postamble eq 'CODE' ?
459             $postamble->($class->object_class->meta, $class) : $postamble;
460              
461 0           print {$pm} $this_postamble;
  0            
462             }
463             }
464             elsif($class->isa('Rose::DB'))
465             {
466 0           print {$pm} _perl_db_class($class, \%extra_info, \%args);
  0            
467             }
468 0           else { croak "Unknown class: $class" }
469              
470 0 0         close($pm) or croak "Could not write $file - $!";
471             }
472              
473 0 0         return wantarray ? @classes : \@classes;
474             }
475              
476             sub _perl_class
477             {
478 0     0     my($class, $info, $args) = @_;
479              
480 0           my $auto_load = $args->{'auto_load_related_classes'};
481 0           my $old_auto_load = $class->meta->auto_load_related_classes;
482              
483 0 0         if(defined $auto_load)
484             {
485 0           $class->meta->auto_load_related_classes($auto_load);
486             }
487              
488 0           my $code = $class->meta->perl_class_definition(%$args);
489              
490 0 0         if(defined $auto_load)
491             {
492 0           $class->meta->auto_load_related_classes($old_auto_load);
493             }
494              
495 0 0 0       if(!$info->{'init_db_in_base_class'} && $info->{'perl_init_db'})
496             {
497 0           my $init_db = $info->{'perl_init_db'};
498              
499 0           $code =~ s/1;/$init_db\n\n1;/;
500             }
501              
502 0           return $code . "\n";
503             }
504              
505             sub _perl_base_class
506             {
507 0     0     my($class, $info, $args) = @_;
508              
509 0           my $init_db = '';
510              
511 0 0 0       if($info->{'init_db_in_base_class'} && $info->{'perl_init_db'})
512             {
513 0           $init_db = "\n" . $info->{'perl_init_db'} . "\n";
514             }
515              
516 0           return<<"EOF";
517             package $class;
518              
519             use base 'Rose::DB::Object';
520             $init_db
521             1;
522             EOF
523             }
524              
525             sub _perl_db_class
526             {
527 0     0     my($class, $info, $args) = @_;
528              
529 0           my $max = 0;
530              
531 0           foreach my $key (keys %{$info->{'db_entry'}})
  0            
532             {
533 0 0         $max = length($key) if(length($key) > $max);
534             }
535              
536             my $hash = perl_hashref(hash => $info->{'db_entry'},
537             inline => 0,
538             no_curlies => 1,
539             key_padding => $max,
540 0   0       indent => $args->{'indent'} || 2);
541              
542 0           return<<"EOF";
543             package $class;
544              
545             use strict;
546              
547             use base 'Rose::DB';
548              
549             __PACKAGE__->use_private_registry;
550              
551             __PACKAGE__->register_db
552             (
553             $hash
554             );
555              
556             1;
557             EOF
558             }
559              
560       0 0   sub default_pre_init_hook { }
561       0 0   sub default_post_init_hook { }
562              
563             sub make_classes
564             {
565 0     0 1   my($self, %args) = @_;
566              
567 0           my $extra_classes = delete $args{'extra_classes'};
568 0           my $extra_info = delete $args{'extra_info'};
569              
570 0           my $db = delete $args{'db'};
571              
572 0           $args{'stay_connected'} = 1;
573 0 0         $args{'passive'} = 1 unless(exists $args{'passive'});
574              
575             my $require_primary_key = exists $args{'require_primary_key'} ?
576 0 0         delete $args{'require_primary_key'} : $self->require_primary_key;
577              
578             # Check for parameter alias conflicts
579 0 0         if(exists $args{'warn_on_missing_pk'})
580             {
581 0 0 0       if(exists $args{'warn_on_missing_primary_key'} &&
    0          
    0          
582             (($args{'warn_on_missing_pk'} ? 1 : 0) != ($args{'warn_on_missing_primary_key'} ? 1 : 0)))
583             {
584 0           croak "The warn_on_missing_primary_key and warn_on_missing_pk parameters ",
585             "were both passed, and they conflict. Since these two parameters are ",
586             "aliases for each other, try passing just one.";
587             }
588              
589 0           $args{'warn_on_missing_primary_key'} = delete $args{'warn_on_missing_pk'};
590             }
591              
592 0           my $warn_on_missing_primary_key;
593              
594             # If not requiring PKs and no explicit decision, either in args or
595             # in the object, has been made about whether to warn on missing PKs,
596             # then don't warn (because not requiring PKs is a strong indication
597             # that their absence is not worth a warning)
598 0 0 0       if(!$require_primary_key &&
      0        
599             ((!exists $args{'warn_on_missing_primary_key'} && !defined $self->warn_on_missing_primary_key) ||
600             exists $args{'warn_on_missing_primary_key'} && !defined $args{'warn_on_missing_primary_key'}))
601             {
602 0           $warn_on_missing_primary_key = 0;
603             }
604             else
605             {
606             $warn_on_missing_primary_key = exists $args{'warn_on_missing_primary_key'} ?
607 0 0         delete $args{'warn_on_missing_primary_key'} : $self->warn_on_missing_primary_key;
608             }
609              
610             my $include_views = exists $args{'include_views'} ?
611 0 0         delete $args{'include_views'} : $self->include_views;
612              
613             my $with_managers = exists $args{'with_managers'} ?
614 0 0         delete $args{'with_managers'} : $self->with_managers;
615              
616             $args{'with_relationships'} = $self->with_relationships
617 0 0         unless(exists $args{'with_relationships'});
618              
619             $args{'with_foreign_keys'} = $self->with_foreign_keys
620 0 0         unless(exists $args{'with_foreign_keys'});
621              
622             $args{'with_unique_keys'} = $self->with_unique_keys
623 0 0         unless(exists $args{'with_unique_keys'});
624              
625             my $no_auto_sequences = exists $args{'no_auto_sequences'} ?
626 0 0         delete $args{'no_auto_sequences'} : $self->no_auto_sequences;
627              
628             my $pre_init_hook = exists $args{'pre_init_hook'} ?
629 0 0         delete $args{'pre_init_hook'} : $self->pre_init_hook;
630              
631             my $post_init_hook = exists $args{'post_init_hook'} ?
632 0 0         delete $args{'post_init_hook'} : $self->post_init_hook;
633              
634             my $include = exists $args{'include_tables'} ?
635 0 0         delete $args{'include_tables'} : $self->include_tables;
636              
637             my $exclude = exists $args{'exclude_tables'} ?
638 0 0         delete $args{'exclude_tables'} : $self->exclude_tables;
639              
640 0 0 0       my $filter = exists $args{'filter_tables'} ? delete $args{'filter_tables'} :
    0          
641             (!defined $include && !defined $exclude) ? $self->filter_tables : undef;
642              
643 0 0 0       if($include || $exclude)
644             {
645 0 0         if($filter)
646             {
647 0           croak "The filter_tables parameter and/or object attribute cannot ",
648             "be used with the include_tables or exclude_tables parameters ",
649             "or object attributes";
650             }
651              
652 0 0         if(defined $include)
653             {
654 0 0         if(ref $include eq 'ARRAY')
655             {
656 0           $include = '(?i)\A(?:' . join('|', map { quotemeta } @$include) . ')\z'
  0            
657             }
658              
659 0           $include = qr((?i)$include);
660             }
661              
662 0 0         if(defined $exclude)
663             {
664 0 0         if(ref $exclude eq 'ARRAY')
665             {
666 0           $exclude = '(?i)\A(?:' . join('|', map { quotemeta } @$exclude) . ')\z'
  0            
667             }
668              
669 0           $exclude = qr((?i)$exclude);
670             }
671              
672             $filter = sub
673             {
674 29     29   265 no warnings 'uninitialized';
  29         82  
  29         13557  
675 0 0 0 0     return 0 if((defined $include && !/$include/) ||
      0        
      0        
676             (defined $exclude && /$exclude/));
677 0           return 1;
678 0           };
679             }
680              
681             my $class_prefix = exists $args{'class_prefix'} ?
682 0 0 0       delete $args{'class_prefix'} : $self->class_prefix || '';
683              
684 0 0         if(length $class_prefix)
685             {
686 0 0         unless($class_prefix =~ /^(?:\w+::)*\w+(?:::)?$/)
687             {
688 0           croak "Illegal class prefix: $class_prefix";
689             }
690              
691 0 0         $class_prefix .= '::' unless($class_prefix =~ /::$/);
692             }
693              
694             # Evil masking of object attribute
695 0           local $self->{'class_prefix'} = $class_prefix;
696              
697             # When setting explicit values for attributes that cascade to
698             # affect other attributes, save off the old values are restore
699             # them at the end.
700 0           my %save;
701              
702 0 0         if(exists $args{'db_class'})
703             {
704 0           my $db_class = delete $args{'db_class'};
705              
706 0 0 0       if($db && $db_class && $db_class ne $db->class)
      0        
707             {
708 0           Carp::croak "The db and db_class parameters conflict: ", $db->class,
709             " vs. $db_class";
710             }
711              
712 0 0         if(defined(my $db_class = $self->db_class))
713             {
714 0           $save{'db_class'} = $db_class;
715             }
716              
717 0 0         if(defined(my $db = $self->db))
718             {
719 0           $save{'db'} = $db;
720             }
721              
722 0           $self->db_class($db_class);
723             }
724              
725             #
726             # Get or create the db object
727             #
728              
729 0   0       $db ||= $self->db;
730              
731 0 0         my $db_class = $db ? $db->class : undef;
732              
733 0           my $made_new_db_class = 0;
734              
735 0 0         unless($db)
736             {
737 0           $db_class = $self->db_class;
738              
739 0 0         if($db_class)
740             {
741 0 0         unless(UNIVERSAL::isa($db_class, 'Rose::DB'))
742             {
743 0           my $error;
744              
745             TRY:
746             {
747 0           local $@;
  0            
748 0           eval "require $db_class";
749 0           $error = $@;
750             }
751              
752 0 0         if($error)
753             {
754             # Failed to load existing module
755 0 0         unless($error =~ /^Can't locate $db_class\.pm/)
756             {
757 0           croak "Could not load db class '$db_class' - $error";
758             }
759              
760             # Make the class
761 29     29   277 no strict 'refs';
  29         94  
  29         2695  
762 0           @{"${db_class}::ISA"} = qw(Rose::DB);
  0            
763 0           $db_class->registry(clone(Rose::DB->registry));
764             }
765             }
766             }
767             else
768             {
769 0           $db_class = $self->generate_db_base_class_name;
770              
771             # Make a class
772 29     29   233 no strict 'refs';
  29         67  
  29         4602  
773 0           @{"${db_class}::ISA"} = qw(Rose::DB);
  0            
774 0           $db_class->registry(clone(Rose::DB->registry));
775              
776 0 0         push(@$extra_classes, $db_class) if($extra_classes);
777 0           $made_new_db_class = 1;
778             }
779             }
780              
781             # Create the init_db subroutine that will be used with the objects
782 0           my %db_args;
783              
784 0 0         if($db)
785             {
786 0           %db_args =
787             (
788             type => $db->type,
789             domain => $db->domain,
790             );
791              
792 0 0         delete $db_args{'type'} if($db_args{'type'} eq $db->default_type);
793 0 0         delete $db_args{'domain'} if($db_args{'domain'} eq $db->default_domain);
794             }
795              
796 0           foreach my $attr (qw(db_dsn db_catalog db_schema db_username db_password db_database))
797             {
798 0           (my $db_attr = $attr) =~ s/^db_//;
799 29     29   228 no strict 'refs';
  29         72  
  29         3289  
800 0 0         $db_args{$db_attr} = $self->$attr() if(defined $self->$attr());
801             }
802              
803 0 0         $db_args{'connect_options'} = $self->db_options if(defined $self->db_options);
804              
805             # Set up the object base class
806 0           my @base_classes = $self->base_classes;
807              
808 0           foreach my $class (@base_classes)
809             {
810 29     29   219 no strict 'refs';
  29         71  
  29         13822  
811 0 0 0       unless(UNIVERSAL::isa($class, 'Rose::DB::Object') || @{"${class}::ISA"})
  0            
812             {
813 0           my $error;
814              
815             TRY:
816             {
817 0           local $@;
  0            
818 0           eval "require $class";
819 0           $error = $@;
820             }
821              
822 0 0         croak $error if($error);
823             }
824             }
825              
826 0           my ($init_db, $need_new_init_db);
827              
828             # Check if the base class already has its own init_db
829 0           my $can_rdbo = Rose::DB::Object->can('init_db');
830 0           my $can_base = $base_classes[0]->can('init_db');
831              
832 0 0 0       unless($can_rdbo && $can_base && $can_rdbo ne $can_base)
      0        
833             {
834 0           $need_new_init_db = 1;
835             }
836              
837 0 0         if($made_new_db_class)
838             {
839 0 0 0       if($db_args{'dsn'} && !$db_args{'driver'})
840             {
841 0 0         if(DBI->can('parse_dsn'))
842             {
843 0           $db_args{'driver'} = lc((DBI->parse_dsn($db_args{'dsn'}))[1]);
844             }
845              
846 0 0         unless($db_args{'driver'})
847             {
848 0 0         $db_args{'dsn'} =~ /^dbi:(\w+)/i or
849             Carp::croak "Could not extract driver name from DSN: $db_args{'dsn'}";
850              
851 0           $db_args{'driver'} = lc $1;
852             }
853             }
854              
855 0           $db_class->register_db(domain => $db_class->default_domain,
856             type => $db_class->default_type,
857             %db_args);
858              
859 0           my $entry =
860             $db_class->registry->entry(domain => $db_class->default_domain,
861             type => $db_class->default_type);
862              
863 0           $extra_info->{'db_entry'} = { %db_args };
864              
865 0 0         unless($entry->database)
866             {
867             # Need appropriate db just for parsing
868 0           my $tmp_db = $db_class->new;
869              
870 0 0         my $database = $tmp_db->database_from_dsn($entry->dsn) or
871             Carp::croak "Could not extract database name from DSN: ", $entry->dsn;
872              
873 0           $entry->database($database);
874              
875 0           $extra_info->{'database'} = $database;
876             }
877              
878 0     0     $init_db = sub { $db_class->new };
  0            
879              
880 0           $extra_info->{'perl_init_db'} =
881             "use $db_class;\n\n" .
882             "sub init_db { $db_class->new }";
883             }
884             else
885             {
886 0 0   0     $init_db = $need_new_init_db ? sub { $db_class->new(%db_args) } : $can_base;
  0            
887              
888 0           my $hash = perl_hashref(hash => \%db_args,
889             inline => 1,
890             no_curlies => 1,
891             indent => 0);
892              
893 0 0         if($need_new_init_db)
894             {
895 0           $extra_info->{'perl_init_db'} =
896             "use $db_class;\n\n" .
897             "sub init_db { $db_class->new($hash) }";
898             }
899             }
900              
901             # Refresh the db
902 0           $db = $init_db->();
903              
904 0           $extra_info->{'init_db_in_base_class'} = 0;
905              
906             # Install the init_db routine in the base class, but only if
907             # using the default base class.
908 0 0         if($self->using_default_base_class)
909             {
910 29     29   258 no strict 'refs';
  29         96  
  29         3578  
911 0           *{"$base_classes[0]::init_db"} = $init_db;
  0            
912 0           $extra_info->{'init_db_in_base_class'} = 1;
913 0           $extra_info->{'base_classes'}{$base_classes[0]}++;
914 0           push(@$extra_classes, $base_classes[0]);
915             }
916             else
917             {
918 0 0 0       if($made_new_db_class || $db_class ne 'Rose::DB')
919             {
920 0 0         if($need_new_init_db)
921             {
922 29     29   228 no strict 'refs';
  29         72  
  29         1422  
923 29     29   193 no warnings;
  29         66  
  29         10091  
924 0           *{"$base_classes[0]::init_db"} = $init_db;
  0            
925             }
926            
927 0           $extra_info->{'init_db_in_base_class'} = 1;
928 0           $extra_info->{'base_classes'}{$base_classes[0]}++;
929             }
930             else
931             {
932 0           foreach my $base_class (@base_classes)
933             {
934 0 0         if($base_class->can('init_db'))
935             {
936 0           $extra_info->{'init_db_in_base_class'} = 1;
937 0           last;
938             }
939             }
940             }
941             }
942              
943 0           my $force_lowercase;
944              
945 0 0         if(exists $args{'force_lowercase'})
946             {
947 0           $force_lowercase = delete $args{'force_lowercase'};
948             }
949             else
950             {
951 0 0         unless(defined($force_lowercase = $self->force_lowercase))
952             {
953 0 0         $force_lowercase = $db->driver eq 'oracle' ? 1 : 0;
954             }
955             }
956              
957 0           my $cm;
958              
959             # XXX: Lame way to check if the convention_manager attribute has
960             # XXX: been set or fetched.
961 0 0         if($self->{'convention_manager'})
962             {
963 0           $cm = $self->convention_manager;
964             }
965             else
966             {
967 0           $cm = $base_classes[0]->meta->convention_manager;
968 0           $self->convention_manager($cm);
969             }
970              
971 0 0         die "Missing convention manager" unless($cm);
972              
973             # Propagate CM-relevant attributes
974 0           $cm->force_lowercase($force_lowercase);
975 0           $cm->no_auto_sequences($no_auto_sequences);
976              
977 0           $self->convention_manager($cm);
978              
979 0           my @classes;
980              
981             my %list_args;
982 0 0         $list_args{'include_views'} = 1 if($include_views);
983              
984             # XXX: Horrible hack. Replce eventually...
985 0 0         local $Rose::DB::Object::Metadata::Auto::Missing_PK_OK =
986             $require_primary_key ? 0 : 1;
987              
988 0           my %created;
989              
990             # Iterate over tables, creating RDBO classes for each
991 0           foreach my $table ($db->list_tables(%list_args))
992             {
993 0           local $_ = $table;
994 0 0 0       next unless(!$filter || $filter->($table));
995              
996 0 0         unless($db->has_primary_key($table))
997             {
998 0 0         if($warn_on_missing_primary_key)
999             {
1000             # Warn about tables with no primary keys
1001 0 0         warn "Warning: table '$table' has no primary key defined.",
1002             ($require_primary_key ? " Skipping.\n" : "\n");
1003             }
1004              
1005             # Skip table if primary keys are required
1006 0 0         next if($require_primary_key);
1007             }
1008              
1009 0           my $obj_class = $class_prefix . $cm->table_to_class($table);
1010              
1011 0 0         $Debug && warn "Loader loading table: $table - $obj_class\n";
1012              
1013 29     29   263 no strict 'refs';
  29         78  
  29         21471  
1014             # Skip classes that have already been created
1015             #if($obj_class->isa('Rose::DB::Object') && $obj_class->meta->is_initialized)
1016 0 0         if($created{$obj_class})
1017             {
1018 0 0         $Debug && warn "Skipping: $obj_class already initialized\n";
1019 0           next;
1020             }
1021              
1022             # Set up the class
1023              
1024 0           @{"${obj_class}::ISA"} = @base_classes;
  0            
1025              
1026 0 0         unless($extra_info->{'init_db_in_base_class'})
1027             {
1028 0           *{"${obj_class}::init_db"} = $init_db;
  0            
1029             }
1030              
1031 0           my $meta = $obj_class->meta;
1032              
1033 0           $meta->db($db);
1034              
1035 0 0         if($pre_init_hook)
1036             {
1037 0 0         if(ref $pre_init_hook eq 'CODE')
    0          
1038             {
1039 0           $pre_init_hook = [ $pre_init_hook ];
1040             }
1041             elsif(ref $pre_init_hook ne 'ARRAY')
1042             {
1043 0           Carp::croak "Invalid pre_init_hook: $pre_init_hook";
1044             }
1045             }
1046              
1047 0     0     unshift(@$pre_init_hook, sub { $self->default_pre_init_hook(@_) });
  0            
1048              
1049 0           $meta->pre_init_hook($pre_init_hook);
1050              
1051 0 0         if($post_init_hook)
1052             {
1053 0 0         if(ref $post_init_hook eq 'CODE')
    0          
1054             {
1055 0           $post_init_hook = [ $post_init_hook ];
1056             }
1057             elsif(ref $post_init_hook ne 'ARRAY')
1058             {
1059 0           Carp::croak "Invalid post_init_hook: $post_init_hook";
1060             }
1061             }
1062              
1063 0     0     unshift(@$post_init_hook, sub { $self->default_post_init_hook(@_) });
  0            
1064              
1065 0           $meta->post_init_hook($post_init_hook);
1066              
1067 0           $meta->table($table);
1068 0           $meta->convention_manager($cm->clone);
1069 0           $meta->db($db);
1070              
1071             my $include_predicated_unique_indexes =
1072             exists $args{'include_predicated_unique_indexes'}
1073 0 0         ? delete $args{'include_predicated_unique_indexes'}
1074             : $self->include_predicated_unique_indexes;
1075              
1076 0           $meta->include_predicated_unique_indexes($include_predicated_unique_indexes);
1077              
1078 0           $meta->auto_initialize(%args);
1079              
1080 0           push(@classes, $obj_class);
1081              
1082 0           $created{$obj_class}++;
1083              
1084             # Make the manager class
1085 0 0         if($with_managers)
1086             {
1087 0           my $mgr_class = $self->generate_manager_class_name($obj_class, $cm);
1088              
1089 0           $meta->make_manager_class(
1090             class => $mgr_class,
1091             base_name => $cm->auto_manager_base_name($table, $obj_class),
1092             isa => scalar $self->manager_base_classes);
1093              
1094 0           push(@classes, $mgr_class);
1095             }
1096             }
1097              
1098 0 0         if(@classes)
1099             {
1100 0           my $meta = $classes[0]->meta;
1101              
1102             # Retry deferred stuff: two passes
1103 0           for(1 .. 2)
1104             {
1105 0           $meta->retry_deferred_tasks;
1106 0           $meta->retry_deferred_foreign_keys;
1107 0           $meta->retry_deferred_relationships;
1108             }
1109              
1110 0           $classes[0]->meta_class->clear_all_dbs;
1111             }
1112              
1113 0 0         if(%save)
1114             {
1115 0           while(my($method, $value) = each(%save))
1116             {
1117 0           $self->$method($value);
1118             }
1119             }
1120              
1121 0 0         return wantarray ? @classes : \@classes;
1122             }
1123              
1124             1;
1125              
1126             __END__
1127              
1128             =head1 NAME
1129              
1130             Rose::DB::Object::Loader - Automatically create Rose::DB::Object subclasses based on database table definitions.
1131              
1132             =head1 SYNOPSIS
1133              
1134             Sample database schema:
1135              
1136             CREATE TABLE vendors
1137             (
1138             id SERIAL NOT NULL PRIMARY KEY,
1139             name VARCHAR(255) NOT NULL,
1140              
1141             UNIQUE(name)
1142             );
1143              
1144             CREATE TABLE products
1145             (
1146             id SERIAL NOT NULL PRIMARY KEY,
1147             name VARCHAR(255) NOT NULL,
1148             price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
1149              
1150             vendor_id INT REFERENCES vendors (id),
1151              
1152             status VARCHAR(128) NOT NULL DEFAULT 'inactive'
1153             CHECK(status IN ('inactive', 'active', 'defunct')),
1154              
1155             date_created TIMESTAMP NOT NULL DEFAULT NOW(),
1156             release_date TIMESTAMP,
1157              
1158             UNIQUE(name)
1159             );
1160              
1161             CREATE TABLE prices
1162             (
1163             id SERIAL NOT NULL PRIMARY KEY,
1164             product_id INT NOT NULL REFERENCES products (id),
1165             region CHAR(2) NOT NULL DEFAULT 'US',
1166             price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
1167              
1168             UNIQUE(product_id, region)
1169             );
1170              
1171             CREATE TABLE colors
1172             (
1173             id SERIAL NOT NULL PRIMARY KEY,
1174             name VARCHAR(255) NOT NULL,
1175              
1176             UNIQUE(name)
1177             );
1178              
1179             CREATE TABLE product_color_map
1180             (
1181             product_id INT NOT NULL REFERENCES products (id),
1182             color_id INT NOT NULL REFERENCES colors (id),
1183              
1184             PRIMARY KEY(product_id, color_id)
1185             );
1186              
1187             To start, make a L<Rose::DB::Object::Loader> object, specifying the database connection information and an optional class name prefix.
1188              
1189             $loader =
1190             Rose::DB::Object::Loader->new(
1191             db_dsn => 'dbi:Pg:dbname=mydb;host=localhost',
1192             db_username => 'someuser',
1193             db_password => 'mysecret',
1194             db_options => { AutoCommit => 1, ChopBlanks => 1 },
1195             class_prefix => 'My::Corp');
1196              
1197             It's even easier to specify the database information if you've set up L<Rose::DB> (say, by following the instructions in L<Rose::DB::Tutorial>). Just pass a L<Rose::DB>-derived object pointing to the database you're interested in.
1198              
1199             $loader =
1200             Rose::DB::Object::Loader->new(
1201             db => My::Corp::DB->new('main'),
1202             class_prefix => 'My::Corp');
1203              
1204             Finally, automatically create L<Rose::DB::Object> subclasses for all the tables in the database. All it takes is one method call.
1205              
1206             $loader->make_classes;
1207              
1208             Here's what you get for your effort.
1209              
1210             $p = My::Corp::Product->new(name => 'Sled');
1211              
1212             $p->vendor(name => 'Acme');
1213              
1214             $p->prices({ price => 1.23, region => 'US' },
1215             { price => 4.56, region => 'UK' });
1216              
1217             $p->colors({ name => 'red' },
1218             { name => 'green' });
1219              
1220             $p->save;
1221              
1222             $products =
1223             My::Corp::Product::Manager->get_products_iterator(
1224             query => [ name => { like => '%le%' } ],
1225             with_objects => [ 'prices' ],
1226             require_objects => [ 'vendor' ],
1227             sort_by => 'vendor.name');
1228              
1229             $p = $products->next;
1230              
1231             print $p->vendor->name; # Acme
1232              
1233             # US: 1.23, UK: 4.56
1234             print join(', ', map { $_->region . ': ' . $_->price } $p->prices);
1235              
1236             See the L<Rose::DB::Object> and L<Rose::DB::Object::Manager> documentation for learn more about the features these classes provide.
1237              
1238             The contents of the database now look like this.
1239              
1240             mydb=# select * from products;
1241             id | name | price | vendor_id | status | date_created
1242             ----+--------+-------+-----------+----------+-------------------------
1243             1 | Sled 3 | 0.00 | 1 | inactive | 2005-11-19 22:09:20.7988
1244              
1245              
1246             mydb=# select * from vendors;
1247             id | name
1248             ----+--------
1249             1 | Acme 3
1250              
1251              
1252             mydb=# select * from prices;
1253             id | product_id | region | price
1254             ----+------------+--------+-------
1255             1 | 1 | US | 1.23
1256             2 | 1 | UK | 4.56
1257              
1258              
1259             mydb=# select * from colors;
1260             id | name
1261             ----+-------
1262             1 | red
1263             2 | green
1264              
1265              
1266             mydb=# select * from product_color_map;
1267             product_id | color_id
1268             ------------+----------
1269             1 | 1
1270             1 | 2
1271              
1272              
1273             =head1 DESCRIPTION
1274              
1275             L<Rose::DB::Object::Loader> will automatically create L<Rose::DB::Object> subclasses for all the tables in a database. It will configure column data types, default values, primary keys, unique keys, and foreign keys. It can also discover and set up inter-table L<relationships|Rose::DB::Object::Metadata/relationship_type_classes>. It uses L<Rose::DB::Object>'s L<auto-initialization|Rose::DB::Object::Metadata/"AUTO-INITIALIZATION"> capabilities to do all of this.
1276              
1277             To do its work, the loader needs to know how to connect to the database. This information can be provided in several ways. The recommended practice is to set up L<Rose::DB> according to the instructions in the L<Rose::DB::Tutorial>, and then pass a L<Rose::DB>-derived object or class name to the loader. The loader will also accept traditional L<DBI>-style connection information: DSN, username, password, etc.
1278              
1279             Once the loader object is configured, the L<make_classes|/make_classes> method does all the work. It takes a few options specifying which tables to make classes for, whether or not to make L<manager|Rose::DB::Object::Manager> classes for each table, and a few other L<options|/make_classes>. The L<convention manager|/convention_manager> is used to convert table names to class names, generate foreign key and relationship method names, and so on. The result of this process is a suite of L<Rose::DB::Object> (and L<Rose::DB::Object::Manager>) subclasses ready for use.
1280              
1281             L<Rose::DB::Object::Loader> inherits from, and follows the conventions of, L<Rose::Object>. See the L<Rose::Object> documentation for more information.
1282              
1283             =head1 GOTCHAS
1284              
1285             Database schema information is extracted using L<DBI>'s schema interrogation methods, which dutifully report exactly how the database describes itself. In some cases, what the database reports about a particular table may not exactly match what you specified in your table definition.
1286              
1287             The most egregious offender is (surprise!) MySQL, which, to give just one example, tends to offer up empty string default values for non-null character columns. That is, if you write a table definition like this:
1288              
1289             CREATE TABLE widgets
1290             (
1291             id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
1292             name VARCHAR(64) NOT NULL
1293             );
1294              
1295             and then interrogate it using L<DBI>, you will find that the "name" column has a default value (as reflected in the C<COLUMN_DEF> column returned by L<DBI>'s L<column_info()|DBI/column_info> method) of '' (i.e., an empty string). In other words, it's as if your table definition was this instead:
1296              
1297             CREATE TABLE widgets
1298             (
1299             id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
1300             name VARCHAR(64) NOT NULL DEFAULT ''
1301             );
1302              
1303             MySQL is full of such surprises, and it's not the only database to do such things. Consult the documentation for your database (or do a Google search for "E<lt>mydbnameE<gt> gotchas") for the gory details.
1304              
1305             To work around these kinds of problems, try the L<pre_init_hook|/pre_init_hook> feature. For example, in your L<pre_init_hook|/pre_init_hook> subroutine you could walk over the list of L<columns|Rose::DB::Object::Metadata/columns> for each class, eliminating all the empty string default values (i.e., changing them to undef instead).
1306              
1307              
1308             =head1 CONSTRUCTOR
1309              
1310             =over 4
1311              
1312             =item B<new PARAMS>
1313              
1314             Returns a new L<Rose::DB::Object::Loader> constructed according to PARAMS, where PARAMS are name/value pairs. Any object method is a valid parameter name.
1315              
1316             =back
1317              
1318             =head1 OBJECT METHODS
1319              
1320             =over 4
1321              
1322             =item B<base_class CLASS>
1323              
1324             This is an alias for the L<base_classes|/base_classes> method.
1325              
1326             =item B<base_classes [ CLASS | ARRAYREF ]>
1327              
1328             Get or set the list of base classes to use for the L<Rose::DB::Object> subclasses created by the L<make_classes|/make_classes> method. The argument may be a class name or a reference to an array of class names. At least one of the classes should inherit from L<Rose::DB::Object>.
1329              
1330             Returns a list (in list context) or reference to an array (in scalar context) of base class names. Defaults to a dynamically-generated L<Rose::DB::Object> subclass name.
1331              
1332             =item B<class_prefix [PREFIX]>
1333              
1334             Get or set the prefix affixed to all class names created by the L<make_classes|/make_classes> method. If PREFIX doesn't end in "::", it will be added automatically.
1335              
1336             =item B<convention_manager [ CLASS | MANAGER ]>
1337              
1338             Get or set the L<Rose::DB::Object::ConventionManager>-derived class name or object to be used during the L<auto-initialization|Rose::DB::Object::Metadata/"AUTO-INITIALIZATION"> process for each class created by the L<make_classes|/make_classes> method. Returns a L<Rose::DB::Object::ConventionManager>-derived object, which defaults to a new L<Rose::DB::Object::ConventionManager> object.
1339              
1340             Unless this attribute is explicitly set or fetched before the call to the L<make_classes|/make_classes> method, the convention manager object used by L<make_classes|/make_classes> will be produced by calling the L<convention_manager|Rose::DB::Object::Metadata/convention_manager> method of the metadata object of the first (left-most) L<base class|/base_classes>.
1341              
1342             =item B<db [DB]>
1343              
1344             Get or set the L<Rose::DB>-derived object used to connect to the database. This object will be used by the L<make_classes|/make_classes> method when extracting information from the database. It will also be used as the prototype for the L<db|Rose::DB::Object/db> object used by each L<Rose::DB::Object> subclass to connect to the database.
1345              
1346             Setting this attribute also sets the L<db_class|/db_class> attributes, overwriting any previously existing value, and sets the L<db_dsn|/db_dsn> value to undef.
1347              
1348             =item B<db_catalog [CATALOG]>
1349              
1350             Get or set the L<catalog|Rose::DB/catalog> for the database connection.
1351              
1352             =item B<db_class [CLASS]>
1353              
1354             Get or set the name of the L<Rose::DB>-derived class used by the L<make_classes|/make_classes> method to construct a L<db|/db> object if one has not been set via the method of the same name.
1355              
1356             Setting this attribute sets the L<db|/db> attribute to undef unless its class is the same as CLASS.
1357              
1358             =item B<db_dsn [DSN]>
1359              
1360             Get or set the L<DBI>-style Data Source Name (DSN) used to connect to the database. This will be used by the L<make_classes|/make_classes> method when extracting information from the database. The L<Rose::DB>-derived objects used by each L<Rose::DB::Object> subclass to connect to the database will be initialized with this DSN.
1361              
1362             Setting this attribute immediately sets the L<dsn|Rose::DB/dsn> of the L<db|/db> attribute, if it is defined.
1363              
1364             =item B<db_options [HASHREF]>
1365              
1366             Get or set the L<options|Rose::DB/connect_options> used to connect to the database.
1367              
1368             =item B<db_password [PASSWORD]>
1369              
1370             Get or set the L<password|Rose::DB/password> used to connect to the database.
1371              
1372             =item B<db_schema [SCHEMA]>
1373              
1374             Get or set the L<schema|Rose::DB/schema> for the database connection.
1375              
1376             =item B<db_username [USERNAME]>
1377              
1378             Get or set the L<username|Rose::DB/username> used to connect to the database.
1379              
1380             =item B<exclude_tables [ REGEX | ARRAYREF ]>
1381              
1382             Get or set a regular expression or reference to an array of table names to exclude. Table names that match REGEX or are contained in ARRAYREF will be skipped by default during calls to the L<make_classes|/make_classes> method. Tables without primary keys are automatically (and always) skipped.
1383              
1384             Table names are compared to REGEX and the names in ARRAYREF in a case-insensitive manner. To override this in the case of the REGEX, add C<(?-i)> to the front of the REGEX. Otherwise, use the L<filter_tables|/filter_tables> method instead.
1385              
1386             =item B<filter_tables CODEREF>
1387              
1388             Get or set a reference to a subroutine that takes a single table name argument and returns true if the table should be processed by default during calls to the L<make_classes|/make_classes> method, false if the table should be skipped. The C<$_> variable will also be set to the table name before the call to CODEREF.
1389              
1390             This attribute should not be combined with the L<exclude_tables|/exclude_tables> or L<include_tables|/include_tables> attributes.
1391              
1392             =item B<force_lowercase [BOOL]>
1393              
1394             Get or set a boolean value that indicates whether or not L<metadata|Rose::DB::Object::Metadata> entity names should be forced to lowercase even when the related entity (e.g., table or column name) is uppercase or mixed case. ("Metadata entities" are thing like L<columns|Rose::DB::Object::Metadata/columns>, L<relationships|Rose::DB::Object::Metadata/relationships>, and L<foreign keys|Rose::DB::Object::Metadata/foreign_keys>.) The default value undef.
1395              
1396             =item B<generate_manager_class_name CLASS [, CM]>
1397              
1398             Given the name of a L<Rose::DB::Object>-derived class, returns a class name for a L<Rose::DB::Object::Manager>-derived class to manage such objects. The default implementation calls the L<auto_manager_class_name|Rose::DB::Object::ConventionManager/auto_manager_class_name> method on the convention manager object passed as the optional CM argument, or returned from the L<convention_manager|/convention_manager> method if a CM argument is not passed.
1399              
1400             =item B<include_tables [ REGEX | ARRAYREF ]>
1401              
1402             Get or set a regular expression or reference to an array of table names to include. Table names that do not match REGEX or are not contained in ARRAYREF will be skipped by default during calls to the L<make_classes|/make_classes> method. Tables without primary keys are automatically (and always) skipped.
1403              
1404             Table names are compared to REGEX and the names in ARRAYREF in a case-insensitive manner. To override this in the case of the REGEX, add C<(?-i)> to the front of the REGEX. Otherwise, use the L<filter_tables|/filter_tables> method instead.
1405              
1406             =item B<include_predicated_unique_indexes BOOL>
1407              
1408             Get or set a boolean value that will be assigned to the L<include_predicated_unique_indexes|Rose::DB::Object::Metadata/include_predicated_unique_indexes> attribute of the L<Rose::DB::Object::Metadata> object for each class created by the L<make_classes|/make_classes> method. The default value is false.
1409              
1410             =item B<include_views BOOL>
1411              
1412             If true, database views will also be processed by default during calls to the L<make_classes|/make_classes> method. Defaults to false.
1413              
1414             =item B<make_classes [PARAMS]>
1415              
1416             Automatically create L<Rose::DB::Object> and (optionally) L<Rose::DB::Object::Manager> subclasses for some or all of the tables in a database. The class creation process is controlled by the loader object's attributes. Optional name/value pairs passed to this method may override some of those values. Valid PARAMS are:
1417              
1418             =over 4
1419              
1420             =item B<db [DB]>
1421              
1422             The L<Rose::DB>-derived object used to connect to the database. This object will also be used as the prototype for the L<db|Rose::DB::Object/db> object used by each L<Rose::DB::Object> subclass created by this call to L<make_classes|/make_classes>. Defaults to the value of the loader object's L<db|/db> attribute.
1423              
1424             =item B<db_class [CLASS]>
1425              
1426             The name of the L<Rose::DB>-derived class used to construct a L<db|/db> object if one has not been set via the parameter or object attribute of the same name. Defaults to the value of the loader object's L<db_class|/db_class> attribute.
1427              
1428             =item B<include_tables [ REGEX | ARRAYREF ]>
1429              
1430             Table names that do not match REGEX or are not contained in ARRAYREF will be skipped. Defaults to the value of the loader object's L<include_tables|/include_tables> attribute. Tables without primary keys are automatically (and always) skipped.
1431              
1432             Table names are compared to REGEX and the names in ARRAYREF in a case-insensitive manner. To override this in the case of the REGEX, add C<(?-i)> to the front of the REGEX. Otherwise, use the C<filter_tables> parameter instead.
1433              
1434             =item B<exclude_tables [ REGEX | ARRAYREF ]>
1435              
1436             Table names that match REGEX or are contained in ARRAYREF will be skipped. Defaults to the value of the loader object's L<exclude_tables|/exclude_tables> attribute. Tables without primary keys are automatically (and always) skipped.
1437              
1438             Table names are compared to REGEX and the names in ARRAYREF in a case-insensitive manner. To override this in the case of the REGEX, add C<(?-i)> to the front of the REGEX. Otherwise, use the C<filter_tables> parameter instead.
1439              
1440             =item B<filter_tables CODEREF>
1441              
1442             A reference to a subroutine that takes a single table name argument and returns true if the table should be processed, false if it should be skipped. The C<$_> variable will also be set to the table name before the call. This parameter cannot be combined with the C<exclude_tables> or C<include_tables> options.
1443              
1444             Defaults to the value of the loader object's L<filter_tables|/filter_tables> attribute, provided that both the C<exclude_tables> and C<include_tables> values are undefined. Tables without primary keys are automatically skipped.
1445              
1446             =item B<force_lowercase BOOL>
1447              
1448             A boolean value that indicates whether or not L<metadata|Rose::DB::Object::Metadata> entity names should be forced to lowercase even when the related entity is uppercase or mixed case. ("Metadata entities" are thing like L<columns|Rose::DB::Object::Metadata/columns>, L<relationships|Rose::DB::Object::Metadata/relationships>, and L<foreign keys|Rose::DB::Object::Metadata/foreign_keys>.)
1449              
1450             If this parameter is omitted and if the loader object's L<force_lowercase|/force_lowercase> attribute is not defined, then the value is chosen based on the database currently being examined. If the database is Oracle, then it defaults to true. Otherwise, it defaults to false.
1451              
1452             The final value is propagated to the L<convention manager|/convention_manager> L<attribute of the same name|Rose::DB::Object::ConventionManager/force_lowercase>.
1453              
1454             =item B<include_predicated_unique_indexes BOOL>
1455              
1456             This value will be assigned to the L<include_predicated_unique_indexes|Rose::DB::Object::Metadata/include_predicated_unique_indexes> attribute of the L<Rose::DB::Object::Metadata> object for each class created by this method. Defaults to the value of the loader object's L<include_predicated_unique_indexes|/include_predicated_unique_indexes> attribute.
1457              
1458             =item B<include_views BOOL>
1459              
1460             If true, database views will also be processed. Defaults to the value of the loader object's L<include_views|/include_views> attribute.
1461              
1462             =item B<post_init_hook [ CODEREF | ARRAYREF ]>
1463              
1464             A reference to a subroutine or a reference to an array of code references that will be called just after each L<Rose::DB::Object>-derived class is L<initialize|Rose::DB::Object::Metadata/initialize>d. Each referenced subroutine will be passed the class's L<metadata|Rose::DB::Object::Metadata> object plus any arguments to the L<initialize|Rose::DB::Object::Metadata/initialize> method. Defaults to the value of the loader object's L<post_init_hook|/post_init_hook> attribute.
1465              
1466             =item B<pre_init_hook [ CODEREF | ARRAYREF ]>
1467              
1468             A reference to a subroutine or a reference to an array of code references that will be called just before each L<Rose::DB::Object>-derived class is L<initialize|Rose::DB::Object::Metadata/initialize>d. Each referenced subroutine will be passed the class's L<metadata|Rose::DB::Object::Metadata> object plus any arguments to the L<initialize|Rose::DB::Object::Metadata/initialize> method. Defaults to the value of the loader object's L<pre_init_hook|/pre_init_hook> attribute.
1469              
1470             =item B<require_primary_key BOOL>
1471              
1472             If true, then any table that does not have a primary key will be skipped. Defaults to the value of the loader object's L<require_primary_key|/require_primary_key> attribute. Note that a L<Rose::DB::Object>-derived class based on a table with no primary key will not function correctly in all circumstances. Use this feature at your own risk.
1473              
1474             =item B<warn_on_missing_pk BOOL>
1475              
1476             This is an alias for the C<warn_on_missing_primary_key> parameter.
1477              
1478             =item B<warn_on_missing_primary_key BOOL>
1479              
1480             If true, then any table that does not have a primary key will trigger a warning.
1481              
1482             If C<require_primary_key> is false and the loader object's L<warn_on_missing_primary_key|/warn_on_missing_primary_key> attribute is undefined, or if the C<warn_on_missing_primary_key> parameter is set to an undefined value or is not passed to the L<make_classes|/make_classes> call at all, then C<warn_on_missing_primary_key> is set to false. Otherwise, it defaults to the value of the loader object's L<warn_on_missing_primary_key|/warn_on_missing_primary_key> attribute. Note that a L<Rose::DB::Object>-derived class based on a table with no primary key will not function correctly in all circumstances.
1483              
1484             These complicated defaults are intended to honor the intentions of the C<require_primary_key> attribute/parameter. If not requiring primary keys and no explicit decision has been made about whether to warn about missing primary keys, either in the parameters to the L<make_classes|/make_classes> call or in the loader object itself, then we don't warn about missing primary keys. The idea is that not requiring primary keys is a strong indication that their absence is not worth a warning.
1485              
1486             =item B<with_foreign_keys BOOL>
1487              
1488             If true, set up foreign key metadata for each L<Rose::DB::Object>-derived. Defaults to the value of the loader object's L<with_foreign_keys|/with_foreign_keys> attribute.
1489              
1490             =item B<with_managers BOOL>
1491              
1492             If true, create L<Rose::DB::Object::Manager|Rose::DB::Object::Manager>-derived manager classes for each L<Rose::DB::Object> subclass. Defaults to the value of the loader object's L<with_managers|/with_managers> attribute.
1493              
1494             The manager class name is determined by passing the L<Rose::DB::Object>-derived class name to the L<generate_manager_class_name|/generate_manager_class_name> method.
1495              
1496             The L<Rose::DB::Object> subclass's L<metadata object|Rose::DB::Object::Metadata>'s L<make_manager_class|Rose::DB::Object::Metadata/make_manager_class> method will be used to create the manager class. It will be passed the return value of the convention manager's L<auto_manager_base_name|Rose::DB::Object::ConventionManager/auto_manager_base_name> method as an argument.
1497              
1498             =item B<with_relationships [ BOOL | ARRAYREF ]>
1499              
1500             A boolean value or a reference to an array of relationship L<type|Rose::DB::Object::Metadata::Relationship/type> names. If set to a simple boolean value, then all types of relationships will be considered when making classes. If set to a list of relationship type names, then only relationships of those types will be considered. Defaults to the value of the loader object's L<with_relationships|/with_relationships> attribute.
1501              
1502             =item B<with_unique_keys BOOL>
1503              
1504             If true, set up unique key metadata for each L<Rose::DB::Object>-derived. Defaults to the value of the loader object's L<with_unique_keys|/with_unique_keys> attribute.
1505              
1506             =back
1507              
1508             Any remaining name/value parameters will be passed on to the call to L<auto_initialize|Rose::DB::Object::Metadata/auto_initialize> used to set up each class. For example, to ask the loader not to create any L<relationships|Rose::DB::Object::Metadata/relationships>, pass the C<with_relationships> parameter with a false value.
1509              
1510             $loader->make_classes(with_relationships => 0);
1511              
1512             This parameter will be passed on to the L<auto_initialize|Rose::DB::Object::Metadata/auto_initialize> method, which, in turn, will pass the parameter on to its own call to the L<auto_init_relationships|Rose::DB::Object::Metadata/auto_init_relationships> method. See the L<Rose::DB::Object::Metadata> documentation for more information on these methods.
1513              
1514             Each L<Rose::DB::Object> subclass will be created according to the "best practices" described in the L<Rose::DB::Object::Tutorial>. If a L<base class|/base_classes> is not provided, one (with a dynamically generated name) will be created automatically. The same goes for the L<db|/db> object. If one is not set, then a new (again, dynamically named) subclass of L<Rose::DB>, with its own L<private data source registry|Rose::DB/use_private_registry>, will be created automatically.
1515              
1516             This method returns a list (in list context) or a reference to an array (in scalar context) of the names of all the classes that were created. (This list will include L<manager|Rose::DB::Object::Manager> class names as well, if any were created.)
1517              
1518             =item B<make_modules [PARAMS]>
1519              
1520             Automatically create L<Rose::DB::Object> and (optionally) L<Rose::DB::Object::Manager> subclasses for some or all of the tables in a database, then create Perl module (*.pm) files for each class.
1521              
1522             This method calls L<make_classes|/make_classes> to make the actual classes.
1523              
1524             B<Note:> If you are trying to regenerate a set of module files that already exist in the target C<module_dir>, please make sure that this C<module_dir> is I<not> in your C<@INC> path. (That is, make sure it is not in the set of paths that perl will search when looking for module files in response to a C<use> or C<require> statement.) More generally, you must make sure that existing versions of the modules you are attempting to generate are not in your C<@INC> path.
1525              
1526             (If you do not do this, when L<make_classes|/make_classes> makes a class and looks for a related class, it will find and load the previously generated C<.pm> file, which will then cause L<make_classes|/make_classes> to skip that class later when it sees that it already exists in memory. And if L<make_classes|/make_classes> skips it, L<make_modules|/make_modules> will never see it and therefore will never regenerate the C<.pm> file.)
1527              
1528             This method takes all of the same parameters as L<make_classes|/make_classes>, with several additions:
1529              
1530             =over 4
1531              
1532             =item B<module_dir DIR>
1533              
1534             The path to the directory where the Perl module files will be created. For example, given a DIR of "/home/john/lib", the Perl module file for the class C<My::DB::Object> would be located at "/home/john/lib/My/DB/Object.pm".
1535              
1536             Defaults to the value of the loader object's L<module_dir|/module_dir> attribute. If the L<module_dir|/module_dir> attribute is also undefined, then the current working directory (as determined by a call to L<cwd()|Cwd/cwd>) is used instead.
1537              
1538             =item B<module_preamble [ SCALAR | CODE ]>
1539              
1540             If defined as a scalar, inserts the contents of the variable into the auto-generated file before any of the auto-generated class information. If provided as a code ref, calls the indicated function, passing the L<metadata object|Rose::DB::Object::Metadata> as a parameter. (The metadata object that belongs to the C<object_class> and the L<Rose::DB::Object::Manager>-derived class name are passed if the module is a L<Rose::DB::Object::Manager>-derived class.) The returned value of the function is inserted as the preamble text.
1541              
1542             Defaults to the value of the loader object's L<module_preamble|/module_preamble> attribute.
1543              
1544             =item B<module_postamble [ SCALAR | CODE ]>
1545              
1546             If defined as a scalar, inserts the contents of the variable into the auto-generated file after any of the auto-generated class information. If provided as a code ref, calls the indicated function, passing the L<metadata object|Rose::DB::Object::Metadata> as a parameter. (The metadata object that belongs to the C<object_class> and the L<Rose::DB::Object::Manager>-derived class name are passed if the module is a L<Rose::DB::Object::Manager>-derived class.) The returned value of the function is inserted as the postamble text.
1547              
1548             Defaults to the value of the loader object's L<module_postamble|/module_postamble> attribute.
1549              
1550             =back
1551              
1552             =item B<module_dir [DIR]>
1553              
1554             Get or set the path to the directory where L<make_modules|/make_modules> will create its Perl modules files. For example, given a DIR of "/home/john/lib", L<make_modules|/make_modules> would create the file "/home/john/lib/My/DB/Object.pm" for the class C<My::DB::Object>.
1555              
1556             =item B<module_preamble [ SCALAR | CODE ]>
1557              
1558             If defined as a scalar, inserts the contents of the variable into the auto-generated file before any of the auto-generated class information. If provided as a code ref, calls the indicated function, passing the L<metadata object|Rose::DB::Object::Metadata> as a parameter. (The metadata object that belongs to the C<object_class> and the L<Rose::DB::Object::Manager>-derived class name are passed if the module is a L<Rose::DB::Object::Manager>-derived class.) The returned value of the function is inserted as the preamble text.
1559              
1560             =item B<module_postamble [ SCALAR | CODE ]>
1561              
1562             If defined as a scalar, inserts the contents of the variable into the auto-generated file after any of the auto-generated class information. If provided as a code ref, calls the indicated function, passing the L<metadata object|Rose::DB::Object::Metadata> as a parameter. (The metadata object that belongs to the C<object_class> and the L<Rose::DB::Object::Manager>-derived class name are passed if the module is a L<Rose::DB::Object::Manager>-derived class.) The returned value of the function is inserted as the postamble text.
1563              
1564             =item B<pre_init_hook [CODE]>
1565              
1566             Get or set a reference to a subroutine to be called just before each L<Rose::DB::Object>-derived class is L<initialize|Rose::DB::Object::Metadata/initialize>ed within the L<make_classes|/make_classes> method. The subroutine will be passed the class's L<metdata|Rose::DB::Object::Metadata> object as an argument.
1567              
1568             =item B<require_primary_key BOOL>
1569              
1570             Get or set a boolean value that determines whether or not the L<make_classes|/make_classes> method will skip any table that does not have a primary key will be skipped. Defaults to true.
1571              
1572             Note that a L<Rose::DB::Object>-derived class based on a table with no primary key will not function correctly in all circumstances. Use this feature at your own risk.
1573              
1574             =item B<warn_on_missing_pk BOOL>
1575              
1576             This is an alias for the L<warn_on_missing_primary_key|/warn_on_missing_primary_key> method.
1577              
1578             =item B<warn_on_missing_primary_key BOOL>
1579              
1580             Get or set a boolean value that determines whether or not the L<make_classes|/make_classes> method will emit a warning when it encounters a table that does not have a primary key. Defaults to undefined.
1581              
1582             =item B<with_foreign_keys BOOL>
1583              
1584             If true, the L<make_classes|/make_classes> method will set up foreign key metadata for each L<Rose::DB::Object>-derived class it creates. Defaults to true.
1585              
1586             =item B<with_managers [BOOL]>
1587              
1588             If true, the L<make_classes|/make_classes> method will create L<Rose::DB::Object::Manager|Rose::DB::Object::Manager>-derived manager classes for each L<Rose::DB::Object> subclass by default. Defaults to true.
1589              
1590             The manager class name is determined by passing the L<Rose::DB::Object>-derived class name to the L<generate_manager_class_name|/generate_manager_class_name> method.
1591              
1592             The L<Rose::DB::Object> subclass's L<metadata object|Rose::DB::Object::Metadata>'s L<make_manager_class|Rose::DB::Object::Metadata/make_manager_class> method will be used to create the manager class. It will be passed the return value of the convention manager's L<auto_manager_base_name|Rose::DB::Object::ConventionManager/auto_manager_base_name> method as an argument.
1593              
1594             =item B<with_relationships [ BOOL | ARRAYREF ]>
1595              
1596             A boolean value or a reference to an array of relationship L<type|Rose::DB::Object::Metadata::Relationship/type> names. If set to a simple boolean value, then the L<make_classes|/make_classes> method will consider all types of relationships when making classes. If set to a list of relationship type names, then only relationships of those types will be considered by L<make_classes|/make_classes>. Defaults to true.
1597              
1598             =item B<with_unique_keys BOOL>
1599              
1600             If true, the L<make_classes|/make_classes> method will set up unique key metadata for each L<Rose::DB::Object>-derived class it creates. Defaults to true.
1601              
1602             =item B<manager_base_class CLASS>
1603              
1604             This is an alias for the L<manager_base_classes|/manager_base_classes> method.
1605              
1606             =item B<manager_base_classes [ CLASS | ARRAYREF ]>
1607              
1608             Get or set the list of base classes to use for the L<Rose::DB::Object::Manager> subclasses created by the L<make_classes|/make_classes> method. The argument may be a class name or a reference to an array of class names. At least one of the classes should inherit from L<Rose::DB::Object::Manager>.
1609              
1610             Returns a list (in list context) or reference to an array (in scalar context) of base class names. Defaults to L<Rose::DB::Object::Manager>.
1611              
1612             =back
1613              
1614             =head1 AUTHOR
1615              
1616             John C. Siracusa (siracusa@gmail.com)
1617              
1618             =head1 LICENSE
1619              
1620             Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is
1621             free software; you can redistribute it and/or modify it under the same terms
1622             as Perl itself.