[Jifty-commit] r2867 - in Jifty-DBI/branches/od: . lib/Jifty/DBI lib/Jifty/DBI/Handle t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Wed Feb 28 14:36:41 EST 2007


Author: jesse
Date: Wed Feb 28 14:36:39 2007
New Revision: 2867

Added:
   Jifty-DBI/branches/od/lib/Jifty/DBI/Filter/YAML.pm
   Jifty-DBI/branches/od/t/06filter_storable.t   (contents, props changed)
   Jifty-DBI/branches/od/t/06filter_yaml.t   (contents, props changed)
Modified:
   Jifty-DBI/branches/od/   (props changed)
   Jifty-DBI/branches/od/Makefile.PL
   Jifty-DBI/branches/od/lib/Jifty/DBI/Collection.pm
   Jifty-DBI/branches/od/lib/Jifty/DBI/Column.pm
   Jifty-DBI/branches/od/lib/Jifty/DBI/Handle/Pg.pm
   Jifty-DBI/branches/od/lib/Jifty/DBI/Record.pm
   Jifty-DBI/branches/od/lib/Jifty/DBI/Schema.pm
   Jifty-DBI/branches/od/lib/Jifty/DBI/SchemaGenerator.pm
   Jifty-DBI/branches/od/t/01records.t
   Jifty-DBI/branches/od/t/06filter_datetime.t
   Jifty-DBI/branches/od/t/10schema.t
   Jifty-DBI/branches/od/t/testmodels.pl

Log:
 s47595 at pinglin (orig r2766):  falcone | 2007-02-08 14:16:33 -0500
  r16656 at ketch:  falcone | 2007-02-08 14:15:52 -0500
  * bytea columns also need to be flagged with DBD::Pg::PG_BYTEA when binding params
 
 r47597 at pinglin (orig r2768):  ewilhelm | 2007-02-08 22:46:02 -0500
 lib/Jifty/DBI/Collection.pm - pod spelling correction
 
 r48369 at pinglin (orig r2800):  sterling | 2007-02-18 10:06:20 -0500
 added Makefile.old to svn:ignore
 r48437 at pinglin (orig r2806):  sterling | 2007-02-20 09:46:48 -0500
 added a YAML filter
 r48438 at pinglin (orig r2807):  sterling | 2007-02-20 09:48:09 -0500
 added a test for the Storable filter
 r48439 at pinglin (orig r2808):  sterling | 2007-02-20 10:05:43 -0500
 removed imports in YAML filter to prevent namespace pollution issues
 r48490 at pinglin (orig r2822):  jesse | 2007-02-22 23:32:11 -0500
  r46167 at pinglin:  jesse | 2006-12-13 20:38:11 -0500
  * Better debugging when we fail an is_distinct check on a create. (this probably doesn't need to actually be a warning, but it's good practice to catch it BEFORE trying to do the insert)
 
 r48491 at pinglin (orig r2823):  jesse | 2007-02-22 23:32:36 -0500
  r48489 at pinglin:  jesse | 2007-02-22 23:31:47 -0500
   * Scalar::Defer is never used
 
 r48494 at pinglin (orig r2824):  sterling | 2007-02-23 09:59:08 -0500
 added a simple test for as_hash
 r48499 at pinglin (orig r2827):  sterling | 2007-02-23 15:25:57 -0500
  * Added better handling of schema versioning
  * Added _init_methods_for_columns to explicitly handle accessor/mutator
    creation for all columns attached to a record
  * Applications employing JDBI can specify schema_version() in a sub-class of
    record to add better handling of "since" and "till" in both schema and code
    generation
  * Modified columns() on records to only return active columns
  * Added all_columns() to retrieve all columns on a record, even inactive ones
  * Added the active() method to columns to test to see if a column is active for
    the current schema version
  * Added/updated tests for the above
 === Targets to commit (you may delete items from it) ===
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/Makefile.PL
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/lib/Jifty/DBI/Column.pm
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/lib/Jifty/DBI/Record.pm
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/lib/Jifty/DBI/Schema.pm
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/lib/Jifty/DBI/SchemaGenerator.pm
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/t/10schema.t
 M   /Users/andrew/Documents/code/perl/Jifty-DBI/t/testmodels.pl
 
 r48586 at pinglin (orig r2857):  trs | 2007-02-27 21:00:17 -0500
  r19819 at zot:  tom | 2007-02-27 20:59:52 -0500
  When using the Storable filter, we need to use blob/bytea not text
 
 r48589 at pinglin (orig r2859):  trs | 2007-02-27 22:07:09 -0500
  r19823 at zot:  tom | 2007-02-27 22:07:00 -0500
  Die on incorrect column type when using the Storable filter
 


Modified: Jifty-DBI/branches/od/Makefile.PL
==============================================================================
--- Jifty-DBI/branches/od/Makefile.PL	(original)
+++ Jifty-DBI/branches/od/Makefile.PL	Wed Feb 28 14:36:39 2007
@@ -19,12 +19,19 @@
 requires('Lingua::EN::Inflect');
 requires('Object::Declare' => 0.22);
 requires('UNIVERSAL::require');
+requires('version');
 build_requires('Test::More' => 0.52);
 build_requires('DBD::SQLite');
 no_index directory => 'ex';
-features( 'Memcached support' => [
-    -default => 1,
-    Cache::Memcached => '']
+features( 
+    'Memcached support' => [
+        -default => 1,
+        Cache::Memcached => ''
+    ],
+    'YAML filter' => [
+        -default => 1,
+        (can_cc() ? requires('YAML::Syck') : requires('YAML')),
+    ],
 );
 auto_install();
 &WriteAll;

Modified: Jifty-DBI/branches/od/lib/Jifty/DBI/Collection.pm
==============================================================================
--- Jifty-DBI/branches/od/lib/Jifty/DBI/Collection.pm	(original)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/Collection.pm	Wed Feb 28 14:36:39 2007
@@ -32,7 +32,7 @@
 =head1 DESCRIPTION
 
 This module provides an object-oriented mechanism for retrieving and
-updating data in a DBI-accesible database.
+updating data in a DBI-accessible database.
 
 In order to use this module, you should create a subclass of
 L<Jifty::DBI::Collection> and a subclass of L<Jifty::DBI::Record> for

Modified: Jifty-DBI/branches/od/lib/Jifty/DBI/Column.pm
==============================================================================
--- Jifty-DBI/branches/od/lib/Jifty/DBI/Column.pm	(original)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/Column.pm	Wed Feb 28 14:36:39 2007
@@ -6,6 +6,7 @@
 our $VERSION = '0.01';
 use base qw/Class::Accessor::Fast Jifty::DBI::HasFilters/;
 use UNIVERSAL::require;
+use version;
 
 __PACKAGE__->mk_accessors qw/
     name
@@ -79,4 +80,47 @@
 sub length { Carp::croak('$column->length is no longer supported; use $column->max_length instead') }
 sub until { Carp::croak('$column->until is no longer supported; use $column->till instead') }
 
+=head2 active
+
+Returns the a true value if the column method exists for the current application
+version. The current application version is determined by checking the L<Jifty::DBI::Record/schema_version> of the column's L</record_class>. This method returns a false value if the column is not yet been added or has been dropped.
+
+This method returns a false value under these circumstances:
+
+=over
+
+=item *
+
+Both the C<since> trait and C<schema_version> method are defined and C<schema_version> is less than the version set on C<since>.
+
+=item *
+
+Both the C<till> trait and C<schema_version> method are defined and C<schema_version> is greater than or equal to the version set on C<till>.
+
+=back
+
+Otherwise, this method returns true.
+
+=cut
+
+sub active {
+    my $self    = shift;
+
+    return 1 unless $self->record_class->can('schema_version');
+    return 1 unless defined $self->record_class->schema_version;
+
+    my $version = version->new($self->record_class->schema_version);
+
+    # The application hasn't yet started using this column
+    return 0 if defined $self->since
+            and $version < version->new($self->since);
+
+    # The application stopped using this column
+    return 0 if defined $self->till
+            and $version >= version->new($self->till);
+
+    # The application currently uses this column
+    return 1;
+}
+
 1;

Added: Jifty-DBI/branches/od/lib/Jifty/DBI/Filter/YAML.pm
==============================================================================
--- (empty file)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/Filter/YAML.pm	Wed Feb 28 14:36:39 2007
@@ -0,0 +1,97 @@
+use strict;
+use warnings;
+
+package Jifty::DBI::Filter::YAML;
+use base qw/ Jifty::DBI::Filter /;
+
+my ($Dump, $Load);
+
+eval "use YAML::Syck ()";
+if ($@) { 
+    use YAML (); 
+    $Dump = \&YAML::Dump;
+    $Load = \&YAML::Load;
+}
+
+else {
+    $Dump = \&YAML::Syck::Dump;
+    $Load = \&YAML::Syck::Load;
+}
+
+=head1 NAME
+
+Jifty::DBI::Filter::YAML - This filter stores arbitrary Perl via YAML
+
+=head1 SYNOPSIS
+
+  use Jifty::DBI::Record schema {
+      column my_data =>
+          type is 'text',
+          filters are qw/ Jifty::DBI::Filter::YAML /;
+  };
+
+  my $thing = __PACKAGE__->new;
+  $thing->create( my_data => { foo => 'bar', baz => [ 1, 2, 3 ] } );
+
+  my $my_data = $thing->my_data;
+  while (my ($key, $value) = %$my_data) {
+      # do something...
+  }
+
+=head1 DESCRIPTION
+
+This filter provides the ability to store arbitrary data structures into a database column using L<YAML>. This is very similar to the L<Jifty::DBI::Filter::Storable> filter except that the L<YAML> format remains human-readable in the database. You can store virtually any Perl data, scalar, hash, array, or object into the database using this filter. 
+
+In addition, YAML (at least the storage of scalars, hashes, and arrays) is compatible with data structures written in other languages, so you may store or read data between applications written in different languages.
+
+=head1 METHODS
+
+=head2 encode
+
+This method is used to encode the Perl data structure into YAML formatted text.
+
+=cut
+
+sub encode {
+    my $self = shift;
+
+    my $value_ref = $self->value_ref;
+    return unless defined $$value_ref;
+
+    $$value_ref = $Dump->($$value_ref);
+}
+
+=head2 decode
+
+This method is used to decode the YAML formatted text from the database into the Perl data structure.
+
+=cut
+
+sub decode {
+    my $self = shift;
+
+    my $value_ref = $self->value_ref;
+    return unless defined $$value_ref;
+
+    $$value_ref = $Load->($$value_ref);
+}
+
+=head1 IMPLEMENTATION
+
+This class will attempt to use L<YAML::Syck> if it is available and then fall back upon L<YAML>. This has been done because the Syck library is written in C and is considerably faster.
+
+=head1 SEE ALSO
+
+L<Jifty::DBI::Filter>, L<YAML>, L<YAML::Syck>
+
+=head1 AUTHOR
+
+Andrew Sterling Hanenkamp E<lt>hanenkamp at cpan.orgE<gt>
+
+=head1 LICENSE
+
+This program is free software and may be modified or distributed under the same terms as Perl itself.
+
+=cut
+
+1

Modified: Jifty-DBI/branches/od/lib/Jifty/DBI/Handle/Pg.pm
==============================================================================
--- Jifty-DBI/branches/od/lib/Jifty/DBI/Handle/Pg.pm	(original)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/Handle/Pg.pm	Wed Feb 28 14:36:39 2007
@@ -125,7 +125,7 @@
     my $type = shift;
 
     # Don't assign to key 'value' as it is defined later.
-    return ( { pg_type => DBD::Pg::PG_BYTEA() } ) if $type eq "blob";
+    return ( { pg_type => DBD::Pg::PG_BYTEA() } ) if $type =~ /^(?:blob|bytea)$/;
     return ( {} );
 }
 

Modified: Jifty-DBI/branches/od/lib/Jifty/DBI/Record.pm
==============================================================================
--- Jifty-DBI/branches/od/lib/Jifty/DBI/Record.pm	(original)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/Record.pm	Wed Feb 28 14:36:39 2007
@@ -190,8 +190,41 @@
 
         $self->_init_methods_for_column($column);
     }
+
 }
 
+=head2 _init_methods_for_columns
+
+This is an internal method responsible for calling L</_init_methods_for_column> for each column that has been configured.
+
+=cut
+
+sub _init_methods_for_columns {
+    my $self = shift;
+
+    for my $column (sort keys %{ $self->COLUMNS || {} }) {
+        $self->_init_methods_for_column($self->COLUMNS->{ $column });
+    }
+}
+
+=head2 schema_version
+
+If present, this method must return a string in '1.2.3' format to be used to determine which columns are currently active in the schema. That is, this value is used to determine which columns are defined, based upon comparison to values set in C<till> and C<since>.
+
+If no implementation is present, the "latest" schema version is assumed, meaning that any column defining a C<till> is not active and all others are.
+
+=head2 _init_methods_for_column COLUMN
+
+This method is used internally to update the symbol table for the record class to include an accessor and mutator for each column based upon the column's name.
+
+In addition, if your record class defines the method L</schema_version>, it will automatically generate methods according to whether the column currently exists for the current application schema version returned by that method. The C<schema_version> method must return a value in the same form used by C<since> and C<till>.
+
+If the column doesn't currently exist, it will create the methods, but they will die with an error message stating that the column does not exist for the current version of the application. If it does exist, a normal accessor and mutator will be created.
+
+See also L<Jifty::DBI::Column/active>, L<Jifty::DBI::Schema/since>, L<Jifty::DBI::Schema/till> for more information.
+
+=cut
+
 sub _init_methods_for_column {
     my $self   = $_[0];
     my $column = $_[1];
@@ -203,30 +236,49 @@
     # through add_column
     $column->record_class( $package ) if not $column->record_class;
 
+    # Check for the correct column type when the Storable filter is in use
+    if ( grep { $_ eq 'Jifty::DBI::Filter::Storable' }
+              ($column->input_filters, $column->output_filters)
+         and $column->type !~ /^(blob|bytea)$/i)
+    {
+        die "Column '$column_name' in @{[$column->record_class]} ".
+            "uses the Storable filter but is not of type 'blob'.\n";
+    }
+
     no strict 'refs';    # We're going to be defining subs
 
     if ( not $self->can($column_name) ) {
         # Accessor
         my $subref;
-        if ( $column->readable ) {
-            if ( UNIVERSAL::isa( $column->refers_to, "Jifty::DBI::Record" ) )
-            {
-                $subref = sub {
-                    $_[0]->_to_record( $column_name,
-                        $_[0]->__value($column_name) );
-                };
-            } elsif (
-                UNIVERSAL::isa(
-                    $column->refers_to, "Jifty::DBI::Collection"
-                )
-                )
-            {
-                $subref = sub { $_[0]->_collection_value($column_name) };
+        if ( $column->active ) {
+            
+
+            if ( $column->readable ) {
+                if ( UNIVERSAL::isa( $column->refers_to, "Jifty::DBI::Record" ) )
+                {
+                    $subref = sub {
+                        $_[0]->_to_record( $column_name,
+                            $_[0]->__value($column_name) );
+                    };
+                } elsif (
+                    UNIVERSAL::isa(
+                        $column->refers_to, "Jifty::DBI::Collection"
+                    )
+                    )
+                {
+                    $subref = sub { $_[0]->_collection_value($column_name) };
+                } else {
+                    $subref = sub { return ( $_[0]->_value($column_name) ) };
+                }
             } else {
-                $subref = sub { return ( $_[0]->_value($column_name) ) };
+                $subref = sub { return '' }
             }
-        } else {
-            $subref = sub { return '' }
+        }
+        else {
+            # XXX sterling: should this be done with Class::ReturnValue instead
+            $subref = sub {
+                Carp::croak("column $column_name is not available for $package for schema version ".$self->schema_version);
+            };
         }
         *{ $package . "::" . $column_name } = $subref;
 
@@ -235,27 +287,45 @@
     if ( not $self->can( "set_" . $column_name ) ) {
         # Mutator
         my $subref;
-        if ( $column->writable ) {
-            if ( UNIVERSAL::isa( $column->refers_to, "Jifty::DBI::Record" ) )
-            {
-                $subref = sub {
-                    my $self = shift;
-                    my $val  = shift;
-
-                    $val = $val->id
-                        if UNIVERSAL::isa( $val, 'Jifty::DBI::Record' );
-                    return (
-                        $self->_set( column => $column_name, value => $val )
+        if ( $column->active ) {
+            if ( $column->writable ) {
+                if ( UNIVERSAL::isa( $column->refers_to, "Jifty::DBI::Record" ) )
+                {
+                    $subref = sub {
+                        my $self = shift;
+                        my $val  = shift;
+
+                        $val = $val->id
+                            if UNIVERSAL::isa( $val, 'Jifty::DBI::Record' );
+                        return (
+                            $self->_set( column => $column_name, value => $val )
+                        );
+                    };
+                } elsif (
+                    UNIVERSAL::isa(
+                        $column->refers_to, "Jifty::DBI::Collection"
+                    )
+                    )
+                {    # XXX elw: collections land here, now what?
+                    my $ret     = Class::ReturnValue->new();
+                    my $message = "Collection column '$column_name' not writable";
+                    $ret->as_array( 0, $message );
+                    $ret->as_error(
+                        errno        => 3,
+                        do_backtrace => 0,
+                        message      => $message
                     );
-                };
-            } elsif (
-                UNIVERSAL::isa(
-                    $column->refers_to, "Jifty::DBI::Collection"
-                )
-                )
-            {    # XXX elw: collections land here, now what?
+                    $subref = sub { return ( $ret->return_value ); };
+                } else {
+                    $subref = sub {
+                        return (
+                            $_[0]->_set( column => $column_name, value => $_[1] )
+                        );
+                    };
+                }
+            } else {
                 my $ret     = Class::ReturnValue->new();
-                my $message = "Collection column '$column_name' not writable";
+                my $message = 'Immutable column';
                 $ret->as_array( 0, $message );
                 $ret->as_error(
                     errno        => 3,
@@ -263,23 +333,13 @@
                     message      => $message
                 );
                 $subref = sub { return ( $ret->return_value ); };
-            } else {
-                $subref = sub {
-                    return (
-                        $_[0]->_set( column => $column_name, value => $_[1] )
-                    );
-                };
             }
-        } else {
-            my $ret     = Class::ReturnValue->new();
-            my $message = 'Immutable column';
-            $ret->as_array( 0, $message );
-            $ret->as_error(
-                errno        => 3,
-                do_backtrace => 0,
-                message      => $message
-            );
-            $subref = sub { return ( $ret->return_value ); };
+        }
+        else {
+            # XXX sterling: should this be done with Class::ReturnValue instead
+            $subref = sub {
+                Carp::croak("column $column_name is not available for $package for schema version ".$self->schema_version);
+            };
         }
         *{ $package . "::" . "set_" . $column_name } = $subref;
     }
@@ -406,11 +466,29 @@
                 <=> ( ( $a->type || '' ) eq 'serial' ) )
                 or ( ($a->sort_order || 0) <=> ($b->sort_order || 0))
                 or ( $a->name cmp $b->name )
-            } values %{ $self->_columns_hashref }
+            } grep { $_->active } values %{ $self->_columns_hashref }
+	])}
+}
 
+=head2 all_columns
 
-	])}
+  my @all_columns = $record->all_columns;
+
+Returns all the columns for the table, even those that are inactive.
+
+=cut
+
+sub all_columns {
+    my $self = shift;
 
+    # Not cached because it's not expected to be used often
+    return
+        sort {
+            ( ( ( $b->type || '' ) eq 'serial' )
+                <=> ( ( $a->type || '' ) eq 'serial' ) )
+                or ( ($a->sort_order || 0) <=> ($b->sort_order || 0))
+                or ( $a->name cmp $b->name )
+            } values %{ $self->_columns_hashref || {} }
 }
 
 sub _columns_hashref {
@@ -595,8 +673,8 @@
 sub as_hash {
     my $self = shift;
     my %values;
-     map {$values{$_} = $self->$_()} $self->readable_attributes  ;
-     return %values;
+    $values{$_} = $self->$_() for $self->readable_attributes;
+    return %values;
 }
 
 
@@ -1015,7 +1093,10 @@
         # Implement 'is distinct' checking
         if ( $column->distinct ) {
             my $ret = $self->is_distinct( $column_name, $attribs{$column_name} );
-            return ( $ret ) if not ( $ret );
+            if (not $ret ) {
+                Carp::cluck("$self failed a 'is_distinct' check for $column_name on ".$attribs{$column_name});
+            return ( $ret ) 
+            }
         }
 
         if ( $column->type =~ /^(text|longtext|clob|blob|lob|bytea)$/i ) {

Modified: Jifty-DBI/branches/od/lib/Jifty/DBI/Schema.pm
==============================================================================
--- Jifty-DBI/branches/od/lib/Jifty/DBI/Schema.pm	(original)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/Schema.pm	Wed Feb 28 14:36:39 2007
@@ -204,10 +204,7 @@
 	    _init_column($column);
 	}
 
-	# Then initialize all columns
-	foreach my $column ( sort keys %{ $from->_columns_hashref } ) {
-	    $from->_init_methods_for_column( $from->_columns_hashref->{$column} );
-	}
+        $from->_init_methods_for_columns;
     };
 
     return ('-base' => $new_code);
@@ -502,8 +499,10 @@
 
 =head2 till
 
-What application version this column was last supported.  Correct usage
-is C<till '0.2.5'>.
+The version after this column was supported. The column is not available in
+the version named, but would have been in the version immediately prior.
+
+Correct usage is C<till '0.2.5'>. This indicates that the column is not available in version C<0.2.5>, but was available in C<0.2.4>. The value specified for L</since> must be less than this version.
 
 =cut
 

Modified: Jifty-DBI/branches/od/lib/Jifty/DBI/SchemaGenerator.pm
==============================================================================
--- Jifty-DBI/branches/od/lib/Jifty/DBI/SchemaGenerator.pm	(original)
+++ Jifty-DBI/branches/od/lib/Jifty/DBI/SchemaGenerator.pm	Wed Feb 28 14:36:39 2007
@@ -8,6 +8,7 @@
 use DBIx::DBSchema::Column;
 use DBIx::DBSchema::Table;
 use Class::ReturnValue;
+use version;
 
 our $VERSION = '0.01';
 
@@ -259,6 +260,24 @@
         next if $column->virtual;
         next if defined $column->alias_for_column;
 
+        # If schema_version is defined, make sure columns are for that version
+        if ($model->can('schema_version') and defined $model->schema_version) {
+
+            # Skip it if the app version is earlier than the column version
+            next if defined $column->since 
+                and $model->schema_version <  version->new($column->since);
+
+            # Skip it if the app version is the same as or later than the 
+            # column version
+            next if defined $column->till
+                and $model->schema_version >= version->new($column->till);
+
+        }
+
+        # Otherwise, assume the latest version and eliminate till columns
+        next if (!$model->can('schema_version') or !defined $model->schema_version)
+            and defined $column->till;
+
         push @cols,
             DBIx::DBSchema::Column->new(
             {   name     => $column->name,

Modified: Jifty-DBI/branches/od/t/01records.t
==============================================================================
--- Jifty-DBI/branches/od/t/01records.t	(original)
+++ Jifty-DBI/branches/od/t/01records.t	Wed Feb 28 14:36:39 2007
@@ -8,7 +8,7 @@
 BEGIN { require "t/utils.pl" }
 our (@available_drivers);
 
-use constant TESTS_PER_DRIVER => 70;
+use constant TESTS_PER_DRIVER => 71;
 
 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
 plan tests => $total;
@@ -48,6 +48,13 @@
         my $record2 = TestApp::Address->create( _handle => $handle, name => 'Enoch', phone => '123 456 7890');
         isa_ok($record2, 'TestApp::Address');
         ok($record2->id, "Created a record with a class method");
+        is_deeply({ $record2->as_hash }, {
+            id          => $record2->id,
+            employee_id => undef,
+            name        => 'Enoch',
+            address     => '',
+            phone       => '123 456 7890',
+        }, 'as_hash works');
 
         my $clone2 = TestApp::Address->load_by_cols( _handle => $handle, name => 'Enoch');
         isa_ok($clone2, 'TestApp::Address');

Modified: Jifty-DBI/branches/od/t/06filter_datetime.t
==============================================================================
--- Jifty-DBI/branches/od/t/06filter_datetime.t	(original)
+++ Jifty-DBI/branches/od/t/06filter_datetime.t	Wed Feb 28 14:36:39 2007
@@ -6,7 +6,7 @@
 BEGIN { require "t/utils.pl" }
 our (@available_drivers);
 
-use constant TESTS_PER_DRIVER => 16;
+use constant TESTS_PER_DRIVER => 18;
 
 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
 plan tests => $total;
@@ -53,6 +53,11 @@
         $rec->set_created;
         is($rec->created, undef, "Set undef value" );
 
+        # Create using default undef
+        my $rec2 = TestApp::User->new( handle => $handle );
+        isa_ok($rec2, 'Jifty::DBI::Record');
+        is($rec2->created, undef, 'Default of undef');
+
         # from string
         require POSIX;
         $rec->set_created( POSIX::strftime( "%Y-%m-%d %H:%M:%S", gmtime($now) ) );
@@ -111,18 +116,20 @@
 BEGIN {
     use Jifty::DBI::Schema;
 
+
     use Jifty::DBI::Record schema {
     column created =>
       type is 'datetime',
-      input_filters are qw/Jifty::DBI::Filter::DateTime/;
+      filters are qw/Jifty::DBI::Filter::DateTime/,
+      default is undef;
 
     column event_on =>
       type is 'date',
-      input_filters are qw/Jifty::DBI::Filter::Date/;
+      filters are qw/Jifty::DBI::Filter::Date/;
 
     column event_stops =>
       type is 'time',
-      input_filters are qw/Jifty::DBI::Filter::Time/;
+      filters are qw/Jifty::DBI::Filter::Time/;
     }
 }
 

Added: Jifty-DBI/branches/od/t/06filter_storable.t
==============================================================================
--- (empty file)
+++ Jifty-DBI/branches/od/t/06filter_storable.t	Wed Feb 28 14:36:39 2007
@@ -0,0 +1,106 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use Test::More;
+BEGIN { require "t/utils.pl" }
+our (@available_drivers);
+
+use constant TESTS_PER_DRIVER => 9;
+
+my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
+plan tests => $total;
+
+my $complex_data = {
+    foo => 'bar',
+    baz => [ 1,  2, 3 ],
+};
+
+foreach my $d (@available_drivers) {
+SKIP: {
+    unless (has_schema('TestApp::User', $d)) {
+        skip "No schema for '$d' driver", TESTS_PER_DRIVER;
+    }
+
+    unless (should_test($d)) {
+        skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
+    }
+
+    diag("start testing with '$d' handle") if $ENV{TEST_VERBOSE};
+
+    my $handle = get_handle($d);
+    connect_handle($handle);
+    isa_ok($handle->dbh, 'DBI::db');
+
+    {
+        my $ret = init_schema('TestApp::User', $handle);
+        isa_ok($ret, 'DBI::st', 'init schema');
+    }
+
+   my $rec = TestApp::User->new( handle => $handle );
+   isa_ok($rec, 'Jifty::DBI::Record');
+
+   my ($id) = $rec->create( my_data => $complex_data );
+   ok($id, 'created record');
+   ok($rec->load($id), 'loaded record');
+   is($rec->id, $id, 'record id matches');
+   is(ref $rec->my_data, 'HASH', 'my_data is a HASH');
+   is_deeply($rec->my_data, $complex_data, 'my_data matches initial data');
+
+   # undef/NULL
+   $rec->set_my_data;
+   is($rec->my_data, undef, 'set undef value');
+
+   cleanup_schema('TestApp', $handle);
+   disconnect_handle($handle);
+}
+}
+
+package TestApp::User;
+use base qw/ Jifty::DBI::Record /;
+
+1;
+
+sub schema_sqlite {
+
+<<EOF;
+CREATE table users (
+    id integer primary key,
+    my_data blob
+)
+EOF
+
+}
+
+sub schema_mysql {
+
+<<EOF;
+CREATE TEMPORARY table users (
+    id integer auto_increment primary key,
+    my_data blob
+)
+EOF
+
+}
+
+sub schema_pg {
+
+<<EOF;
+CREATE TEMPORARY table users (
+    id serial primary key,
+    my_data bytea
+)
+EOF
+
+}
+
+BEGIN {
+    use Jifty::DBI::Schema;
+
+    use Jifty::DBI::Record schema {
+    column my_data =>
+        type is 'blob',
+        filters are qw/ Jifty::DBI::Filter::Storable /;
+    }
+}
+

Added: Jifty-DBI/branches/od/t/06filter_yaml.t
==============================================================================
--- (empty file)
+++ Jifty-DBI/branches/od/t/06filter_yaml.t	Wed Feb 28 14:36:39 2007
@@ -0,0 +1,114 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use Test::More;
+BEGIN { require "t/utils.pl" }
+our (@available_drivers);
+
+use constant TESTS_PER_DRIVER => 9;
+
+eval "use YAML::Syck ()";
+if ($@) {
+    eval "use YAML ()";
+    if ($@) {
+        plan skip_all => "neither YAML::Syck nor YAML is installed";
+    }
+}
+
+my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
+plan tests => $total;
+
+my $complex_data = {
+    foo => 'bar',
+    baz => [ 1,  2, 3 ],
+};
+
+foreach my $d (@available_drivers) {
+SKIP: {
+    unless (has_schema('TestApp::User', $d)) {
+        skip "No schema for '$d' driver", TESTS_PER_DRIVER;
+    }
+
+    unless (should_test($d)) {
+        skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
+    }
+
+    diag("start testing with '$d' handle") if $ENV{TEST_VERBOSE};
+
+    my $handle = get_handle($d);
+    connect_handle($handle);
+    isa_ok($handle->dbh, 'DBI::db');
+
+    {
+        my $ret = init_schema('TestApp::User', $handle);
+        isa_ok($ret, 'DBI::st', 'init schema');
+    }
+
+   my $rec = TestApp::User->new( handle => $handle );
+   isa_ok($rec, 'Jifty::DBI::Record');
+
+   my ($id) = $rec->create( my_data => $complex_data );
+   ok($id, 'created record');
+   ok($rec->load($id), 'loaded record');
+   is($rec->id, $id, 'record id matches');
+   is(ref $rec->my_data, 'HASH', 'my_data is a HASH');
+   is_deeply($rec->my_data, $complex_data, 'my_data matches initial data');
+
+   # undef/NULL
+   $rec->set_my_data;
+   is($rec->my_data, undef, 'set undef value');
+
+   cleanup_schema('TestApp', $handle);
+   disconnect_handle($handle);
+}
+}
+
+package TestApp::User;
+use base qw/ Jifty::DBI::Record /;
+
+1;
+
+sub schema_sqlite {
+
+<<EOF;
+CREATE table users (
+    id integer primary key,
+    my_data text
+)
+EOF
+
+}
+
+sub schema_mysql {
+
+<<EOF;
+CREATE TEMPORARY table users (
+    id integer auto_increment primary key,
+    my_data text
+)
+EOF
+
+}
+
+sub schema_pg {
+
+<<EOF;
+CREATE TEMPORARY table users (
+    id serial primary key,
+    my_data text
+)
+EOF
+
+}
+
+BEGIN {
+    use Jifty::DBI::Schema;
+
+    use Jifty::DBI::Record schema {
+    column my_data =>
+        type is 'text',
+        filters are qw/ Jifty::DBI::Filter::YAML /;
+    }
+}
+

Modified: Jifty-DBI/branches/od/t/10schema.t
==============================================================================
--- Jifty-DBI/branches/od/t/10schema.t	(original)
+++ Jifty-DBI/branches/od/t/10schema.t	Wed Feb 28 14:36:39 2007
@@ -3,8 +3,9 @@
 use strict;
 use warnings;
 use Test::More;
+use version;
 
-use constant TESTS_PER_DRIVER => 18;
+use constant TESTS_PER_DRIVER => 48;
 our @available_drivers;
 
 BEGIN {
@@ -91,6 +92,40 @@
                        $manually_make_text, 
                        'create_table_sql_text is the statements in create_table_sql_statements');
 
+    my $version_024_min = version->new('0.2.4');
+    my $version_024_max = version->new('0.2.8');
+
+    for my $version (qw/ 0.2.0 0.2.4 0.2.6 0.2.8 0.2.9 /) {
+
+        Sample::Address->schema_version($version);
+
+        my $SG = Jifty::DBI::SchemaGenerator->new($handle, $version);
+        $SG->add_model('Sample::Address');
+
+        my $street_added
+            = version->new($version) >= $version_024_min
+           && version->new($version) <  $version_024_max;
+
+        ok(Sample::Address->COLUMNS->{id}->active, 'id active');
+        ok(Sample::Address->COLUMNS->{employee_id}->active, 'employee_id active');
+        ok(Sample::Address->COLUMNS->{name}->active, 'name active');
+        ok(Sample::Address->COLUMNS->{phone}->active, 'phone active');
+        if ($street_added) {
+            ok(Sample::Address->COLUMNS->{street}->active, 'street active');
+        }
+
+        else {
+            ok(!Sample::Address->COLUMNS->{street}->active, 'street not active');
+        }
+
+        my $address_version_schema = $street_added ? "${address_schema}_024"
+            :                                         $address_schema;
+
+        is_ignoring_space($SG->create_table_sql_text,
+                        Sample::Address->$address_version_schema,
+                        "got the right Address schema for $d version $version");
+    }
+
     cleanup_schema( 'TestApp', $handle );
     disconnect_handle( $handle );
 }

Modified: Jifty-DBI/branches/od/t/testmodels.pl
==============================================================================
--- Jifty-DBI/branches/od/t/testmodels.pl	(original)
+++ Jifty-DBI/branches/od/t/testmodels.pl	Wed Feb 28 14:36:39 2007
@@ -53,10 +53,23 @@
 column phone =>
   type is 'varchar';
 
+column street =>
+  type is 'varchar',
+  since '0.2.4',
+  till '0.2.8';
+
 };
 
 sub validate_name { 1 }
 
+my $schema_version = undef;
+sub schema_version {
+    my $class = shift;
+    my $new_schema_version = shift;
+    $schema_version = $new_schema_version if defined $new_schema_version;
+    return $schema_version;
+}
+
 sub schema_sqlite {
     return q{
     CREATE TABLE addresses (
@@ -68,6 +81,18 @@
     }
 }
 
+sub schema_sqlite_024 {
+    return q{
+    CREATE TABLE addresses (
+     id INTEGER PRIMARY KEY NOT NULL  ,
+     employee_id integer   ,
+     name varchar  DEFAULT 'Frank' ,
+     phone varchar ,
+     street varchar
+    ) ;
+    }
+}
+
 sub schema_pg {
     return q{
     CREATE TABLE addresses ( 
@@ -80,4 +105,17 @@
     };
 }
 
+sub schema_pg_024 {
+    return q{
+    CREATE TABLE addresses ( 
+      id serial NOT NULL , 
+      employee_id integer  ,
+      name varchar DEFAULT 'Frank' ,
+      phone varchar ,
+      street varchar ,
+      PRIMARY KEY (id)
+    ) ;
+    };
+}
+
 1;


More information about the Jifty-commit mailing list