Codebase list libjifty-dbi-perl / 91f3c0d
[svn-upgrade] Integrating new upstream version, libjifty-dbi-perl (0.60) Jonathan Yu 14 years ago
12 changed file(s) with 216 addition(s) and 102 deletion(s). Raw diff Collapse all Expand all
00 Revision history for Perl extension Jifty::DBI.
1
2 0.60 Mon Jan 4 13:02:17 EST 2010
3 - Features:
4 * Allow passing of extra parameters to canonicalizers
5 * Add an attribute which controls placeholder use for load_by_cols
6
7 - Fixes:
8 * Don't add LOWER() on <= or >= operators, only = and !=
9 * Better case sensitivity tests
10 * Expose quote_value() on Jifty::DBI::Handle
11 * When generating COUT, don't add a DISTINCT unless needed
12 * Fix t/12prefetch.t's assumptions on row ordering
113
214 0.59 Wed Nov 18 20:12:57 EST 2009
315 - Features:
4343 version: 0
4444 resources:
4545 license: http://dev.perl.org/licenses/
46 version: 0.59
46 version: 0.60
1414 Hash: SHA1
1515
1616 SHA1 f29ac6543498d1b0e81f387b7284a039f83e7d29 .gitignore
17 SHA1 81b8e2df34131211193bf3b935b5a036dc051ec4 Changes
17 SHA1 ebecbc802fdf30c483cb2c9cf0639600e1c4ef43 Changes
1818 SHA1 006b044e48cc925d04f620f317a907d459b2d128 MANIFEST
19 SHA1 2f7ef1c4bb35edf899145b1c291924200fcac09f META.yml
19 SHA1 d836113207f525431fc0b36592d96c0178e85d70 META.yml
2020 SHA1 48bd6ca8a37ec79b7cae91028d7e9489ad33a03b Makefile.PL
2121 SHA1 ae8407c841f230c353f683bd5c257815aed9b9f0 README
2222 SHA1 82d6ac3f6def48558d09f8b6e3b53ed4194d8c81 ROADMAP
4040 SHA1 12bf1867955480d47d5171a9e9c6a96fabe0b58f inc/Module/Install/Metadata.pm
4141 SHA1 f7ee667e878bd2faf22ee9358a7b5a2cc8e91ba4 inc/Module/Install/Win32.pm
4242 SHA1 8ed29d6cf217e0977469575d788599cbfb53a5ca inc/Module/Install/WriteAll.pm
43 SHA1 2d4ea93c0b624bc5939d882d9c7f0d897fdc63b1 lib/Jifty/DBI.pm
44 SHA1 09c42f022a1b2ca5dab645fe9fe6e50ea1fa82b4 lib/Jifty/DBI/Collection.pm
43 SHA1 889c457846ee2b8cfbe53b668170043342fcbc7b lib/Jifty/DBI.pm
44 SHA1 e406abd0327e7e14d62f46eb8f8684f5e9d86965 lib/Jifty/DBI/Collection.pm
4545 SHA1 639ef9c81f03fb084b312a5f9a6f6a3ff63b36b7 lib/Jifty/DBI/Collection/Union.pm
4646 SHA1 bcba77fd2bacf0475aea1de97f57365c8de92ca6 lib/Jifty/DBI/Collection/Unique.pm
47 SHA1 6d59ec1286f3ed887494753d01ed1f4760fd0a9b lib/Jifty/DBI/Column.pm
47 SHA1 47caeff7332bb22c9a38e19e15f15f4f11a1f229 lib/Jifty/DBI/Column.pm
4848 SHA1 c21a985a5b799e50f2624e0fa6daee0895313825 lib/Jifty/DBI/Filter.pm
4949 SHA1 e030c3ef5c723ba6dce2e3fc23afecf2a6dfe260 lib/Jifty/DBI/Filter/Boolean.pm
5050 SHA1 d0addaa43cfa8950cb33d42a364a3c3c56a2dd59 lib/Jifty/DBI/Filter/Date.pm
5858 SHA1 67ffe7188a1f529d7594f4fa3803bcbe15ba6485 lib/Jifty/DBI/Filter/YAML.pm
5959 SHA1 9a6fd17e677321904436fefec4d434e17a4685b1 lib/Jifty/DBI/Filter/base64.pm
6060 SHA1 deb33fa7b35f3542aac3e2d7fb4b5d3070dc3917 lib/Jifty/DBI/Filter/utf8.pm
61 SHA1 99a22e6954200e1bf3901cf963b88c2a830e460f lib/Jifty/DBI/Handle.pm
61 SHA1 3e42dd9a4a0106219d15ac32c377539aa50ea4c4 lib/Jifty/DBI/Handle.pm
6262 SHA1 bcc7c456e1c4d0dddd5564f03c8bb03a6c7e261f lib/Jifty/DBI/Handle/Informix.pm
6363 SHA1 338116a45f8eb6bfca5e76e8d3be78fb61fffe81 lib/Jifty/DBI/Handle/ODBC.pm
6464 SHA1 960fd0b63f3de11924c5d47a3c0c6d1db105ed5b lib/Jifty/DBI/Handle/Oracle.pm
65 SHA1 23eeff073884c8951e004be4308ca946a1d5e205 lib/Jifty/DBI/Handle/Pg.pm
66 SHA1 1e850abb12a1d970eae373f452219c123be350e6 lib/Jifty/DBI/Handle/SQLite.pm
65 SHA1 d1757e2c992ead86f70f0dfc9c659387dc9600cf lib/Jifty/DBI/Handle/Pg.pm
66 SHA1 2f4c08340712bd21679282ebd669ce7b99d6d646 lib/Jifty/DBI/Handle/SQLite.pm
6767 SHA1 bba2314c20fcc3ef71cc69090f1cd6bd515cd9b4 lib/Jifty/DBI/Handle/Sybase.pm
6868 SHA1 cf80896a175702a157770f64ae469430678c3357 lib/Jifty/DBI/Handle/mysql.pm
6969 SHA1 f2cc4fcce79c9a88a023d4e6bd96c2089eef1ced lib/Jifty/DBI/Handle/mysqlPP.pm
7070 SHA1 45d653e3a223599b50850010826bd835b80368d7 lib/Jifty/DBI/HasFilters.pm
71 SHA1 24de085d41bfa49b1a6588311e675cff0615c8f0 lib/Jifty/DBI/Record.pm
71 SHA1 78a2d14d076f088b66433ab3be2f45c8b0474c34 lib/Jifty/DBI/Record.pm
7272 SHA1 663978b31373520d1e2deec87e957d1dbfd1347c lib/Jifty/DBI/Record/Cachable.pm
7373 SHA1 1aac77960c508d3b2e5188e15825ad5b04391d76 lib/Jifty/DBI/Record/Memcached.pm
7474 SHA1 53834b3315a509ba33a8647681f472d3ae7b0557 lib/Jifty/DBI/Record/Plugin.pm
9999 SHA1 bb91f506a251d7b27d2fcd29c482a345318ef04f t/06filter_yaml.t
100100 SHA1 64c3722f5b34feafc87113257079721c174f3f96 t/10schema.t
101101 SHA1 0f4655f0a4e558ac31df7b7fdf17c9b110f934da t/11schema_records.t
102 SHA1 22a083137927a8635b02931e40f80c60220ec3a7 t/12prefetch.t
102 SHA1 164ebb7144e978617c81306f5017bdcbcf41b801 t/12prefetch.t
103103 SHA1 2389b47958bd6f92a561ca893d7bfab166ced127 t/13collection.t
104104 SHA1 41b7fbaf031d103a4f2066f177cc3bee84ab0458 t/14handle-pg.t
105105 SHA1 4f41229caa246bf6ebb369010deb0c1eb8809666 t/15types.t
108108 SHA1 cc7d6dd9889837143074729d30030ddabcfa6b9e t/18triggers.t
109109 SHA1 54b7727b49111162703581d13dd47dfe276fbe9a t/19reference.t
110110 SHA1 72a16ddfc2642564023448450f3475ae5abf6d86 t/20overload.t
111 SHA1 5b3f8373687f89ccf3faf2dfbda9663137a8c078 t/case_sensitivity.t
111 SHA1 5e1158a9340410d46ffad19f381982159dccc924 t/case_sensitivity.t
112112 SHA1 1dd9675b0a9a59fdcd300f5d92297f0ecf4f03e4 t/metadata.t
113113 SHA1 59c44900b1cb957d262f96363ceff21b46e0d598 t/pod-coverage.t
114114 SHA1 e9c6a5881fc60173fbc8d479c1afd2ce3b43bef1 t/pod.t
115115 SHA1 62742c946808f35bcc8b2777e975c1ce068a0a71 t/testmodels.pl
116116 SHA1 653c2f961d8b4f195e5391cd261f37815068e8d5 t/utils.pl
117117 -----BEGIN PGP SIGNATURE-----
118 Version: GnuPG v1.4.7 (Darwin)
118 Version: GnuPG v2.0.14 (GNU/Linux)
119119
120 iD8DBQFLBJv7sxfQtHhyRPoRAog4AKCIv7JYxk/gyfUsKD1I6AwLS1tSfwCfeY18
121 jZQ6G3H6abFEj8XNr5+p6TQ=
122 =ao3T
120 iEYEARECAAYFAktCLRQACgkQMflWJZZAbqAAOwCeOxm56OcXyvFYKXRdNUHxJNHF
121 VUEAoLquqWn/1ANIGQffysa0WwKfOStP
122 =AGva
123123 -----END PGP SIGNATURE-----
801801 }
802802
803803 # DISTINCT query only required for multi-table selects
804 if ( $self->_is_joined ) {
804 if ( $self->distinct_required or $self->prefetch_related ) {
805805 $query_string = $self->_handle->distinct_count( \$query_string );
806806 } else {
807807 $query_string = "SELECT count(main.id) FROM " . $query_string;
12641264
12651265 if ( $args{'quote_value'} && $args{'operator'} !~ /IS/i ) {
12661266 if ( $value_ref eq 'ARRAY' ) {
1267 map { $_ = $self->_quote_value($_) } @{ $args{'value'} };
1267 map { $_ = $self->_handle->quote_value($_) } @{ $args{'value'} };
12681268 } else {
1269 $args{'value'} = $self->_quote_value( $args{'value'} );
1269 $args{'value'} = $self->_handle->quote_value( $args{'value'} );
12701270 }
12711271 }
12721272 }
12731273
12741274 if ( $args{'escape'} ) {
1275 $args{'escape'} = 'ESCAPE ' . $self->_quote_value( $args{escape} );
1275 $args{'escape'} = 'ESCAPE ' . $self->_handle->quote_value( $args{escape} );
12761276 }
12771277
12781278 # If we're trying to get a leftjoin restriction, lets set
14811481 $self->{$type} = $value;
14821482 }
14831483
1484 # quote the search value
1484 # stub for back-compat
14851485 sub _quote_value {
14861486 my $self = shift;
1487 my ($value) = @_;
1488
1489 my $tmp = $self->_handle->dbh->quote($value);
1490
1491 # Accomodate DBI drivers that don't understand UTF8
1492 if ( $] >= 5.007 ) {
1493 require Encode;
1494 if ( Encode::is_utf8($tmp) ) {
1495 Encode::_utf8_on($tmp);
1496 }
1497 }
1498 return $tmp;
1499
1487 return $self->_handle->quote_value(@_);
15001488 }
15011489
15021490 =head2 order_by_cols DEPRECATED
4141 valid_values
4242 available_values
4343 autocompleted
44 no_placeholder
4445 /;
4546
4647 # compat: this should probably never exist and be deprecated
137138
138139 =over
139140
140 =item container
141
142 =item label hints render_as
143
144 =item display_length
145
146 =item valid_values
147
148 =item available_values
149
150 =item autocompleted
151
152 =item documentation
141 =item container
142
143 =item label hints render_as
144
145 =item display_length
146
147 =item valid_values
148
149 =item available_values
150
151 =item autocompleted
152
153 =item documentation
154
155 =item no_placeholder
156
157 Setting this to a true value causes L<Jifty::DBI::record/load_by_cols>
158 to not use a placeholder when loading the column. This can allow the
159 database to come up with better query plans in some cases.
153160
154161 =back
155162
172172 my $value = shift;
173173
174174 if ( $self->_case_insensitivity_valid( $column, $operator, $value ) ) {
175 if ( $operator =~ /(?:LIKE|=|IN)/i ) {
176 $column = "LOWER($column)";
177 if ( $operator =~ /^(IN|=)$/i and ref($value) eq 'ARRAY' ) {
178 $value = [ map {"LOWER($_)"} @$value ];
179 } else {
180 $value = "LOWER($value)";
181 }
175 $column = "LOWER($column)";
176 if ( $operator =~ /^(IN|=)$/i and ref($value) eq 'ARRAY' ) {
177 $value = [ map {"LOWER($_)"} @$value ];
178 } else {
179 $value = "LOWER($value)";
182180 }
183181 }
184182 return ( $column, $operator, $value );
9494 my $column = shift;
9595 my $operator = shift;
9696 my $value = shift;
97
98 return ($column, $operator, $value)
99 unless $self->_case_insensitivity_valid( $column, $operator, $value );
100
97101 return("$column COLLATE NOCASE", $operator, $value);
98102 }
99103
715715
716716 return $value ne ''
717717 && $value ne "''"
718 && ( $operator !~ /IS/ && $value !~ /^null$/i )
718 && ( $operator =~ /^(?:(?:NOT )?LIKE|!?=|IN)$/i )
719719
720720 # don't downcase integer values
721721 && $value !~ /^['"]?\d+['"]?$/;
736736 }
737737 }
738738 return ( $column, $operator, $value );
739 }
740
741 =head2 quote_value VALUE
742
743 Calls the database's L<DBD/quote> method and returns the result.
744 Additionally, turns on perl's utf8 flag if the returned content is
745 UTF8.
746
747 =cut
748
749 sub quote_value {
750 my $self = shift;
751 my ($value) = @_;
752 my $tmp = $self->dbh->quote($value);
753
754 # Accomodate DBI drivers that don't understand UTF8
755 if ( $] >= 5.007 ) {
756 require Encode;
757 if ( Encode::is_utf8($tmp) ) {
758 Encode::_utf8_on($tmp);
759 }
760 }
761 return $tmp;
739762 }
740763
741764 =head2 begin_transaction
11391139 }
11401140 }
11411141
1142 push @phrases, "$key $op $function";
1143 push @bind, $value;
1142 if ($column_obj and $column_obj->no_placeholder and $function eq "?") {
1143 push @phrases, "$key $op ".$self->_handle->quote_value($value);
1144 } else {
1145 push @phrases, "$key $op $function";
1146 push @bind, $value;
1147 }
1148
11441149 } elsif ( !defined $hash{$key} ) {
11451150 push @phrases, "$key IS NULL";
11461151 } else {
16991704 my %args = (
17001705 column => undef,
17011706 value => undef,
1707 extra => [],
17021708 @_
17031709 );
17041710
17051711 my ( $ret, $value_ref ) = $self->_run_callback(
1706 name => "canonicalize_" . $args{'column'},
1707 args => $args{'value'},
1712 name => "canonicalize_" . $args{'column'},
1713 args => $args{'value'},
1714 extra => $args{'extra'},
17081715 short_circuit => 0,
17091716 );
17101717 return unless defined $ret;
17521759 my $attr = $args{'value'};
17531760
17541761 my ( $ret, $results )
1755 = $self->_run_callback( name => "validate_" . $key, args => $attr, extra => $args{'extra'} );
1762 = $self->_run_callback(
1763 name => "validate_" . $key,
1764 args => $attr,
1765 extra => $args{'extra'},
1766 );
17561767
17571768 if ( defined $ret ) {
17581769 return ( 1, 'Validation ok' );
11 use warnings;
22 use strict;
33
4 $Jifty::DBI::VERSION = '0.59';
4 $Jifty::DBI::VERSION = '0.60';
55
66 =head1 NAME
77
66
77 BEGIN { require "t/utils.pl" }
88 our (@available_drivers);
9 use constant TESTS_PER_DRIVER => 58;
9 use constant TESTS_PER_DRIVER => 59;
1010
1111 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
1212
9494 column2 => 'employee'
9595 );
9696 $collection->prefetch( $phones_alias => 'phones' );
97 $collection->order_by( column => 'id' );
9798 is( $collection->count, 2 );
9899 is( scalar( $handle->sql_statement_log ),
99100 1, "count is one statement" );
100101
101102 $handle->clear_sql_statement_log;
102103 my $user = $collection->next;
104 is( $user->name, 'RUZ' );
103105 is( $user->id, 1, "got our user" );
104106 my $phones = $user->phones;
105107 is( $phones->first->id, 1 );
55 BEGIN { require "t/utils.pl" }
66 our (@available_drivers);
77
8 use constant TESTS_PER_DRIVER => 9;
8 use constant TESTS_PER_DRIVER => 139;
99
1010 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
1111 plan tests => $total;
1212
1313 use DateTime ();
1414
15 foreach my $d ( @available_drivers ) {
15 foreach my $d (@available_drivers) {
1616 SKIP: {
17 unless( has_schema( 'TestApp::User', $d ) ) {
18 skip "No schema for '$d' driver", TESTS_PER_DRIVER;
19 }
20 unless( should_test( $d ) ) {
21 skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
22 }
23 diag("start testing with '$d' handle") if $ENV{TEST_VERBOSE};
17 unless ( has_schema( 'TestApp::User', $d ) ) {
18 skip "No schema for '$d' driver", TESTS_PER_DRIVER;
19 }
20 unless ( should_test($d) ) {
21 skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
22 }
23 diag("start testing with '$d' handle") if $ENV{TEST_VERBOSE};
2424
25 my $handle = get_handle( $d );
26 connect_handle( $handle );
27 isa_ok($handle->dbh, 'DBI::db');
25 my $handle = get_handle($d);
26 connect_handle($handle);
27 isa_ok( $handle->dbh, 'DBI::db' );
2828
29 {my $ret = init_schema( 'TestApp::User', $handle );
30 isa_ok($ret,'DBI::st', "Inserted the schema. got a statement handle back" );}
31
32 my $rec = TestApp::User->new( handle => $handle );
33 isa_ok($rec, 'Jifty::DBI::Record');
34
35 my ($id) = $rec->create( name => 'Foobar', interests => 'Slacking' );
36 ok($id, "Successfuly created ticket");
37
38 $rec->load_by_cols( name => 'foobar');
39 TODO: {
40 local $TODO = "How do we force mysql to be case sensitive?" if ( $d eq 'mysql' || $d eq 'mysqlPP' );
41 is($rec->id, undef);
29 {
30 my $ret = init_schema( 'TestApp::User', $handle );
31 isa_ok( $ret, 'DBI::st',
32 "Inserted the schema. got a statement handle back" );
4233 }
4334
44 $rec->load_by_cols( name => { value => 'foobar', case_sensitive => 0, operator => '=' });
45 is($rec->id, $id);
35 my $rec = TestApp::User->new( handle => $handle );
36 isa_ok( $rec, 'Jifty::DBI::Record' );
4637
47 $rec->load_by_cols( name => 'Foobar');
48 is($rec->id, $id);
38 my ($id) = $rec->create( name => 'Foobar', interests => 'Slacking' );
39 ok( $id, "Successfuly created ticket" );
4940
50 $rec->load_by_cols( interests => 'slacking');
51 is($rec->id, $id);;
41 $rec->load_by_cols( name => 'foobar' );
42 TODO: {
43 local $TODO = "How do we force mysql to be case sensitive?"
44 if ( $d eq 'mysql' || $d eq 'mysqlPP' );
45 is( $rec->id, undef );
46 }
5247
53 $rec->load_by_cols( interests => 'Slacking');
54 is($rec->id, $id);;
48 $rec->load_by_cols( name =>
49 { value => 'foobar', case_sensitive => 0, operator => '=' } );
50 is( $rec->id, $id );
5551
56 cleanup_schema( 'TestApp', $handle );
57 disconnect_handle( $handle );
52 $rec->load_by_cols( name => 'Foobar' );
53 is( $rec->id, $id );
54
55 $rec->load_by_cols( interests => 'slacking' );
56 is( $rec->id, $id );
57
58 $rec->load_by_cols( interests => 'Slacking' );
59 is( $rec->id, $id );
60
61 # IN
62 # IS
63 # IS NOT
64
65 ### Numbers
66 threeway_same($handle, id => $_, 42) for qw/= != < > <= >=/;
67 threeway_same($handle, id => $_, 42) for ("LIKE", "NOT LIKE", "MATCHES", "STARTS_WITH", "ENDS_WITH");
68 threeway_same($handle, id => $_ => [ 42, 17 ]) for qw/= IN/;
69 threeway_same($handle, id => $_ => 'NULL') for ("IS", "IS NOT");
70 threeway_same($handle, id => $_ => 'null') for ("IS", "IS NOT");
71
72 ## Strings
73 threeway_same($handle, name => $_, "bob") for qw/< > <= >=/;
74 threeway_same($handle, name => $_, 17) for ("=", "!=", "LIKE", "NOT LIKE");
75 threeway_different($handle, name => $_, 17) for ("MATCHES", "STARTS_WITH", "ENDS_WITH");
76 threeway_different($handle, name => $_, "bob") for ("=", "!=", "LIKE", "NOT LIKE", "MATCHES", "STARTS_WITH", "ENDS_WITH");
77 threeway_different($handle, name => $_, "null") for ("=", "!=", "LIKE", "NOT LIKE", "MATCHES", "STARTS_WITH", "ENDS_WITH");
78 threeway_different($handle, name => $_ => [ "bob", "alice" ]) for qw/= IN/;
79 threeway_same($handle, name => $_ => 'NULL') for ("IS", "IS NOT");
80 threeway_same($handle, name => $_ => 'null') for ("IS", "IS NOT");
81
82 ## Other
83 threeway_same($handle, created => $_, 42) for qw/= != < > <= >=/;
84 threeway_same($handle, created => $_, 42) for ("LIKE", "NOT LIKE", "MATCHES", "STARTS_WITH", "ENDS_WITH");
85 threeway_same($handle, created => $_ => [ 42, 17 ]) for qw/= IN/;
86 threeway_same($handle, created => $_ => 'NULL') for ("IS", "IS NOT");
87 threeway_same($handle, created => $_ => 'null') for ("IS", "IS NOT");
88
89 cleanup_schema( 'TestApp', $handle );
90 disconnect_handle($handle);
5891 }
92 }
93
94 sub threeway_same {
95 my ($default, $insensitive, $sensitive) = threeway_test(@_);
96 shift @_;
97 is( $default, $insensitive, "Default and insensitive queries are the same (@_)");
98 is( $sensitive, $insensitive, "Sensitive and insensitive queries are the same (@_)");
99 }
100
101 sub threeway_different {
102 my ($default, $insensitive, $sensitive) = threeway_test(@_);
103 my $handle = shift @_;
104 is( $default, $sensitive, "Default and insensitive queries are the same (@_)");
105 TODO: {
106 local $TODO = "How do we force mysql to be case sensitive?"
107 if $handle =~ /mysql/;
108 isnt( $sensitive, $insensitive, "Sensitive and insensitive queries are not the same (@_)");
109 }
110 }
111
112 sub threeway_test {
113 my ($handle, $column, $op, $value) = @_;
114 my $default = TestApp::UserCollection->new( handle => $handle );
115 $default->limit( column => $column, value => $value, operator => $op );
116
117 my $insensitive = TestApp::UserCollection->new( handle => $handle );
118 $insensitive->limit( column => $column, value => $value, operator => $op, case_sensitive => 0 );
119
120 my $sensitive = TestApp::UserCollection->new( handle => $handle );
121 $sensitive->limit( column => $column, value => $value, operator => $op, case_sensitive => 1 );
122
123 return map {$_->build_select_query} ($default, $insensitive, $sensitive);
59124 }
60125
61126 package TestApp::User;
62127 use base qw/Jifty::DBI::Record/;
63
64 1;
65128
66129 sub schema_sqlite {
67130
69132 CREATE table users (
70133 id integer primary key,
71134 name varchar,
72 interests varchar
135 interests varchar,
136 created date
73137 )
74138 EOF
75139
81145 CREATE TEMPORARY table users (
82146 id integer auto_increment primary key,
83147 name varchar(255),
84 interests varchar(255)
148 interests varchar(255),
149 created date
85150 )
86151 EOF
87152
93158 CREATE TEMPORARY table users (
94159 id serial primary key,
95160 name varchar,
96 interests varchar
161 interests varchar,
162 created date
97163 )
98164 EOF
99165
104170 use Jifty::DBI::Record schema {
105171 column name => type is 'varchar', label is 'Name', is case_sensitive;
106172 column interests => type is 'varchar';
173 column created => type is 'date';
107174 };
108175
176 package TestApp::UserCollection;
177 use base qw/Jifty::DBI::Collection/;
109178
110179 1;
111180