File Coverage

blib/lib/DBIx/Class/Sims.pm
Criterion Covered Total %
statement 9 18 50.0
branch 0 4 0.0
condition n/a
subroutine 4 5 80.0
pod n/a
total 13 27 48.1


line stmt bran cond sub pod time code
1             # vim: set sw=2 ft=perl:
2             package DBIx::Class::Sims;
3              
4 26     26   2356659 use 5.010_001;
  26         64  
5              
6 26     26   455 use strictures 2;
  26         1523  
  26         810  
7              
8             our $VERSION = '0.300700';
9              
10             {
11             # Do **NOT** import a clone() function into the DBIx::Class::Schema namespace
12             # because that will override DBIC's clone() method and break all the things.
13             package MyCloner;
14              
15             sub clone {
16 0     0     my ($data) = @_;
17              
18 0 0         if (ref($data) eq 'HASH') {
    0          
19             return {
20 0           map { $_ => clone($data->{$_}) }
  0            
21             keys %$data
22             };
23             }
24             elsif (ref($data) eq 'ARRAY') {
25             return [
26 0           map { clone($_) }
  0            
27             @$data
28             ];
29             }
30              
31 0           return $data;
32             }
33             }
34              
35 26     26   16238 use DDP;
  26         666299  
  26         176  
36              
37 26     26   6644 use Data::Walk qw( walk );
  0            
  0            
38             use DateTime;
39             use DBIx::Class::TopoSort ();
40             use Hash::Merge qw( merge );
41             use List::Util qw( first );
42             use List::MoreUtils qw( natatime );
43             use Scalar::Util qw( blessed reftype );
44              
45             {
46             # The aliases in this block are done at BEGIN time so that the ::Types class
47             # can use them when it is loaded through `use`.
48              
49             my @sim_names;
50             my %sim_types;
51             my @sim_matchers;
52              
53             sub set_sim_type {
54             shift;
55             my $types = shift // '';
56              
57             if (ref($types) eq 'HASH') {
58             while ( my ($name, $meth) = each(%$types) ) {
59             next unless ref($meth) eq 'CODE';
60              
61             $sim_types{$name} = $meth;
62             push @sim_names, $name;
63             }
64             }
65             elsif (ref($types) eq 'ARRAY') {
66             foreach my $item (@$types) {
67             next unless ref($item->[2]) eq 'CODE';
68              
69             push @sim_names, $item->[0];
70             push @sim_matchers, [ qr/^$item->[1]$/, $item->[2] ];
71             }
72             }
73              
74             return;
75             }
76             BEGIN { *set_sim_types = \&set_sim_type; }
77              
78             sub __find_sim_type {
79             my ($str) = @_;
80              
81             unless (exists $sim_types{$str}) {
82             my $item = first { $str =~ $_->[0] } @sim_matchers;
83             if ($item) {
84             $sim_types{$str} = $item->[1];
85             }
86             }
87              
88             return $sim_types{$str};
89             }
90              
91             sub sim_type {
92             shift;
93              
94             # If no specific type requested, then return the complete list of all
95             # registered types.
96             return sort @sim_names if @_ == 0;
97              
98             return __find_sim_type($_[0]) if @_ == 1;
99             return map { __find_sim_type($_) } @_;
100             }
101             BEGIN { *sim_types = \&sim_type; }
102             }
103             use DBIx::Class::Sims::Types;
104              
105             use DBIx::Class::Sims::Runner;
106             use DBIx::Class::Sims::Util;
107              
108             sub add_sims {
109             my $class = shift;
110             my ($schema, $source, @remainder) = @_;
111              
112             my $rsrc = $schema->source($source);
113             my $it = natatime(2, @remainder);
114             while (my ($column, $sim_info) = $it->()) {
115             my $col_info = $schema->source($source)->column_info($column) // next;
116             $col_info->{sim} = merge(
117             $col_info->{sim} // {},
118             $sim_info // {},
119             );
120             }
121              
122             return;
123             }
124             *add_sim = \&add_sims;
125              
126             sub load_sims {
127             my $self = shift;
128             my $schema;
129             if (ref($self) && $self->isa('DBIx::Class::Schema')) {
130             $schema = $self;
131             }
132             else {
133             $schema = shift(@_);
134             }
135             my ($spec_proto, $opts_proto) = @_;
136             $spec_proto = MyCloner::clone($spec_proto // {});
137             $opts_proto = MyCloner::clone($opts_proto // {});
138              
139             my $spec = massage_input($schema, normalize_input($spec_proto));
140             my $opts = normalize_input($opts_proto);
141              
142             # 1. Ensure the belongs_to relationships are in $reqs
143             # 2. Set the rel_info as the leaf in $reqs
144             my $reqs = normalize_input($opts->{constraints} // {});
145              
146             # 2: Create the rows in toposorted order
147             my $hooks = $opts->{hooks} // {};
148             $hooks->{preprocess} //= sub {};
149             $hooks->{postprocess} //= sub {};
150              
151             # Create a lookup of the items passed in so we can return them back.
152             my $initial_spec = {};
153             foreach my $name (keys %$spec) {
154             my $normalized = DBIx::Class::Sims::Util->normalize_aoh($spec->{$name});
155             unless ($normalized) {
156             warn "Skipping $name - I don't know what to do!\n";
157             delete $spec->{$name};
158             next;
159             }
160             $spec->{$name} = $normalized;
161              
162             foreach my $item (@{$spec->{$name}}) {
163             $initial_spec->{$name}{$item} = 1;
164             }
165             }
166              
167             my ($rows, $additional) = ({}, {});
168             if (keys %{$spec}) {
169             # Yes, this invokes srand() twice, once in implicitly in rand() and once
170             # again right after. But, that's okay. We don't care what the seed is and
171             # this allows DBIC to be called multiple times in the same process in the
172             # same second without problems.
173             $additional->{seed} = $opts->{seed} //= rand(time & $$);
174             srand($opts->{seed});
175              
176             my @toposort = DBIx::Class::TopoSort->toposort(
177             $schema,
178             %{$opts->{toposort} // {}},
179             );
180              
181             my $runner = DBIx::Class::Sims::Runner->new(
182             parent => $self,
183             schema => $schema,
184             toposort => \@toposort,
185             initial_spec => $initial_spec,
186             spec => $spec,
187             hooks => $hooks,
188             reqs => $reqs,
189             );
190              
191             $rows = eval {
192             $runner->run();
193             }; if ($@) {
194             $additional->{error} = $@;
195              
196             if ($opts->{die_on_failure} // 1) {
197             warn "SEED: $opts->{seed}\n";
198             die $@;
199             }
200             }
201              
202             $additional->{created} = $runner->{created};
203             $additional->{duplicates} = $runner->{duplicates};
204              
205             # Force a reload from the database of every row we're returning.
206             foreach my $item (values %$rows) {
207             $_->discard_changes for @$item;
208             }
209             }
210              
211             if (wantarray) {
212             return ($rows, $additional);
213             }
214             else {
215             return $rows;
216             }
217             }
218              
219             use YAML::Any qw( LoadFile Load );
220             sub normalize_input {
221             my ($proto) = @_;
222              
223             if ( ref($proto) ) {
224             return $proto;
225             }
226              
227             # Doing a stat on a filename with a newline throws an error.
228             my $x = eval {
229             no warnings;
230             if ( -e $proto ) {
231             return LoadFile($proto);
232             }
233             };
234             return $x if $x;
235              
236             return Load($proto);
237             }
238              
239             sub massage_input {
240             my ($schema, $struct) = @_;
241              
242             my $dtp = $schema->storage->datetime_parser;
243             walk({
244             preprocess => sub {
245             # Don't descend into the weeds. Only do the things we care about.
246             return if grep { blessed($_) } @_;
247             return unless grep { reftype($_) } @_;
248             return @_;
249             },
250             wanted => sub {
251             return unless (reftype($_)//'') eq 'HASH' && !blessed($_);
252             foreach my $k ( keys %$_ ) {
253             my $t = $_;
254              
255             # Expand the dot-naming convention.
256             while ( $k =~ /([^.]*)\.(.*)/ ) {
257             $t->{$1} = { $2 => delete($t->{$k}) };
258             $t = $t->{$1}; $k = $2;
259             }
260              
261             # Handle DateTime values passed to us.
262             if (defined $t->{$k}) {
263             if ( $t->{$k} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)$/ ) {
264             # format_datetime() requires a DateTime object. This may be a
265             # string, therefore hoist it if need-be.
266             unless (blessed($t->{$k})) {
267             $t->{$k} = DateTime->new(
268             year => $1, month => $2, day => $3,
269             hour => $4, minute => $5, second => $6,
270             );
271             }
272             $t->{$k} = $dtp->format_datetime($t->{$k});
273             }
274             }
275             }
276             },
277             }, $struct);
278              
279             return $struct;
280             }
281              
282             1;
283             __END__
284              
285             =head1 NAME
286              
287             DBIx::Class::Sims - The addition of simulating data to DBIx::Class
288              
289             =head1 SYNOPSIS (CLASS VERSION)
290              
291             DBIx::Class::Sims->add_sims(
292             $schema, 'source_name',
293             address => { type => 'us_address' },
294             zip_code => { type => 'us_zipcode' },
295             # ...
296             );
297              
298             my $rows = DBIx::Class::Sims->load_sims($schema, {
299             Table1 => [
300             {}, # Take sims or default values for everything
301             { # Override some values, take sim values for others
302             column1 => 20,
303             column2 => 'something',
304             },
305             ],
306             });
307              
308             =head1 SYNOPSIS (COMPONENT VERSION)
309              
310             Within your schema class:
311              
312             __PACKAGE__->load_components('Sims');
313              
314             Within your resultsources, specify the sims generation rules for columns that
315             need specified.
316              
317             __PACKAGE__->add_columns(
318             ...
319             address => {
320             data_type => 'varchar',
321             is_nullable => 1,
322             data_length => 10,
323             sim => { type => 'us_address' },
324             },
325             zipcode => {
326             data_type => 'varchar',
327             is_nullable => 1,
328             data_length => 10,
329             sim => { type => 'us_zipcode' },
330             },
331             column1 => {
332             data_type => 'int',
333             is_nullable => 0,
334             sim => {
335             min => 10,
336             max => 20,
337             },
338             },
339             column2 => {
340             data_type => 'varchar',
341             is_nullable => 1,
342             data_length => 10,
343             default_value => 'foobar',
344             },
345             ...
346             );
347              
348             Later:
349              
350             $schema->deploy({
351             add_drop_table => 1,
352             });
353              
354             my $rows = $schema->load_sims({
355             Table1 => [
356             {}, # Take sims or default values for everything
357             { # Override some values, take sim values for others
358             column1 => 20,
359             column2 => 'something',
360             },
361             ],
362             });
363              
364             =head1 PURPOSE
365              
366             Generating test data for non-simplistic databases is extremely hard, especially
367             as the schema grows and changes. Designing scenarios B<should> be doable by only
368             specifying the minimal elements actually used in the test with the test being
369             resilient to any changes in the schema that don't affect the elements specified.
370             This includes changes like adding a new parent table, new required child tables,
371             and new non-NULL columns to the table being tested.
372              
373             With Sims, you specify only what you care about. Any required parent rows are
374             automatically generated. If a row requires a certain number of child rows (all
375             artists must have one or more albums), that can be set as well. If a column must
376             have specific data in it (a US zipcode or a range of numbers), you can specify
377             that in the table definition.
378              
379             And, in all cases, you can override anything.
380              
381             =head1 DESCRIPTION
382              
383             This is a L<DBIx::Class> component that adds a few methods to your
384             L<DBIx::Class::Schema> object. These methods make it much easier to create data
385             for testing purposes (though, obviously, it's not limited to just test data).
386              
387             Alternately, it can be used as a class method vs. a component, if that fits your
388             needs better.
389              
390             =head1 METHODS
391              
392             =head2 load_sims
393              
394             C<< $rv, $addl? = $schema->load_sims( $spec, ?$opts ) >>
395             C<< $rv, $addl? = DBIx::Class::Sims->load_sims( $schema, $spec, ?$opts ) >>
396              
397             This method will load the rows requested in C<$spec>, plus any additional rows
398             necessary to make those rows work. This includes any parent rows (as defined by
399             C<belongs_to>) and per any constraints defined in C<$opts->{constraints}>. If
400             need-be, you can pass in hooks (as described below) to manipulate the data.
401              
402             load_sims does all of its work within a call to L<DBIx::Class::Schema/txn_do>.
403             If anything goes wrong, load_sims will rethrow the error after the transaction
404             is rolled back.
405              
406             This, of course, assumes that the tables you are working with support
407             transactions. (I'm looking at you, MyISAM!) If they do not, that is on you.
408              
409             =head3 Return value
410              
411             This returns one or two values, depending on if you call load_sims in a scalar
412             or array context.
413              
414             The first value is a hash of arrays of hashes. This will match the C<$spec>,
415             except that where the C<$spec> has a requested set of things to make, the return
416             will have the DBIx::Class::Row objects that were created.
417              
418             Note that you do not get back the objects for anything other than the objects
419             specified at the top level.
420              
421             This second value is a hashref with additional items that may be useful. It may
422             contain:
423              
424             =over 4
425              
426             =item * error
427              
428             This will contain any error that happened while trying to create the rows.
429              
430             This is most useful when C<< die_on_failure >> is set to 0.
431              
432             =item * seed
433              
434             This is the random seed that was used in this run. If you set the seed in the
435             opts parameter in the load_sims call, it will be that value. Otherwise, it will
436             be set to a usefully random value for you. It will be different every time even
437             if you call load_sims multiple times within the same process in the same second.
438              
439             =item * created
440              
441             This is a hashref containing a count of each source that was created. This is
442             different from the first return value in that this lists everything created, not
443             just what was requested. It also only has counts, not the actual rows.
444              
445             =item * duplicates
446              
447             This is a hashref containing a list for each source of all the duplicates that
448             were found when creating rows for that source. For each duplicate found, there
449             will be an entry that specifies the criteria used to find that duplicate and the
450             row in the database that was found.
451              
452             The list will be ordered by when the duplicate was found, but that ordering will
453             B<NOT> be stable across different runs unless the same C<< seed >> is used.
454              
455             =back
456              
457             =head2 set_sim_type
458              
459             C<< $class_or_obj->set_sim_type({ $name => $handler, ... }); >>
460             C<< $class_or_obj->set_sim_type([ [ $name, $regex, $handler ], ... ]); >>
461              
462             This method will set the handler for the C<$name> sim type. The C<$handler> must
463             be a reference to a subroutine. You may pass in as many name/handler pairs as you
464             like.
465              
466             You may alternately pass in an arrayref of triplets. This allows you to use a
467             regex to match the provided type. C<$name> will be returned when the user
468             introspects the list of loaded sim types. C<$regex> will be used when finding the
469             type to handle this column. C<$handler> must be a reference to a subroutine.
470              
471             You cannot set pairs and triplets in the same invocation.
472              
473             This method may be called as a class or object method.
474              
475             This method returns nothing.
476              
477             C<set_sim_types()> is an alias to this method.
478              
479             =head2 sim_types
480              
481             C<< $class_or_obj->sim_types(); >>
482              
483             This method will return a sorted list of all registered sim types.
484              
485             This method may be called as a class or object method.
486              
487             =head1 SPECIFICATION
488              
489             The specification can be passed along as a filename that contains YAML or JSON,
490             a string that contains YAML or JSON, or as a hash of arrays of hashes. The
491             structure should look like:
492              
493             {
494             ResultSourceName => [
495             {
496             column => $value,
497             column => $value,
498             relationship => $parent_object,
499             relationship => {
500             column => $value,
501             },
502             'relationship.column' => $value,
503             'rel1.rel2.rel3.column' => $value,
504             },
505             ],
506             }
507              
508             If a column is a belongs_to relationship name, then the row associated with that
509             relationship specifier will be used. This is how you would specify a specific
510             parent-child relationship. (Otherwise, a random choice will be made as to which
511             parent to use, creating one as necessary if possible.) The dots will be followed
512             as far as necessary.
513              
514             If a column's value is a reference to a hashref, then that will be treated as a
515             sim entry. Example:
516              
517             {
518             Artist => [
519             {
520             name => \{ type => 'us_name' },
521             },
522             ],
523             }
524              
525             That will use the provided sim type 'us_name'. This will override any sim entry
526             specified on the column. See L</SIM ENTRY> for more information.
527              
528             Columns that have not been specified will be populated in one of two ways. The
529             first is if the database has a default value for it. Otherwise, you can specify
530             the C<sim> key in the column_info for that column. This is a new key that is not
531             used by any other component. See L</SIM ENTRY> for more information.
532              
533             (Please see L<DBIx::Class::ResultSource/add_columns> for details on column_info)
534              
535             B<NOTE>: The keys of the outermost hash are resultsource names. The keys within
536             the row-specific hashes are either columns or relationships. Not resultsources.
537              
538             =head2 Reuse wherever possible
539              
540             The Sims's normal behavior is to attempt to reuse whenever possible. The theory
541             is that if you didn't say you cared about something, you do B<NOT> care about
542             that thing.
543              
544             =head3 Unique constraints
545              
546             If a source has unique constraints defined, the Sims will use them to determine
547             if a new row with these values I<can> be created or not. If a row already
548             exists with these values for the unique constraints, then that row will be used
549             instead of creating a new one.
550              
551             This is B<REGARDLESS> of the values for the non-unique-constraint rows.
552              
553             =head3 Forcing creation of a parent
554              
555             If you do not specify values for a parent (i.e., belongs_to), then the first row
556             for that parent will be be used. If you don't care what values the parent has,
557             but you care that a different parent is used, then you can set the __META__ key
558             as follows:
559              
560             $schema->load_sims({
561             Album => {
562             artist => { __META__ => { create => 1 } },
563             name => 'Some name',
564             }
565             })
566              
567             This will force the creation of a parent instead of reusing the parent.
568              
569             B<NOTE>: If the simmed values within the parent's class would result in values
570             that are the same across a unique constraint with an existing row, then that
571             row will be used. This just bypasses the "attempt to use the first parent".
572              
573             =head2 Alternatives
574              
575             =head3 Hard-coded number of things
576              
577             If you only want N of a thing, not really caring just what the column values end
578             up being, you can take a shortcut:
579              
580             {
581             ResultSourceName => 3,
582             }
583              
584             That will create 3 of that thing, taking all the defaults and sim'ed options as
585             exist.
586              
587             This will also work if you want 3 of a child via a has_many relationship. For
588             example, you can do:
589              
590             {
591             Artist => {
592             name => 'Someone Famous',
593             albums => 240,
594             },
595             }
596              
597             That will create 240 different albums for that artist, all with the defaults.
598              
599             =head3 Just one thing
600              
601             If you are creating one of a thing and setting some of the values, you can skip
602             the arrayref and pass the hashref directly.
603              
604             {
605             ResultSourceName => {
606             column => $value,
607             column => $value,
608             relationship => {
609             column => $value,
610             },
611             'relationship.column' => $value,
612             'rel1.rel2.rel3.column' => $value,
613             },
614             }
615              
616             And that will work exactly as expected.
617              
618             =head3 References
619              
620             Let's say you have a table that's a child of two other tables. You can specify
621             that relationship as follows:
622              
623             {
624             Parent1 => 1,
625             Parent2 => {
626             Child => {
627             parent1 => \"Parent1[0]",
628             },
629             },
630             }
631              
632             That's a reference to a string with the tablename as a pseudo-array, then the
633             index into that array. This only works for rows that you are going to return
634             back from the C<< load_sims() >> call.
635              
636             This also only works for belongs_to relationships. Since all parents are created
637             before all children, the Sims cannot back-reference into children.
638              
639             =head2 Notes
640              
641             =over 4
642              
643             =item * Multiply-specified children
644              
645             Sometimes, you will have a table with more than one parent (q.v. t/t5.t for an
646             example of this). If you specify a row for each parent and, in each parent,
647             specify a child with the same characteristics, only one child will be created.
648             The assumption is that you meant the same row.
649              
650             This does B<not> apply to creating multiple rows with the same characteristics
651             as children of the same parent. The assumption is that you meant to do that.
652              
653             =back
654              
655             =head1 OPTS
656              
657             There are several possible options.
658              
659             =head2 constraints
660              
661             The constraints can be passed along as a filename that contains YAML or JSON, a
662             string that contains YAML or JSON, or as a hash of arrays of hashes. The
663             structure should look like:
664              
665             {
666             Person => {
667             addresses => 2,
668             },
669             }
670              
671             All the C<belongs_to> relationships are automatically added to the constraints.
672             You can add additional constraints, as needed. The most common use for this will
673             be to add required child rows. For example, C<< Person->has_many('addresses') >>
674             would normally mean that if you create a Person, no Address rows would be
675             created. But, we could specify a constraint that says "Every person must have
676             at least 2 addresses." Now, whenever a Person is created, two Addresses will be
677             added along as well, if they weren't already created through some other
678             specification.
679              
680             =head2 die_on_failure
681              
682             If set to 0, this will prevent a die when creating a row. Instead, you will be
683             responsible for checking C<< $additional->{error} >> yourself.
684              
685             This defaults to 1.
686              
687             =head2 seed
688              
689             If set, this will be the srand() seed used for this invocation.
690              
691             =head2 toposort
692              
693             This is passed directly to the call to C<< DBIx::Class::TopoSort->toposort >>.
694              
695             =head2 hooks
696              
697             Most people will never need to use this. But, some schema definitions may have
698             reasons that prevent a clean simulating with this module. For example, there may
699             be application-managed sequences. To that end, you may specify the following
700             hooks:
701              
702             =over 4
703              
704             =item * preprocess
705              
706             This receives C<$name, $source, $spec> and expects nothing in return. C<$spec>
707             is the hashref that will be passed to C<<$schema->resultset($name)->create()>>.
708             This hook is expected to modify C<$spec> as needed.
709              
710             =item * postprocess
711              
712             This receives C<$name, $source, $row> and expects nothing in return. This hook
713             is expected to modify the newly-created row object as needed.
714              
715             =back
716              
717             =head1 SIM ENTRY
718              
719             To control how a column's values are simulated, add a "sim" entry in the
720             column_info for that column. The sim entry is a hash that can have the followingkeys:
721              
722             =over 4
723              
724             =item * value / values
725              
726             This behaves just like default_value would behave, but doesn't require setting a
727             default value on the column.
728              
729             sim => {
730             value => 'The value to always use',
731             },
732              
733             This can be either a string, number, or an arrayref of strings or numbers. If it
734             is an arrayref, then a random choice from that array will be selected.
735              
736             =item * type
737              
738             This labels the column as having a certain type. A type is registered using
739             L</set_sim_type>. The type acts as a name for a function that's used to generate
740             the value. See L</Types> for more information.
741              
742             =item * min / max
743              
744             If the column is numeric, then the min and max bound the random value generated.
745             If the column is a string, then the min and max are the length of the random
746             value generated.
747              
748             =item * func
749              
750             This is a function that is provided the column info. Its return value is used to
751             populate the column.
752              
753             =item * null_chance
754              
755             If the column is nullable I<and> this is set I<and> it is a number between 0 and
756             1, then if C<rand()> is less than that number, the column will be set to null.
757             Otherwise, the standard behaviors will apply.
758              
759             If the column is B<not> nullable, this setting is ignored.
760              
761             =back
762              
763             (Please see L<DBIx::Class::ResultSource/add_columns> for details on column_info)
764              
765             =head2 Types
766              
767             The handler for a sim type will receive the column info (as defined in
768             L<DBIx::Class::ResultSource/add_columns>). From that, the handler returns the
769             value that will be used for this column.
770              
771             Please see L<DBIx::Class::Sims::Types> for the list of included sim types.
772              
773             =head1 SEQUENCE OF EVENTS
774              
775             When an item is created, the following actions are taken (in this order):
776              
777             =over 4
778              
779             =item 1 The columns are fixed up.
780              
781             This is where generated values are generated. After this is done, all the values
782             that will be inserted into the database are now available.
783              
784             q.v. L</SIM ENTRY> for more information.
785              
786             =item 1 The preprocess hook fires.
787              
788             You can modify the hashref as necessary. This includes potentially changing what
789             parent and/or child rows to associate with this row.
790              
791             =item 1 All foreign keys are resolved.
792              
793             If it's a parent relationship, the parent row will be found or created. All
794             parent rows will go through the same sequence of events as described here.
795              
796             If it's a child relationship, creation of the child rows will be deferred until
797             later.
798              
799             =item 1 The row is found or created.
800              
801             It might be found by unique constraint or created.
802              
803             =item 1 All child relationships are handled
804              
805             Because they're a child relationship, they are deferred until the time that
806             model is handled in the toposorted graph. They are not created now because they
807             might associate with a different parent that has not been created yet.
808              
809             =item 1 The postprocess hook fires.
810              
811             Note that any child rows are not guaranteed to exist yet.
812              
813             =back
814              
815             =head1 TODO
816              
817             =head2 Multi-column types
818              
819             In some applications, columns like "state" and "zipcode" are correlated. Values
820             for one must be legal for the value in the other. The Sims currently has no way
821             of generating correlated columns like this.
822              
823             This is most useful for saying "These 6 columns should be a coherent address".
824              
825             =head2 Allow a column to reference other columns
826              
827             Sometimes, a column should alter its behavior based on other columns. A fullname
828             column may have the firstname and lastname columns concatenated, with other
829             things thrown in. Or, a zipcode column should only generate a zipcode that're
830             legal for the state.
831              
832             =head1 BUGS/SUGGESTIONS
833              
834             This module is hosted on Github at
835             L<https://github.com/robkinyon/dbix-class-sims>. Pull requests are strongly
836             encouraged.
837              
838             =head1 DBIx::Class::Fixtures
839              
840             L<DBIx::Class::Fixtures> is another way to load data into a database. Unlike
841             this module, L<DBIx::Class::Fixtures> approaches the problem by loading the same
842             data every time. This is complementary because some tables (such as lookup
843             tables of countries) want to be seeded with the same data every time. The ideal
844             solution would be to have a set of tables loaded with fixtures and another set
845             of tables loaded with sims.
846              
847             =head1 SEE ALSO
848              
849             L<DBIx::Class>, L<DBIx::Class::Fixtures>
850              
851             =head1 AUTHOR
852              
853             Rob Kinyon <rob.kinyon@gmail.com>
854              
855             =head1 LICENSE
856              
857             Copyright (c) 2013 Rob Kinyon. All Rights Reserved.
858             This is free software, you may use it and distribute it under the same terms
859             as Perl itself.
860              
861             =cut