[Bast-commits] r3221 - in branches/DBIx-Class-current: . lib/DBIx lib/DBIx/Class lib/DBIx/Class/CDBICompat lib/DBIx/Class/InflateColumn lib/DBIx/Class/Manual lib/DBIx/Class/Storage t t/cdbi-t t/testlib

blblack at dev.catalyst.perl.org blblack at dev.catalyst.perl.org
Tue May 1 06:41:33 GMT 2007


Author: blblack
Date: 2007-05-01 06:41:32 +0100 (Tue, 01 May 2007)
New Revision: 3221

Added:
   branches/DBIx-Class-current/lib/DBIx/Class/Manual/Joining.pod
   branches/DBIx-Class-current/t/testlib/OtherThing.pm
   branches/DBIx-Class-current/t/testlib/Thing.pm
Modified:
   branches/DBIx-Class-current/
   branches/DBIx-Class-current/Changes
   branches/DBIx-Class-current/MANIFEST.SKIP
   branches/DBIx-Class-current/lib/DBIx/Class.pm
   branches/DBIx-Class-current/lib/DBIx/Class/CDBICompat/HasMany.pm
   branches/DBIx-Class-current/lib/DBIx/Class/Componentised.pm
   branches/DBIx-Class-current/lib/DBIx/Class/InflateColumn/DateTime.pm
   branches/DBIx-Class-current/lib/DBIx/Class/Manual.pod
   branches/DBIx-Class-current/lib/DBIx/Class/Manual/Cookbook.pod
   branches/DBIx-Class-current/lib/DBIx/Class/Manual/FAQ.pod
   branches/DBIx-Class-current/lib/DBIx/Class/Manual/Intro.pod
   branches/DBIx-Class-current/lib/DBIx/Class/Manual/Troubleshooting.pod
   branches/DBIx-Class-current/lib/DBIx/Class/Ordered.pm
   branches/DBIx-Class-current/lib/DBIx/Class/Relationship.pm
   branches/DBIx-Class-current/lib/DBIx/Class/ResultSet.pm
   branches/DBIx-Class-current/lib/DBIx/Class/ResultSource.pm
   branches/DBIx-Class-current/lib/DBIx/Class/Row.pm
   branches/DBIx-Class-current/lib/DBIx/Class/Schema.pm
   branches/DBIx-Class-current/lib/DBIx/Class/Storage/DBI.pm
   branches/DBIx-Class-current/t/76joins.t
   branches/DBIx-Class-current/t/cdbi-t/09-has_many.t
Log:
 r20551 at brandon-blacks-computer (orig r3005):  castaway | 2007-01-05 03:25:11 -0600
 add inflatecolumn fixes to Changes
 
 r20553 at brandon-blacks-computer (orig r3007):  castaway | 2007-01-09 15:20:55 -0600
 todoify collapse test
 
 r20554 at brandon-blacks-computer (orig r3008):  castaway | 2007-01-09 15:42:59 -0600
 Up version to 0.07004
 
 r20555 at brandon-blacks-computer (orig r3009):  castaway | 2007-01-09 15:44:39 -0600
 0.07004
 
 r20556 at brandon-blacks-computer (orig r3010):  castaway | 2007-01-10 11:54:19 -0600
 Skip .orig files in dist
 
 r20557 at brandon-blacks-computer (orig r3011):  castaway | 2007-01-10 13:37:23 -0600
 oops, remove .orig files etc
 
 r20599 at brandon-blacks-computer (orig r3053):  zarquon | 2007-01-23 04:15:05 -0600
 minor doc improvement to clarify how to do joins
 r20604 at brandon-blacks-computer (orig r3058):  zarquon | 2007-01-24 15:48:07 -0600
 explained a cryptic error message
 r20610 at brandon-blacks-computer (orig r3064):  castaway | 2007-01-29 10:28:12 -0600
 Make POD a little more obvious about component order
  --This line, and those below, will be ignored--
 
 M    DateTime.pm
 
 r20616 at brandon-blacks-computer (orig r3070):  jester | 2007-01-31 17:59:06 -0600
 Doc cleanup in Ordered.pm
 r20618 at brandon-blacks-computer (orig r3072):  castaway | 2007-02-02 13:48:53 -0600
 POD updates
 
 r20619 at brandon-blacks-computer (orig r3073):  ash | 2007-02-03 15:33:19 -0600
 Made ->update not change the hashref passed in (with test.)
 r20621 at brandon-blacks-computer (orig r3075):  ash | 2007-02-05 06:29:52 -0600
 Backed out my r3073, and doc'd the fact that it takes a hashref that might be changed
 r20622 at brandon-blacks-computer (orig r3076):  castaway | 2007-02-05 07:56:35 -0600
 Add _accessor example, thanks to grinktt3n
 
 r20623 at brandon-blacks-computer (orig r3077):  castaway | 2007-02-05 08:23:22 -0600
 Fix overload example
 
 r20625 at brandon-blacks-computer (orig r3079):  grink1tt3n | 2007-02-06 13:40:00 -0600
 Added;
 	FAQ-fetch-a-formatted-column.txt
 	FAQ-store-JSON-in-a-column.txt
 
 
 r20640 at brandon-blacks-computer (orig r3094):  castaway | 2007-02-08 02:25:54 -0600
 Argh! Fix spurious example
 
 r20643 at brandon-blacks-computer (orig r3097):  castaway | 2007-02-13 08:00:21 -0600
 Improve resultset_attributes docs
 
 r20644 at brandon-blacks-computer (orig r3098):  grink1tt3n | 2007-02-14 01:16:40 -0600
 Fleshed out the JSON inflated column example with a corresponding YAML example. Added a cautionary warning against overuse. Added a link to InflateColumn.
 
 
 r20645 at brandon-blacks-computer (orig r3099):  grink1tt3n | 2007-02-14 02:39:26 -0600
 Added how to '.. fetch a single (or topmost) row?' to the FAQ
 
 
 r20646 at brandon-blacks-computer (orig r3100):  zarquon | 2007-02-14 02:44:18 -0600
 improved docs for as attrib
 r20647 at brandon-blacks-computer (orig r3101):  zarquon | 2007-02-14 04:05:51 -0600
 pointed out ambiguity of as attribs
 r26909 at brandon-blacks-computer (orig r3107):  castaway | 2007-03-03 06:15:03 -0600
 Fix to $filename from Carl Vincent
 
 r27114 at brandon-blacks-computer (orig r3126):  jshirley | 2007-03-12 16:27:08 -0500
 Updating Manual/Intro to reflect better -in => [] usage, adding myself to contributors (mst put me in dbic-devel, too)
 r27116 at brandon-blacks-computer (orig r3128):  castaway | 2007-03-14 10:02:44 -0500
 Added patch from Schwern to allow cdbi compat to infer the has_many from a has_a
 
 r27119 at brandon-blacks-computer (orig r3129):  castaway | 2007-03-16 11:04:07 -0500
 Initial version of Manual::Joining
 
 r27120 at brandon-blacks-computer (orig r3130):  castaway | 2007-03-16 11:06:21 -0500
 Add FAQ and Joining links to Manual.pod
 
 r27319 at brandon-blacks-computer (orig r3148):  blblack | 2007-03-29 08:42:27 -0500
 fix for rt.cpan.org #25683 (DBD::Sybase/FreeTDS/MSSQL cannot have two open sths during column_info
 r27324 at brandon-blacks-computer (orig r3153):  blblack | 2007-03-29 09:13:17 -0500
 backport Ash's quoting fix from Loader to columns_info_for
 r29666 at brandon-blacks-computer (orig r3173):  castaway | 2007-04-02 17:19:05 -0500
 Add patch from dec to allow us to pick which sources to deploy
 
 r30330 at brandon-blacks-computer (orig r3185):  matthewt | 2007-04-09 15:41:34 -0500
 add SQL::Abstract to search docs (patch from zamolxes)
 r30510 at brandon-blacks-computer (orig r3189):  blblack | 2007-04-13 19:09:32 -0500
 fixed regex in t/76joins (was relying on a 5.8.8 bug that is fixed in bleadperl, so this test was failing on bleadperl)
 r30560 at brandon-blacks-computer (orig r3196):  marcus | 2007-04-16 07:55:44 -0500
 Updated cookbook example
 r30589 at brandon-blacks-computer (orig r3199):  blblack | 2007-04-17 18:45:11 -0500
 Changes list synced up through now
 r30590 at brandon-blacks-computer (orig r3200):  blblack | 2007-04-17 18:47:03 -0500
 cleared up a Changes entry
 r30591 at brandon-blacks-computer (orig r3201):  blblack | 2007-04-17 19:21:01 -0500
 0.07006 changes, version update
 r30607 at brandon-blacks-computer (orig r3202):  matthewt | 2007-04-18 21:29:05 -0500
 reverting r3173, already implemented in -current
 r30709 at brandon-blacks-computer (orig r3208):  matthewt | 2007-04-24 17:04:02 -0500
 oops. props to chapman for the spot
 r30762 at brandon-blacks-computer (orig r3220):  blblack | 2007-05-01 00:25:33 -0500
 load-time performance improvements



Property changes on: branches/DBIx-Class-current
___________________________________________________________________
Name: svk:merge
   - 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
78d5d833-3a7e-474d-aed6-cfba645156b5:/local/DBIx-Class.current:29201
78d5d833-3a7e-474d-aed6-cfba645156b5:/local/DBIx-Class.oracle8:29250
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:3122
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/column_info_from_storage:2596
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/load_namespaces:2725
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/param_bind:3015
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/source-handle:2975
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/storage_exceptions:2617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/versioning:2930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:2994
   + 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
78d5d833-3a7e-474d-aed6-cfba645156b5:/local/DBIx-Class.current:29201
78d5d833-3a7e-474d-aed6-cfba645156b5:/local/DBIx-Class.oracle8:29250
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/column_info_from_storage:2596
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/load_namespaces:2725
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/param_bind:3015
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/source-handle:2975
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/storage_exceptions:2617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/versioning:2930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3220

Modified: branches/DBIx-Class-current/Changes
===================================================================
--- branches/DBIx-Class-current/Changes	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/Changes	2007-05-01 05:41:32 UTC (rev 3221)
@@ -9,6 +9,14 @@
           is_foreign_key_constrain to allow explicit control over wether or
           not a foreign constraint is needed
 
+0.07006 2007-04-17 23:18:00
+        - Lots of documentation updates
+        - deploy now takes an optional 'source_names' parameter (dec)
+        - Quoting for for columns_info_for
+        - RT#25683 fixed (multiple open sths on DBD::Sybase)
+        - CDBI compat infers has_many from has_a (Schwern)
+        - Fix ddl_filename transformation (Carl Vincent)
+
 0.07999_02 2007-01-25 20:11:00
         - add support for binding BYTEA and similar parameters (w/Pg impl)
         - add support to Ordered for multiple ordering columns
@@ -18,6 +26,24 @@
         - Changed row and rs objects to not have direct handle to a source,
           instead a (schema,source_name) tuple of type ResultSourceHandle
 
+0.07005 2007-01-10 18:36:00
+        - fixup changes file
+        - remove erroneous .orig files - oops
+
+0.07004 2007-01-09 21:52:00
+        - fix find_related-based queries to correctly grep the unique key
+        - fix InflateColumn to inflate/deflate all refs but scalar refs
+
+0.07003 2006-11-16 11:52:00
+        - fix for rt.cpan.org #22740 (use $^X instead of hardcoded "perl")
+        - Tweaks to resultset to allow inflate_result to return an array
+        - Fix UTF8Columns to work under Perl <= 5.8.0
+        - Fix up new_result in ResultSet to avoid alias-related bugs
+        - Made new/update/find handle 'single' rel accessor correctly
+        - Fix NoBindVars to be safer and handle non-true bind values
+        - Don't blow up if columns_info_for returns useless results
+        - Documentation updates
+
 0.07999_01 2006-10-05 21:00:00
         - add connect_info option "disable_statement_caching"
         - create insert_bulk using execute_array, populate uses it
@@ -41,19 +67,6 @@
           These accessors no longer automatically require the classes when
           set.
 
-0.07004
-        - fix find_related-based queries to correctly grep the unique key
-
-0.07003 2006-11-16 11:52:00
-        - fix for rt.cpan.org #22740 (use $^X instead of hardcoded "perl")
-        - Tweaks to resultset to allow inflate_result to return an array
-        - Fix UTF8Columns to work under Perl <= 5.8.0
-        - Fix up new_result in ResultSet to avoid alias-related bugs
-        - Made new/update/find handle 'single' rel accessor correctly
-        - Fix NoBindVars to be safer and handle non-true bind values
-        - Don't blow up if columns_info_for returns useless results
-        - Documentation updates
-
 0.07002 2006-09-14 21:17:32
         - fix quote tests for recent versions of SQLite
         - added reference implementation of Manual::Example

Modified: branches/DBIx-Class-current/MANIFEST.SKIP
===================================================================
--- branches/DBIx-Class-current/MANIFEST.SKIP	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/MANIFEST.SKIP	2007-05-01 05:41:32 UTC (rev 3221)
@@ -41,5 +41,8 @@
 # Skip maint stuff
 ^maint/
 
+# Avoid copies to .orig
+\.orig$
+
 # Dont use Module::Build anymore
 # Build.PL

Modified: branches/DBIx-Class-current/lib/DBIx/Class/CDBICompat/HasMany.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/CDBICompat/HasMany.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/CDBICompat/HasMany.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -20,6 +20,12 @@
     $args->{cascade_delete} = 0;
   }
 
+  if( !$f_key and !@f_method ) {
+      my $f_source = $f_class->result_source_instance;
+      ($f_key) = grep { $f_source->relationship_info($_)->{class} eq $class }
+                      $f_source->relationships;
+  }
+
   $class->next::method($rel, $f_class, $f_key, $args);
 
   if (@f_method) {

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Componentised.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Componentised.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Componentised.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -33,8 +33,7 @@
   # it on the basis of the comments in Class::C3, the author was on #dbix-class
   # while I was implementing this.
 
-  my $table = { Class::C3::_dump_MRO_table };
-  eval "package $target; import Class::C3;" unless exists $table->{$target};
+  eval "package $target; import Class::C3;" unless exists $Class::C3::MRO{$target};
 }
 
 sub load_components {

Modified: branches/DBIx-Class-current/lib/DBIx/Class/InflateColumn/DateTime.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/InflateColumn/DateTime.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/InflateColumn/DateTime.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -14,7 +14,7 @@
 columns to be of the datetime, timestamp or date datatype.
 
   package Event;
-  __PACKAGE__->load_components(qw/InflateColumn::DateTime/);
+  __PACKAGE__->load_components(qw/Core InflateColumn::DateTime/);
   __PACKAGE__->add_columns(
     starts_when => { data_type => 'datetime' }
   );
@@ -33,7 +33,7 @@
 that this feature is new as of 0.07, so it may not be perfect yet - bug
 reports to the list very much welcome).
 
-For more help with components, see L<DBIx::Class::Manual::Component>.
+For more help with using components, see L<DBIx::Class::Manual::Component/USING>.
 
 =cut
 

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Manual/Cookbook.pod
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Manual/Cookbook.pod	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Manual/Cookbook.pod	2007-05-01 05:41:32 UTC (rev 3221)
@@ -107,12 +107,15 @@
   );
 
   # Equivalent SQL:
-  # SELECT name name, LENGTH( name ) name_length
+  # SELECT name name, LENGTH( name )
   # FROM artist
 
-If your alias exists as a column in your base class (i.e. it was added
-with C<add_columns>), you just access it as normal. Our C<Artist>
-class has a C<name> column, so we just use the C<name> accessor:
+Note that the C< as > attribute has absolutely nothing to with the sql
+syntax C< SELECT foo AS bar > (see the documentation in
+L<DBIx::Class::ResultSet/ATTRIBUTES>).  If your alias exists as a
+column in your base class (i.e. it was added with C<add_columns>), you
+just access it as normal. Our C<Artist> class has a C<name> column, so
+we just use the C<name> accessor:
 
   my $artist = $rs->first();
   my $name = $artist->name();
@@ -139,7 +142,7 @@
       select => [
         { distinct => [ $source->columns ] }
       ],
-      as => [ $source->columns ]
+      as => [ $source->columns ] # remember 'as' is not the same as SQL AS :-)
     }
   );
 
@@ -176,6 +179,10 @@
   # LEFT JOIN cd cds ON ( cds.artist = me.artistid )
   # GROUP BY name
 
+Please see L<DBIx::Class::ResultSet/ATTRIBUTES> documentation if you
+are in any way unsure about the use of the attributes above (C< join
+>, C< select >, C< as > and C< group_by >).
+
 =head3 Predefined searches
 
 You can write your own L<DBIx::Class::ResultSet> class by inheriting from it
@@ -415,7 +422,7 @@
     {},
     { 
        select => [ { sum => 'Cost' } ],
-       as     => [ 'total_cost' ],
+       as     => [ 'total_cost' ], # remember this 'as' is for DBIx::Class::ResultSet not SQL
     }
   );
   my $tc = $rs->first->get_column('total_cost');
@@ -526,7 +533,7 @@
 
 =head2 Many-to-many relationships
 
-This is straightforward using L<DBIx::Class::Relationship::ManyToMany>:
+This is straightforward using L<ManyToMany|DBIx::Class::Relationship/many_to_many>:
 
   package My::DB;
   # ... set up connection ...
@@ -568,7 +575,9 @@
 
     $attrs->{foo} = 'bar' unless defined $attrs->{foo};
 
-    $class->next::method($attrs);
+    my $new = $class->next::method($attrs);
+
+    return $new;
   }
 
 For more information about C<next::method>, look in the L<Class::C3> 
@@ -586,7 +595,7 @@
 To make an object stringify itself as a single column, use something
 like this (replace C<foo> with the column/method of your choice):
 
-  use overload '""' => 'foo', fallback => 1;
+  use overload '""' => sub { shift->name}, fallback => 1;
 
 For more complex stringification, you can use an anonymous subroutine:
 
@@ -1122,4 +1131,43 @@
     # do whatever else you wanted if it was a new row
   }
 
+=head3 Wrapping/overloading a column accessor
+
+Problem: Say you have a table "Camera" and want to associate a description
+with each camera. For most cameras, you'll be able to generate the description from
+the other columns. However, in a few special cases you may want to associate a
+custom description with a camera.
+
+Solution:
+
+In your database schema, define a description field in the "Camera" table that
+can contain text and null values.
+
+In DBIC, we'll overload the column accessor to provide a sane default if no
+custom description is defined. The accessor will either return or generate the
+description, depending on whether the field is null or not.
+
+First, in your "Camera" schema class, define the description field as follows:
+
+  __PACKAGE__->add_columns(description => { accessor => '_description' });
+
+Next, we'll define the accessor-wrapper subroutine:
+
+  sub description {
+      my $self = shift;
+
+      # If there is an update to the column, we'll let the original accessor
+      # deal with it.
+      return $self->_description(@_) if @_;
+
+      # Fetch the column value.
+      my $description = $self->_description;
+
+      # If there's something in the description field, then just return that.
+      return $description if defined $description && length $descripton;
+
+      # Otherwise, generate a description.
+      return $self->generate_description;
+  }
+
 =cut

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Manual/FAQ.pod
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Manual/FAQ.pod	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Manual/FAQ.pod	2007-05-01 05:41:32 UTC (rev 3221)
@@ -255,6 +255,36 @@
 L<DBIx::Class::ResultSetColumn>, see it's documentation and the
 L<Cookbook|DBIx::Class::Manual::Cookbook> for details.
 
+=item .. fetch a formatted column?
+
+In your table schema class, create a "private" column accessor with:
+
+  __PACKAGE__->add_columns(my_common => { accessor => '_hidden_my_column' });
+
+Then, in the same class, implement a subroutine called "my_column" that
+fetches the real value and does the formatting you want.
+
+See the Cookbook for more details.
+
+=item .. fetch a single (or topmost) row?
+
+Sometimes you many only want a single record back from a search. A quick
+way to get that single row is to first run your search as usual:
+
+  ->search->(undef, { order_by => "id DESC" })
+
+Then call L<DBIx::Class::ResultSet/slice> and ask it only to return 1 row:
+
+  ->slice(0,1)
+
+These two calls can be combined into a single statement:
+
+  ->search->(undef, { order_by => "id DESC" })->slice(0,1)
+
+Why slice instead of L<DBIx::Class::ResultSet/first> or L<DBIx::Class::ResultSet/single>?
+If supported by the database, slice will use LIMIT/OFFSET to hint to the database that we
+really only need one row. This can result in a significant speed improvement.
+
 =back
 
 =head2 Inserting and updating data
@@ -296,6 +326,35 @@
 
  ->update({ somecolumn => \'othercolumn' })
 
+=item .. store JSON/YAML in a column and have it deflate/inflate automatically?
+
+You can use L<DBIx::Class::InflateColumn> to accomplish YAML/JSON storage transparently.
+
+If you want to use JSON, then in your table schema class, do the following:
+
+ use JSON;
+
+ __PACKAGE__->add_columns(qw/ ... my_column ../)
+ __PACKAGE__->inflate_column('my_column', {
+     inflate => sub { jsonToObj(shift) },
+     deflate => sub { objToJson(shift) },
+ });
+
+For YAML, in your table schema class, do the following:
+
+ use YAML;
+
+ __PACKAGE__->add_columns(qw/ ... my_column ../)
+ __PACKAGE__->inflate_column('my_column', {
+     inflate => sub { YAML::Load(shift) },
+     deflate => sub { YAML::Dump(shift) },
+ });
+
+This technique is an easy way to store supplemental unstructured data in a table. Be
+careful not to overuse this capability, however. If you find yourself depending more
+and more on some data within the inflated column, then it may be time to factor that
+data out.
+
 =back
 
 =head2 Misc

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Manual/Intro.pod
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Manual/Intro.pod	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Manual/Intro.pod	2007-05-01 05:41:32 UTC (rev 3221)
@@ -356,7 +356,7 @@
   my $rs = $schema->resultset('Album')->search({
     artist  => { '!=', 'Janis Joplin' },
     year    => { '<' => 1980 },
-    albumid => [ 1, 14, 15, 65, 43 ]
+    albumid => { '-in' => [ 1, 14, 15, 65, 43 ] }
   });
 
 This results in something like the following C<WHERE> clause:

Added: branches/DBIx-Class-current/lib/DBIx/Class/Manual/Joining.pod
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Manual/Joining.pod	                        (rev 0)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Manual/Joining.pod	2007-05-01 05:41:32 UTC (rev 3221)
@@ -0,0 +1,171 @@
+=head1 NAME 
+
+DBIx::Class::Manual::Joining - Manual on joining tables with DBIx::Class
+
+=head1 DESCRIPTION
+
+This document should help you to use L<DBIx::Class> if you are trying
+to convert your normal SQL queries into DBIx::Class based queries, if
+you use joins extensively (and also probably if you don't).
+
+=head1 WHAT ARE JOINS
+
+If you ended up here and you don't actually know what joins are yet,
+then you should likely try the L<DBIx::Class::Manual::Intro>
+instead. Skip this part if you know what joins are..
+
+But I'll explain anyway. Assuming you have created your database in a
+more or less sensible way, you will end up with several tables that
+contain C<related> information. For example, you may have a table
+containing information about C<CDs>, containing the CD title and it's
+year of publication, and another table containing all the C<Track>s
+for the CDs, one track per row.
+
+When you wish to extract information about a particular CD and all
+it's tracks, You can either fetch the CD row, then make another query
+to fetch the tracks, or you can use a join. Compare:
+
+  SELECT ID, Title, Year FROM CD WHERE Title = 'Funky CD';
+  # .. Extract the ID, which is 10
+  SELECT Name, Artist FROM Tracks WHERE CDID = 10;
+
+  SELECT cd.ID, cd.Title, cd.Year, tracks.Name, tracks.Artist FROM CD JOIN Tracks ON CD.ID = tracks.CDID WHERE cd.Title = 'Funky CD';
+
+So, joins are a way of extending simple select statements to include
+fields from other, related, tables. There are various types of joins,
+depending on which combination of the data you wish to retrieve, see
+L<MySQL's doc on JOINs|http://dev.mysql.com/doc/refman/5.0/en/join.html>.
+
+=head1 DEFINING JOINS AND RELATIONSHIPS
+
+In L<DBIx::Class> each relationship between two tables needs to first
+be defined in the L<ResultSource|DBIx::Class::Manual::Glossary/ResultSource> for the
+table. If the relationship needs to be accessed in both directions
+(i.e. Fetch all tracks of a CD, and fetch the CD data for a Track),
+then it needs to be defined in both tables.
+
+For the CDs/Tracks example, that means writing, in C<MySchema::CD>:
+
+  MySchema::CD->has_many('tracks', 'MySchema::Tracks');
+
+And in C<MySchema::Tracks>:
+
+  MySchema::Tracks->belongs_to('cd', 'MySchema::CD', 'CDID');
+
+There are several other types of relationships, they are more
+comprehensively described in L<DBIx::Class::Relationship>.
+
+=head1 USING JOINS
+
+Once you have defined all your relationships, using them in actual
+joins is fairly simple. The type of relationship that you chose
+e.g. C<has_many>, already indicates what sort of join will be
+performed. C<has_many> produces a C<LEFT JOIN> for example, which will
+fetch all the rows on the left side, whether there are matching rows
+on the right (table being joined to), or not. You can force other
+types of joins in your relationship, see the
+L<DBIx::Class::Relationship> docs.
+
+When performing either a L<search|DBIx::Class::ResultSet/search> or a
+L<find|DBIx::Class::ResultSet/find> operation, you can specify which
+C<relations> to also fetch data from (or sort by), using the
+L<join|DBIx::Class::ResultSet/join> attribute, like this:
+
+  $schema->resultset('CD')->search(
+    { 'Title' => 'Funky CD' },
+    { join      => 'tracks',
+      '+select' => [ 'tracks.Name', 'tracks.Artist' ],
+      '+as'     => [ 'TrackName', 'ArtistName' ]
+    }
+  );
+
+If you don't recognise most of this syntax, you should probably go
+read L<DBIx::Class::ResultSet/search> and
+L<DBIx::Class::ResultSet/ATTRIBUTES>, but here's a quick break down:
+
+The first argument to search is a hashref of the WHERE attributes, in
+this case a simple restriction on the Title column. The second
+argument is a hashref of attributes to the search, '+select' adds
+extra columns to the select (from the joined table(s) or from
+calculations), and '+as' gives aliases to those fields.
+
+'join' specifies which C<relationships> to include in the query. The
+distinction between C<relationships> and C<tables> is important here,
+only the C<relationship> names are valid.
+
+This example should magically produce SQL like the second select in
+L</WHAT ARE JOINS> above.
+
+=head1 COMPLEX JOINS AND STUFF
+
+=head2 Across multiple relations
+
+For simplicity in the example above, the C<Artist> was shown as a
+simple text firld in the C<Tracks> table, in reality, you'll want to
+have the artists in their own table as well, thus to fetch the
+complete set of data we'll need to join to the Artist table too.
+
+In C<MySchema::Tracks>:
+
+  MySchema::Tracks->belongs_to('artist', 'MySchema::Artist', 'ArtistID');
+
+The search:
+
+  $schema->resultset('CD')->search(
+    { 'Title' => 'Funky CD' },
+    { join      => { 'tracks' => 'artist' },
+      '+select' => [ 'tracks.Name', 'artist.Artist' ],
+      '+as'     => [ 'TrackName', 'ArtistName' ]
+    }
+  );
+
+Which is:
+
+  SELECT me.ID, me.Title, me.Year, tracks.Name, artist.Artist FROM CD me JOIN Tracks tracks ON CD.ID = tracks.CDID JOIN Artists artist ON tracks.ArtistID = artist.ID WHERE me.Title = 'Funky CD';
+
+To perform joins using relations of the tables you are joining to, use
+a hashref to indicate the join depth. This can theoretically go as
+deep as you like (warning, contrived examples!): 
+
+  join => { room => { table => 'leg' } }
+
+To join two relations at the same level, use an arrayref instead:
+
+  join => { room => [ 'chair', 'table' ] } 
+
+Or combine the two:
+
+  join => { room => [ 'chair', { table => 'leg' } ]
+
+=head2 Table aliases
+
+As an aside to all the discussion on joins, note that L<DBIx::Class>
+uses the C<relation names> as table aliases. This is important when
+you need to add grouping or ordering to your queries:
+
+  $schema->resultset('CD')->search(
+    { 'Title' => 'Funky CD' },
+    { join      => { 'tracks' => 'artist' },
+      order_by  => [ 'tracks.Name', 'artist.Artist' ],
+      '+select' => [ 'tracks.Name', 'artist.Artist' ],
+      '+as'     => [ 'TrackName', 'ArtistName' ]
+    }
+  );
+
+  SELECT me.ID, me.Title, me.Year, tracks.Name, artist.Artist FROM CD me JOIN Tracks tracks ON CD.ID = tracks.CDID JOIN Artists artist ON tracks.ArtistID = artist.ID WHERE me.Title = 'Funky CD' ORDER BY tracks.Name, artist.Artist;
+
+This is essential if any of your tables have columns with the same names.
+
+Note that the table of the resultsource the search was performed on, is always aliased to C<me>.
+
+=head2 Joining to the same table twice
+
+There is no magic to this, just do it. The table aliases will
+automatically be numbered:
+
+  join => [ 'room', 'room' ]
+
+The aliases are: C<room_1> and C<room_2>.
+
+=cut
+

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Manual/Troubleshooting.pod
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Manual/Troubleshooting.pod	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Manual/Troubleshooting.pod	2007-05-01 05:41:32 UTC (rev 3221)
@@ -47,5 +47,13 @@
 
 L<DBI> version 1.50 and L<DBD::Pg> 1.43 are known to work.
 
+=head2 ... Can't locate object method "source_name" via package ...
+
+There's likely a syntax error in the table class referred to elsewhere
+in this error message.  In particular make sure that the package
+declaration is correct, so for a schema C< MySchema > you need to
+specify a fully qualified namespace: C< package MySchema::MyTable; >
+for example.
+
 =cut
 

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Manual.pod
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Manual.pod	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Manual.pod	2007-05-01 05:41:32 UTC (rev 3221)
@@ -11,6 +11,10 @@
 
 =head1 SECTIONS
 
+=head2 L<DBIx::Class::Manual::FAQ>
+
+Short answers and doc pointers to questions.
+
 =head2 L<DBIx::Class::Manual::Intro>
 
 Beginner guide to using DBIx::Class. 
@@ -19,6 +23,10 @@
 
 An example of slightly more complex usage.
 
+=head2 L<DBIx::Class::Manual::Joining>
+
+How to translate known SQL JOINs into DBIx-Class-ish.
+
 =head2 L<DBIx::Class::Manual::Cookbook>
 
 Convenient recipes for DBIC usage.

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Ordered.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Ordered.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Ordered.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -38,7 +38,7 @@
     other_group_id INTEGER NOT NULL
   );
 
-In your Schema or DB class add Ordered to the top 
+In your Schema or DB class add "Ordered" to the top 
 of the component list.
 
   __PACKAGE__->load_components(qw( Ordered ... ));
@@ -57,7 +57,7 @@
 
   __PACKAGE__->grouping_column(['group_id', 'other_group_id']);
 
-Thats it, now you can change the position of your objects.
+That's it, now you can change the position of your objects.
 
   #!/use/bin/perl
   use My::Item;
@@ -103,7 +103,7 @@
   __PACKAGE__->position_column('position');
 
 Sets and retrieves the name of the column that stores the 
-positional value of each record.  Default to "position".
+positional value of each record.  Defaults to "position".
 
 =cut
 
@@ -113,7 +113,7 @@
 
   __PACKAGE__->grouping_column('group_id');
 
-This method specified a column to limit all queries in 
+This method specifies a column to limit all queries in 
 this module by.  This effectively allows you to have multiple 
 ordered lists within the same table.
 
@@ -126,7 +126,7 @@
   my $rs = $item->siblings();
   my @siblings = $item->siblings();
 
-Returns either a result set or an array of all other objects 
+Returns either a resultset or an array of all other objects 
 excluding the one you called it on.
 
 =cut
@@ -150,7 +150,7 @@
   my $sibling = $item->first_sibling();
 
 Returns the first sibling object, or 0 if the first sibling 
-is this sibliing.
+is this sibling.
 
 =cut
 
@@ -170,7 +170,7 @@
 
   my $sibling = $item->last_sibling();
 
-Return the last sibling, or 0 if the last sibling is this 
+Returns the last sibling, or 0 if the last sibling is this 
 sibling.
 
 =cut
@@ -191,8 +191,8 @@
 
   my $sibling = $item->previous_sibling();
 
-Returns the sibling that resides one position back.  Undef 
-is returned if the current object is the first one.
+Returns the sibling that resides one position back.  Returns undef 
+if the current object is the first one.
 
 =cut
 
@@ -213,8 +213,8 @@
 
   my $sibling = $item->next_sibling();
 
-Returns the sibling that resides one position foward.  Undef 
-is returned if the current object is the last one.
+Returns the sibling that resides one position forward. Returns undef 
+if the current object is the last one.
 
 =cut
 
@@ -236,9 +236,9 @@
 
   $item->move_previous();
 
-Swaps position with the sibling on position previous in the list.  
-1 is returned on success, and 0 is returned if the objects is already 
-the first one.
+Swaps position with the sibling in the position previous in
+the list.  Returns 1 on success, and 0 if the object is
+already the first one.
 
 =cut
 
@@ -252,8 +252,9 @@
 
   $item->move_next();
 
-Swaps position with the sibling in the next position.  1 is returned on 
-success, and 0 is returned if the object is already the last in the list.
+Swaps position with the sibling in the next position in the
+list.  Returns 1 on success, and 0 if the object is already
+the last in the list.
 
 =cut
 
@@ -269,8 +270,8 @@
 
   $item->move_first();
 
-Moves the object to the first position.  1 is returned on 
-success, and 0 is returned if the object is already the first.
+Moves the object to the first position in the list.  Returns 1
+on success, and 0 if the object is already the first.
 
 =cut
 
@@ -283,8 +284,8 @@
 
   $item->move_last();
 
-Moves the object to the very last position.  1 is returned on 
-success, and 0 is returned if the object is already the last one.
+Moves the object to the last position in the list.  Returns 1
+on success, and 0 if the object is already the last one.
 
 =cut
 
@@ -298,9 +299,9 @@
 
   $item->move_to( $position );
 
-Moves the object to the specified position.  1 is returned on 
-success, and 0 is returned if the object is already at the 
-specified position.
+Moves the object to the specified position.  Returns 1 on
+success, and 0 if the object is already at the specified
+position.
 
 =cut
 
@@ -539,7 +540,7 @@
 
 If a position is not specified for an insert than a position 
 will be chosen based on COUNT(*)+1.  But, it first selects the 
-count then inserts the record.  The space of time between select 
+count, and then inserts the record.  The space of time between select 
 and insert introduces a race condition.  To fix this we need the 
 ability to lock tables in DBIC.  I've added an entry in the TODO 
 about this.

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Relationship.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Relationship.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Relationship.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -308,6 +308,11 @@
 
   My::DBIC::Schema::Role->many_to_many( actors => 'actor_roles', 'actor' );
 
+To add a role for your actor, and fill in the year of the role in the
+actor_roles table:
+
+  $actor->add_to_roles($role, { year => 1995 });
+
 Many_to_many is not strictly a relationship in its own right. Instead, it is
 a bridge between two resultsets which provide the same kind of convenience
 accessors as true relationships provide. Although the accessor will return a 

Modified: branches/DBIx-Class-current/lib/DBIx/Class/ResultSet.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/ResultSet.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/ResultSet.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -135,7 +135,10 @@
     columns => [qw/name artistid/],
   });
 
-For a list of attributes that can be passed to C<search>, see L</ATTRIBUTES>. For more examples of using this function, see L<Searching|DBIx::Class::Manual::Cookbook/Searching>.
+For a list of attributes that can be passed to C<search>, see
+L</ATTRIBUTES>. For more examples of using this function, see
+L<Searching|DBIx::Class::Manual::Cookbook/Searching>. For a complete
+documentation for the first argument, see L<SQL::Abstract>.
 
 =cut
 
@@ -1813,7 +1816,9 @@
   });
 
 would return all CDs and include a 'name' column to the information
-passed to object inflation
+passed to object inflation. Note that the 'artist' is the name of the
+column (or relationship) accessor, and 'name' is the name of the column
+accessor in the related table.
 
 =head2 select
 
@@ -1864,8 +1869,14 @@
 
 =back
 
-Indicates column names for object inflation. This is used in conjunction with
-C<select>, usually when C<select> contains one or more function or stored
+Indicates column names for object inflation. That is, c< as >
+indicates the name that the column can be accessed as via the
+C<get_column> method (or via the object accessor, B<if one already
+exists>).  It has nothing to do with the SQL code C< SELECT foo AS bar
+>.
+
+The C< as > attribute is used in conjunction with C<select>,
+usually when C<select> contains one or more function or stored
 procedure names:
 
   $rs = $schema->resultset('Employee')->search(undef, {

Modified: branches/DBIx-Class-current/lib/DBIx/Class/ResultSource.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/ResultSource.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/ResultSource.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -957,7 +957,9 @@
 
   $source->resultset_attributes({ order_by => [ 'id' ] });
 
-Specify here any attributes you wish to pass to your specialised resultset.
+Specify here any attributes you wish to pass to your specialised
+resultset. For a full list of these, please see
+L<DBIx::Class::ResultSet/ATTRIBUTES>.
 
 =cut
 

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Row.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Row.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Row.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -121,12 +121,16 @@
 
 =head2 update
 
-  $obj->update;
+  $obj->update \%columns?;
 
 Must be run on an object that is already in the database; issues an SQL
 UPDATE query to commit any changes to the object to the database if
 required.
 
+Also takes an options hashref of C<< column_name => value> pairs >> to update
+first. But be aware that this hashref might be edited in place, so dont rely on
+it being the same after a call to C<update>.
+
 =cut
 
 sub update {

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Schema.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Schema.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Schema.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -97,17 +97,13 @@
 
   %$source = %{ $source->new( { %$source, source_name => $moniker }) };
 
-  my %reg = %{$self->source_registrations};
-  $reg{$moniker} = $source;
-  $self->source_registrations(\%reg);
+  $self->source_registrations->{$moniker} = $source;
 
   $source->schema($self);
 
   weaken($source->{schema}) if ref($self);
   if ($source->result_class) {
-    my %map = %{$self->class_mappings};
-    $map{$source->result_class} = $moniker;
-    $self->class_mappings(\%map);
+    $self->class_mappings->{$source->result_class} = $moniker;
   }
 }
 
@@ -578,9 +574,6 @@
 
 sub compose_namespace {
   my ($self, $target, $base) = @_;
-  my %reg = %{ $self->source_registrations };
-  my %target;
-  my %map;
   my $schema = $self->clone;
   {
     no warnings qw/redefine/;
@@ -1007,7 +1000,7 @@
     my ($self, $type, $dir, $version, $pversion) = @_;
 
     my $filename = ref($self);
-    $filename =~ s/::/-/;
+    $filename =~ s/::/-/g;
     $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
     $filename =~ s/$version/$pversion-$version/ if($pversion);
 

Modified: branches/DBIx-Class-current/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class/Storage/DBI.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class/Storage/DBI.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -1131,18 +1131,12 @@
   }
 
   my %result;
-  my $sth = $dbh->prepare("SELECT * FROM $table WHERE 1=0");
+  my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
   $sth->execute;
   my @columns = @{$sth->{NAME_lc}};
   for my $i ( 0 .. $#columns ){
     my %column_info;
-    my $type_num = $sth->{TYPE}->[$i];
-    my $type_name;
-    if(defined $type_num && $dbh->can('type_info')) {
-      my $type_info = $dbh->type_info($type_num);
-      $type_name = $type_info->{TYPE_NAME} if $type_info;
-    }
-    $column_info{data_type} = $type_name ? $type_name : $type_num;
+    $column_info{data_type} = $sth->{TYPE}->[$i];
     $column_info{size} = $sth->{PRECISION}->[$i];
     $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
 
@@ -1153,7 +1147,19 @@
 
     $result{$columns[$i]} = \%column_info;
   }
+  $sth->finish;
 
+  foreach my $col (keys %result) {
+    my $colinfo = $result{$col};
+    my $type_num = $colinfo->{data_type};
+    my $type_name;
+    if(defined $type_num && $dbh->can('type_info')) {
+      my $type_info = $dbh->type_info($type_num);
+      $type_name = $type_info->{TYPE_NAME} if $type_info;
+      $colinfo->{data_type} = $type_name if $type_name;
+    }
+  }
+
   return \%result;
 }
 

Modified: branches/DBIx-Class-current/lib/DBIx/Class.pm
===================================================================
--- branches/DBIx-Class-current/lib/DBIx/Class.pm	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/lib/DBIx/Class.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -217,6 +217,8 @@
 
 jguenther: Justin Guenther <jguenther at cpan.org>
 
+jshirley: J. Shirley <jshirley at gmail.com>
+
 konobi: Scott McWhirter
 
 LTJake: Brian Cassidy <bricas at cpan.org>

Modified: branches/DBIx-Class-current/t/76joins.t
===================================================================
--- branches/DBIx-Class-current/t/76joins.t	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/t/76joins.t	2007-05-01 05:41:32 UTC (rev 3221)
@@ -105,7 +105,7 @@
     [ { father => 'person' }, { 'father.person_id' => { '!=', '42' } }, ],
     [ { mother => 'person' }, { 'mother.person_id' => 'child.mother_id' } ],
 );
-$match = qr/^\QHASH reference arguments are not supported in JOINS - try using \"..." instead\E/;
+$match = qr/^HASH reference arguments are not supported in JOINS - try using "\.\.\." instead/;
 eval { $sa->_recurse_from(@j6) };
 like( $@, $match, 'join 6 (HASH reference for ON statement dies) ok' );
 

Modified: branches/DBIx-Class-current/t/cdbi-t/09-has_many.t
===================================================================
--- branches/DBIx-Class-current/t/cdbi-t/09-has_many.t	2007-05-01 05:25:33 UTC (rev 3220)
+++ branches/DBIx-Class-current/t/cdbi-t/09-has_many.t	2007-05-01 05:41:32 UTC (rev 3221)
@@ -6,15 +6,15 @@
   eval "use DBIx::Class::CDBICompat;";
   plan skip_all => 'Class::Trigger and DBIx::ContextualFetch required' if $@;
   eval "use DBD::SQLite";
-  plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 30);
+  plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 31);
 }
 
 
 use lib 't/testlib';
 use Film;
 use Actor;
-Film->has_many(actors => Actor => 'Film', { order_by => 'name' });
 Actor->has_a(Film => 'Film');
+Film->has_many(actors => 'Actor', { order_by => 'name' });
 is(Actor->primary_column, 'id', "Actor primary OK");
 
 ok(Actor->can('Salary'), "Actor table set-up OK");
@@ -110,3 +110,18 @@
 
 is($as->Name, 'Arnold Schwarzenegger', "Arnie's still Arnie");
 
+
+# Test infering of the foreign key of a has_many from an existing has_a
+{
+    use Thing;
+    use OtherThing;
+
+    Thing->has_a(that_thing => "OtherThing");
+    OtherThing->has_many(things => "Thing");
+
+    my $other_thing = OtherThing->create({ id => 1 });
+    Thing->create({ id => 1, that_thing => $other_thing });
+    Thing->create({ id => 2, that_thing => $other_thing });
+
+    is_deeply [sort map { $_->id } $other_thing->things], [1,2];
+}

Added: branches/DBIx-Class-current/t/testlib/OtherThing.pm
===================================================================
--- branches/DBIx-Class-current/t/testlib/OtherThing.pm	                        (rev 0)
+++ branches/DBIx-Class-current/t/testlib/OtherThing.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -0,0 +1,11 @@
+package OtherThing;
+use base 'DBIx::Class::Test::SQLite';
+
+OtherThing->set_table("other_thing");
+OtherThing->columns(All => qw(id));
+
+sub create_sql {
+    return qq{
+        id              INTEGER
+    };
+}

Added: branches/DBIx-Class-current/t/testlib/Thing.pm
===================================================================
--- branches/DBIx-Class-current/t/testlib/Thing.pm	                        (rev 0)
+++ branches/DBIx-Class-current/t/testlib/Thing.pm	2007-05-01 05:41:32 UTC (rev 3221)
@@ -0,0 +1,14 @@
+package Thing;
+use base 'DBIx::Class::Test::SQLite';
+
+Thing->set_table("thing");
+Thing->columns(All => qw(id that_thing));
+
+sub create_sql {
+    return qq{
+        id              INTEGER,
+        that_thing      INTEGER
+    };
+}
+
+1;




More information about the Bast-commits mailing list