[Bast-commits] r4896 - in DBIx-Class/0.08/branches/view_support: .
lib/DBIx/Class lib/DBIx/Class/Manual
lib/DBIx/Class/Relationship lib/DBIx/Class/ResultClass
lib/DBIx/Class/Storage lib/DBIx/Class/Storage/DBI maint t t/lib
wreis at dev.catalyst.perl.org
wreis at dev.catalyst.perl.org
Tue Oct 7 00:29:20 BST 2008
Author: wreis
Date: 2008-10-07 00:29:20 +0100 (Tue, 07 Oct 2008)
New Revision: 4896
Modified:
DBIx-Class/0.08/branches/view_support/
DBIx-Class/0.08/branches/view_support/Changes
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Exception.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Cookbook.pod
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/FAQ.pod
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship/Base.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultClass/HashRefInflator.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Row.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/ODBC.pm
DBIx-Class/0.08/branches/view_support/maint/benchmark_hashrefinflator.pl
DBIx-Class/0.08/branches/view_support/t/100populate.t
DBIx-Class/0.08/branches/view_support/t/32connect_code_ref.t
DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t
DBIx-Class/0.08/branches/view_support/t/66relationship.t
DBIx-Class/0.08/branches/view_support/t/68inflate_resultclass_hashrefinflator.t
DBIx-Class/0.08/branches/view_support/t/89dbicadmin.t
DBIx-Class/0.08/branches/view_support/t/92storage.t
DBIx-Class/0.08/branches/view_support/t/93single_accessor_object.t
DBIx-Class/0.08/branches/view_support/t/93storage_replication.t
DBIx-Class/0.08/branches/view_support/t/96file_column.t
DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm
Log:
r27171 at tabor (orig r4812): matthewt | 2008-09-16 15:58:25 -0300
fixup get_from_storage and delete to use original ident
r27172 at tabor (orig r4824): matthewt | 2008-09-19 09:39:23 -0300
removed retarded global; if you want this feature, make it a bloody constructor argument, what I'm deleting is -not- DBIC core quality code
r27173 at tabor (orig r4825): matthewt | 2008-09-19 09:39:47 -0300
delete mention of broken HashRefInflator global
r27174 at tabor (orig r4832): ribasushi | 2008-09-21 14:36:58 -0300
Revert r482[45], by implementing a better version of r4760
r27183 at tabor (orig r4841): ribasushi | 2008-09-21 21:34:54 -0300
Make t/93single_accessor_object.t work under DBICTEST_SQLT_DEPLOY=1, although I am not quite sure how and why it passed with the stock sqlite.sql
r27185 at tabor (orig r4843): castaway | 2008-09-22 09:35:06 -0300
FAQ patch from Alex, how to make oracle searches case insensitive
r27186 at tabor (orig r4846): matthewt | 2008-09-24 10:12:51 -0300
first cut at sanitising multi-create/new_related etc., a couple things don't work that -mostly- worked before but what does work is now reliable
r27187 at tabor (orig r4847): plu | 2008-09-24 11:28:25 -0300
r1633 at merkur: plu | 2008-09-24 16:24:27 +0200
default sqlite storage ":memory:", possible to switch back to file storage using ->init_schema( sqlite_use_file => 1 )
r27188 at tabor (orig r4848): plu | 2008-09-24 11:28:32 -0300
r1634 at merkur: plu | 2008-09-24 16:26:06 +0200
doing ->init_schema( sqlite_use_file => 1 ) in 92storage.t 89dbicadmin.t 33storage_reconnect.t 32connect_code_ref.t
r27189 at tabor (orig r4849): plu | 2008-09-24 11:28:38 -0300
r1635 at merkur: plu | 2008-09-24 16:27:05 +0200
not checking if t/var/DBIxClass.db was created anymore (since we use :memory:)
r27190 at tabor (orig r4850): plu | 2008-09-24 12:07:32 -0300
r1639 at merkur: plu | 2008-09-24 17:07:22 +0200
thanks to ribasushi for _sqlite_dbname and fixing 93storage_replication.t
r27191 at tabor (orig r4854): matthewt | 2008-09-28 13:07:23 -0300
new_related works again
r27192 at tabor (orig r4855): ribasushi | 2008-09-28 15:46:08 -0300
mst is right: there is no sane way to allow automatic inflation with HRI, as most core inflation components rely on being passed a live row object. Ripping all related code away
r27193 at tabor (orig r4856): castaway | 2008-09-29 09:16:24 -0300
Doc patch from jhannah
r27194 at tabor (orig r4857): ribasushi | 2008-09-29 14:36:43 -0300
Add cookbook discussion of single() vs first()
r27195 at tabor (orig r4862): ribasushi | 2008-09-30 09:48:35 -0300
Better docs about single()
r27228 at tabor (orig r4863): matthewt | 2008-09-30 20:25:33 -0300
fix new_related on uninserted objects to handle has_manys correctly
r27333 at tabor (orig r4881): castaway | 2008-10-05 08:26:30 -0300
Rename _merge_attr args to something saner than $a, $b
r27334 at tabor (orig r4884): castaway | 2008-10-05 17:46:56 -0300
Fix incorrect relationship docs!
r27335 at tabor (orig r4893): semifor | 2008-10-06 13:43:06 -0300
Use DBI->last_insert_id for ODBC base class.
This closes RT #21260: Problem with last_insert_rowid:
http://rt.cpan.org/Public/Bug/Display.html?id=21260
r27336 at tabor (orig r4894): castaway | 2008-10-06 15:16:07 -0300
cosmincx's patch to show relationship attr filtering in cookbook
r27337 at tabor (orig r4895): semifor | 2008-10-06 17:04:50 -0300
Remove superfluous TODO test
Property changes on: DBIx-Class/0.08/branches/view_support
___________________________________________________________________
Name: svk:merge
- 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/trunk:4809
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
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/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/many_to_many:2025
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/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
+ 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:1639
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/trunk:4895
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
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/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/many_to_many:2025
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/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
Modified: DBIx-Class/0.08/branches/view_support/Changes
===================================================================
--- DBIx-Class/0.08/branches/view_support/Changes 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/Changes 2008-10-06 23:29:20 UTC (rev 4896)
@@ -1,5 +1,8 @@
Revision history for DBIx::Class
+ - Fix storage to copy scalar conds before regexping to avoid
+ trying to modify a constant in odd edge cases
+ - Related resultsets on uninserted objects are now empty
- Fixed up related resultsets and multi-create
- Fixed superfluous connection in ODBC::_rebless
- Fixed undef PK for first insert in ODBC::Microsoft_SQL_Server
@@ -7,8 +10,6 @@
path across multiple versions (jgoulah)
- Better (and marginally faster) implementation of the HashRefInflator
hash construction algorithm
- - Added an option for HashRefInflator to inflate any inflatable
- values in the resulting hashref
- Allow explicit specification of ON DELETE/ON UPDATE constraints
when using the SQLT parser
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Exception.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Exception.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Exception.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -16,8 +16,8 @@
=head1 DESCRIPTION
-Exception objects of this class are used in internally by
-he default error handling of L<DBIx::Class::Schema/throw_exception>
+Exception objects of this class are used internally by
+the default error handling of L<DBIx::Class::Schema/throw_exception>
to prevent confusing and/or redundant re-application of L<Carp>'s
stack trace information.
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Cookbook.pod
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Cookbook.pod 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Cookbook.pod 2008-10-06 23:29:20 UTC (rev 4896)
@@ -68,6 +68,41 @@
For more information on generating complex queries, see
L<SQL::Abstract/WHERE CLAUSES>.
+=head2 Retrieve one and only one row from a resultset
+
+Sometimes you need only the first "top" row of a resultset. While this can be
+easily done with L<< $rs->first|DBIx::Class::ResultSet/first >>, it is suboptimal,
+as a full blown cursor for the resultset will be created and then immediately
+destroyed after fetching the first row object.
+L<< $rs->single|DBIx::Class::ResultSet/single >> is
+designed specifically for this case - it will grab the first returned result
+without even instantiating a cursor.
+
+Before replacing all your calls to C<first()> with C<single()> please observe the
+following CAVEATS:
+
+=over
+
+=item *
+While single() takes a search condition just like search() does, it does
+_not_ accept search attributes. However one can always chain a single() to
+a search():
+
+ my $top_cd = $cd_rs -> search({}, { order_by => 'rating' }) -> single;
+
+
+=item *
+Since single() is the engine behind find(), it is designed to fetch a
+single row per database query. Thus a warning will be issued when the
+underlying SELECT returns more than one row. Sometimes however this usage
+is valid: i.e. we have an arbitrary number of cd's but only one of them is
+at the top of the charts at any given time. If you know what you are doing,
+you can silence the warning by explicitly limiting the resultset size:
+
+ my $top_cd = $cd_rs -> search ({}, { order_by => 'rating', rows => 1 }) -> single;
+
+=back
+
=head2 Arbitrary SQL through a custom ResultSource
Sometimes you have to run arbitrary SQL because your query is too complex
@@ -733,7 +768,7 @@
### The statement below will print
print "I can do admin stuff\n" if $admin->can('do_admin_stuff');
-=head2 Skip object creation for faster results
+=head2 Skip row object creation for faster results
DBIx::Class is not built for speed, it's built for convenience and
ease of use, but sometimes you just need to get the data, and skip the
@@ -746,7 +781,7 @@
$rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
my $hash_ref = $rs->find(1);
-
+
Wasn't that easy?
=head2 Get raw data for blindingly fast results
@@ -870,6 +905,12 @@
__PACKAGE__->has_many('pages' => 'Page', 'book', { order_by => \'page_number DESC'} );
+=head2 Filtering a relationship result set
+
+If you want to get a filtered result set, you can just add add to $attr as follows:
+
+ __PACKAGE__->has_many('pages' => 'Page', 'book', { where => { scrap => 0 } } );
+
=head2 Many-to-many relationships
This is straightforward using L<ManyToMany|DBIx::Class::Relationship/many_to_many>:
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/FAQ.pod
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/FAQ.pod 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/FAQ.pod 2008-10-06 23:29:20 UTC (rev 4896)
@@ -265,6 +265,18 @@
L<DBIx::Class::Manual::Cookbook>, try looking in the SQL::Abstract
documentation.
+=item .. make searches in Oracle (10gR2 and newer) case-insensitive?
+
+To make Oracle behave like most RDBMS use on_connect_do to issue
+alter session statements on database connection establishment:
+
+ ->on_connect_do("ALTER SESSION SET NLS_COMP = 'LINGUISTIC'");
+ ->on_connect_do("ALTER SESSION SET NLS_SORT = '<NLS>_CI'");
+ e.g.
+ ->on_connect_do("ALTER SESSION SET NLS_SORT = 'BINARY_CI'");
+ ->on_connect_do("ALTER SESSION SET NLS_SORT = 'GERMAN_CI'");
+
+
=back
=head2 Fetching data
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship/Base.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship/Base.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship/Base.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -186,9 +186,22 @@
if (@_ > 1 && (@_ % 2 == 1));
my $query = ((@_ > 1) ? {@_} : shift);
- my $cond = $self->result_source->resolve_condition(
+ my $source = $self->result_source;
+ my $cond = $source->resolve_condition(
$rel_obj->{cond}, $rel, $self
);
+ if ($cond eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION) {
+ my $reverse = $source->reverse_relationship_info($rel);
+ foreach my $rev_rel (keys %$reverse) {
+ if ($reverse->{$rev_rel}{attrs}{accessor} eq 'multi') {
+ $attrs->{related_objects}{$rev_rel} = [ $self ];
+ Scalar::Util::weaken($attrs->{related_object}{$rev_rel}[0]);
+ } else {
+ $attrs->{related_objects}{$rev_rel} = $self;
+ Scalar::Util::weaken($attrs->{related_object}{$rev_rel});
+ }
+ }
+ }
if (ref $cond eq 'ARRAY') {
$cond = [ map {
if (ref $_ eq 'HASH') {
@@ -202,7 +215,7 @@
$_;
}
} @$cond ];
- } else {
+ } elsif (ref $cond eq 'HASH') {
foreach my $key (grep { ! /\./ } keys %$cond) {
$cond->{"me.$key"} = delete $cond->{$key};
}
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Relationship.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -31,9 +31,9 @@
MyDB::Schema::Actor->many_to_many('roles' => 'actorroles', 'role');
## Using relationships
- $schema->resultset('Actor')->roles();
- $schema->resultset('Role')->search_related('actors', { Name => 'Fred' });
- $schema->resultset('ActorRole')->add_to_roles({ Name => 'Sherlock Holmes'});
+ $schema->resultset('Actor')->find({ id => 1})->roles();
+ $schema->resultset('Role')->find({ id => 1 })->actorroles->search_related('actor', { Name => 'Fred' });
+ $schema->resultset('Actor')->add_to_roles({ Name => 'Sherlock Holmes'});
See L<DBIx::Class::Manual::Cookbook> for more.
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultClass/HashRefInflator.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultClass/HashRefInflator.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultClass/HashRefInflator.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -3,26 +3,29 @@
use strict;
use warnings;
-our %inflator_cache;
-our $inflate_data;
-
=head1 NAME
DBIx::Class::ResultClass::HashRefInflator
=head1 SYNOPSIS
- my $rs = $schema->resultset('CD');
+ use DBIx::Class::ResultClass::HashRefInflator;
+ my $rs = $schema->resultset('CD');
$rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
+ while (my $hashref = $rs->next) {
+ ...
+ }
=head1 DESCRIPTION
-DBIx::Class is not built for speed: it's built for convenience and
-ease of use. But sometimes you just need to get the data, and skip the
-fancy objects. That is what this class provides.
+DBIx::Class is faster than older ORMs like Class::DBI but it still isn't
+designed primarily for speed. Sometimes you need to quickly retrieve the data
+from a massive resultset, while skipping the creation of fancy row objects.
+Specifying this class as a C<result_class> for a resultset will change C<< $rs->next >>
+to return a plain data hash-ref (or a list of such hash-refs if C<< $rs->all >> is used).
-There are two ways of using this class.
+There are two ways of applying this class to a resultset:
=over
@@ -39,53 +42,23 @@
=back
-=head1 AUTOMATICALLY INFLATING COLUMN VALUES
-
-So you want to skip the DBIx::Class object creation part, but you still want
-all your data to be inflated according to the rules you defined in your table
-classes. Setting the global variable
-C<$DBIx::Class::ResultClass::HashRefInflator::inflate_data> to a true value
-will instruct L<mk_hash> to interrogate the processed columns and apply any
-inflation methods declared via L<DBIx::Class::InflateColumn/inflate_column>.
-
-For increased speed the inflation method lookups are cached in
-C<%DBIx::Class::ResultClass::HashRefInflator::inflator_cache>. Make sure to
-reset this hash if you modify column inflators at run time.
-
-=head1 METHODS
-
-=head2 inflate_result
-
-Inflates the result and prefetched data into a hash-ref using L<mk_hash>.
-
=cut
-sub inflate_result {
- my ($self, $source, $me, $prefetch) = @_;
-
- my $hashref = mk_hash($me, $prefetch);
- inflate_hash ($source->schema, $source->result_class, $hashref) if $inflate_data;
- return $hashref;
-}
-
-=head2 mk_hash
-
-This does all the work of inflating the (pre)fetched data.
-
-=cut
-
##############
# NOTE
#
-# Generally people use this to gain as much speed as possible. If a new mk_hash is
+# Generally people use this to gain as much speed as possible. If a new &mk_hash is
# implemented, it should be benchmarked using the maint/benchmark_hashrefinflator.pl
-# script (in addition to passing all tests of course :). Additional instructions are
+# script (in addition to passing all tests of course :). Additional instructions are
# provided in the script itself.
#
-sub mk_hash {
+# This coderef is a simple recursive function
+# Arguments: ($me, $prefetch) from inflate_result() below
+my $mk_hash;
+$mk_hash = sub {
if (ref $_[0] eq 'ARRAY') { # multi relationship
- return [ map { mk_hash (@$_) || () } (@_) ];
+ return [ map { $mk_hash->(@$_) || () } (@_) ];
}
else {
my $hash = {
@@ -94,7 +67,7 @@
# the second arg is a hash of arrays for each prefetched relation
map
- { $_ => mk_hash( @{$_[1]->{$_}} ) }
+ { $_ => $mk_hash->( @{$_[1]->{$_}} ) }
( $_[1] ? (keys %{$_[1]}) : () )
};
@@ -106,49 +79,30 @@
return undef;
}
-}
+};
-=head2 inflate_hash
+=head1 METHODS
-This walks through a hashref produced by L<mk_hash> and inflates any data
-for which there is a registered inflator in the C<column_info>
+=head2 inflate_result
+Inflates the result and prefetched data into a hash-ref (invoked by L<DBIx::Class::ResultSet>)
+
=cut
-sub inflate_hash {
- my ($schema, $rc, $data) = @_;
+##################################################################################
+# inflate_result is invoked as:
+# HRI->inflate_result ($resultsource_instance, $main_data_hashref, $prefetch_data_hashref)
+sub inflate_result {
+ return $mk_hash->($_[2], $_[3]);
+}
- foreach my $column (keys %{$data}) {
- if (ref $data->{$column} eq 'HASH') {
- inflate_hash ($schema, $schema->source ($rc)->related_class ($column), $data->{$column});
- }
- elsif (ref $data->{$column} eq 'ARRAY') {
- foreach my $rel (@{$data->{$column}}) {
- inflate_hash ($schema, $schema->source ($rc)->related_class ($column), $rel);
- }
- }
- else {
- # "null is null is null"
- next if not defined $data->{$column};
+=head1 CAVEATS
- # cache the inflator coderef
- unless (exists $inflator_cache{$rc}{$column}) {
- $inflator_cache{$rc}{$column} = exists $schema->source ($rc)->_relationships->{$column}
- ? undef # currently no way to inflate a column sharing a name with a rel
- : $rc->column_info($column)->{_inflate_info}{inflate}
- ;
- }
+=over
- if ($inflator_cache{$rc}{$column}) {
- $data->{$column} = $inflator_cache{$rc}{$column}->($data->{$column});
- }
- }
- }
-}
+=item *
-=head1 CAVEAT
-
This will not work for relationships that have been prefetched. Consider the
following:
@@ -162,6 +116,8 @@
HashRefInflator only affects resultsets at inflation time, and prefetch causes
relations to be inflated when the master C<$artist> row is inflated.
+=back
+
=cut
1;
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -573,20 +573,30 @@
my $cd = $schema->resultset('CD')->single({ year => 2001 });
Inflates the first result without creating a cursor if the resultset has
-any records in it; if not returns nothing. Used by L</find> as an optimisation.
+any records in it; if not returns nothing. Used by L</find> as a lean version of
+L</search>.
-Can optionally take an additional condition B<only> - this is a fast-code-path
-method; if you need to add extra joins or similar call L</search> and then
-L</single> without a condition on the L<DBIx::Class::ResultSet> returned from
-that.
+While this method can take an optional search condition (just like L</search>)
+being a fast-code-path it does not recognize search attributes. If you need to
+add extra joins or similar, call L</search> and then chain-call L</single> on the
+L<DBIx::Class::ResultSet> returned.
-B<Note>: As of 0.08100, this method assumes that the query returns only one
-row. If more than one row is returned, you will receive a warning:
+=over
+=item B<Note>
+
+As of 0.08100, this method enforces the assumption that the preceeding
+query returns only one row. If more than one row is returned, you will receive
+a warning:
+
Query returned more than one row
-In this case, you should be using L</first> or L</find> instead.
+In this case, you should be using L</first> or L</find> instead, or if you really
+know what you are doing, use the L</rows> attribute to explicitly limit the size
+of the resultset.
+=back
+
=cut
sub single {
@@ -1519,23 +1529,36 @@
my ($self, $values) = @_;
$self->throw_exception( "new_result needs a hash" )
unless (ref $values eq 'HASH');
- $self->throw_exception(
- "Can't abstract implicit construct, condition not a hash"
- ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
+ my %new;
my $alias = $self->{attrs}{alias};
- my $collapsed_cond = $self->{cond} ? $self->_collapse_cond($self->{cond}) : {};
- # precendence must be given to passed values over values inherited from the cond,
- # so the order here is important.
- my %new;
- my %implied = %{$self->_remove_alias($collapsed_cond, $alias)};
- while( my($col,$value) = each %implied ){
- if(ref($value) eq 'HASH' && keys(%$value) && (keys %$value)[0] eq '='){
- $new{$col} = $value->{'='};
- next;
+ if (
+ defined $self->{cond}
+ && $self->{cond} eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION
+ ) {
+ %new = %{$self->{attrs}{related_objects}};
+ } else {
+ $self->throw_exception(
+ "Can't abstract implicit construct, condition not a hash"
+ ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
+
+ my $collapsed_cond = (
+ $self->{cond}
+ ? $self->_collapse_cond($self->{cond})
+ : {}
+ );
+
+ # precendence must be given to passed values over values inherited from
+ # the cond, so the order here is important.
+ my %implied = %{$self->_remove_alias($collapsed_cond, $alias)};
+ while( my($col,$value) = each %implied ){
+ if(ref($value) eq 'HASH' && keys(%$value) && (keys %$value)[0] eq '='){
+ $new{$col} = $value->{'='};
+ next;
+ }
+ $new{$col} = $value if $self->_is_deterministic_value($value);
}
- $new{$col} = $value if $self->_is_deterministic_value($value);
}
%new = (
@@ -2158,44 +2181,44 @@
}
sub _merge_attr {
- my ($self, $a, $b) = @_;
+ my ($self, $orig, $import) = @_;
- return $b unless defined($a);
- return $a unless defined($b);
+ return $import unless defined($orig);
+ return $orig unless defined($import);
- $a = $self->_rollout_attr($a);
- $b = $self->_rollout_attr($b);
+ $orig = $self->_rollout_attr($orig);
+ $import = $self->_rollout_attr($import);
my $seen_keys;
- foreach my $b_element ( @{$b} ) {
- # find best candidate from $a to merge $b_element into
+ foreach my $import_element ( @{$import} ) {
+ # find best candidate from $orig to merge $b_element into
my $best_candidate = { position => undef, score => 0 }; my $position = 0;
- foreach my $a_element ( @{$a} ) {
- my $score = $self->_calculate_score( $a_element, $b_element );
+ foreach my $orig_element ( @{$orig} ) {
+ my $score = $self->_calculate_score( $orig_element, $import_element );
if ($score > $best_candidate->{score}) {
$best_candidate->{position} = $position;
$best_candidate->{score} = $score;
}
$position++;
}
- my ($b_key) = ( ref $b_element eq 'HASH' ) ? keys %{$b_element} : ($b_element);
+ my ($import_key) = ( ref $import_element eq 'HASH' ) ? keys %{$import_element} : ($import_element);
- if ($best_candidate->{score} == 0 || exists $seen_keys->{$b_key}) {
- push( @{$a}, $b_element );
+ if ($best_candidate->{score} == 0 || exists $seen_keys->{$import_key}) {
+ push( @{$orig}, $import_element );
} else {
- my $a_best = $a->[$best_candidate->{position}];
- # merge a_best and b_element together and replace original with merged
- if (ref $a_best ne 'HASH') {
- $a->[$best_candidate->{position}] = $b_element;
- } elsif (ref $b_element eq 'HASH') {
- my ($key) = keys %{$a_best};
- $a->[$best_candidate->{position}] = { $key => $self->_merge_attr($a_best->{$key}, $b_element->{$key}) };
+ my $orig_best = $orig->[$best_candidate->{position}];
+ # merge orig_best and b_element together and replace original with merged
+ if (ref $orig_best ne 'HASH') {
+ $orig->[$best_candidate->{position}] = $import_element;
+ } elsif (ref $import_element eq 'HASH') {
+ my ($key) = keys %{$orig_best};
+ $orig->[$best_candidate->{position}] = { $key => $self->_merge_attr($orig_best->{$key}, $import_element->{$key}) };
}
}
- $seen_keys->{$b_key} = 1; # don't merge the same key twice
+ $seen_keys->{$import_key} = 1; # don't merge the same key twice
}
- return $a;
+ return $orig;
}
sub result_source {
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -837,6 +837,8 @@
=cut
+our $UNRESOLVABLE_CONDITION = \'1 = 0';
+
sub resolve_condition {
my ($self, $cond, $as, $for) = @_;
#warn %$cond;
@@ -855,7 +857,7 @@
if ($for->in_storage) {
$self->throw_exception("Column ${v} not loaded on ${for} trying to reolve relationship");
}
- return [ \'1 = 0' ];
+ return $UNRESOLVABLE_CONDITION;
}
$ret{$k} = $for->get_column($v);
#$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Row.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Row.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Row.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -378,7 +378,7 @@
my $self = shift;
if (ref $self) {
$self->throw_exception( "Not in database" ) unless $self->in_storage;
- my $ident_cond = $self->ident_condition;
+ my $ident_cond = $self->{_orig_ident} || $self->ident_condition;
$self->throw_exception("Cannot safely delete a row in a PK-less table")
if ! keys %$ident_cond;
foreach my $column (keys %$ident_cond) {
@@ -836,14 +836,13 @@
sub get_from_storage {
my $self = shift @_;
my $attrs = shift @_;
- my @primary_columns = map { $self->$_ } $self->primary_columns;
my $resultset = $self->result_source->resultset;
if(defined $attrs) {
$resultset = $resultset->search(undef, $attrs);
}
- return $resultset->find(@primary_columns);
+ return $resultset->find($self->{_orig_ident} || $self->ident_condition);
}
=head2 throw_exception
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/ODBC.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/ODBC.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/ODBC.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -17,7 +17,15 @@
}
}
+sub _dbh_last_insert_id {
+ my ($self, $dbh, $source, $col) = @_;
+ # punt: if there is no derived class for the specific backend, attempt
+ # to use the DBI->last_insert_id, which may not be sufficient (see the
+ # discussion of last_insert_id in perldoc DBI)
+ return $dbh->last_insert_id(undef, undef, $source->from, $col);
+}
+
1;
=head1 NAME
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -1243,7 +1243,11 @@
my $order = $attrs->{order_by};
if (ref $condition eq 'SCALAR') {
- $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
+ my $unwrap = ${$condition};
+ if ($unwrap =~ s/ORDER BY (.*)$//i) {
+ $order = $1;
+ $condition = \$unwrap;
+ }
}
my $for = delete $attrs->{for};
Modified: DBIx-Class/0.08/branches/view_support/maint/benchmark_hashrefinflator.pl
===================================================================
--- DBIx-Class/0.08/branches/view_support/maint/benchmark_hashrefinflator.pl 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/maint/benchmark_hashrefinflator.pl 2008-10-06 23:29:20 UTC (rev 4896)
@@ -1,56 +1,45 @@
#!/usr/bin/perl
-use warnings;
-use strict;
-
-use FindBin;
-
#
# So you wrote a new mk_hash implementation which passed all tests (particularly
# t/68inflate_resultclass_hashrefinflator) and would like to see how it holds up
-# against older versions of the same. Just add your subroutine somewhere below and
-# add its name to the @bench array. Happy testing.
+# against older versions of the same. Just add your coderef to the HRI::Bench
+# namespace and add a name/ref pair to the %bench_list hash. Happy testing.
-my @bench = qw/current_mk_hash old_mk_hash/;
+package DBIx::Class::ResultClass::HashRefInflator::Bench;
-use Benchmark qw/timethis cmpthese/;
+use warnings;
+use strict;
-use lib ("$FindBin::Bin/../lib", "$FindBin::Bin/../t/lib");
-use DBICTest;
-use DBIx::Class::ResultClass::HashRefInflator;
+my $current_mk_hash;
+$current_mk_hash = sub {
+ if (ref $_[0] eq 'ARRAY') { # multi relationship
+ return [ map { $current_mk_hash->(@$_) || () } (@_) ];
+ }
+ else {
+ my $hash = {
+ # the main hash could be an undef if we are processing a skipped-over join
+ $_[0] ? %{$_[0]} : (),
-chdir ("$FindBin::Bin/..");
-my $schema = DBICTest->init_schema();
+ # the second arg is a hash of arrays for each prefetched relation
+ map
+ { $_ => $current_mk_hash->( @{$_[1]->{$_}} ) }
+ ( $_[1] ? (keys %{$_[1]}) : () )
+ };
-my $test_sub = sub {
- my $rs_hashrefinf = $schema->resultset ('Artist')->search ({}, {
- prefetch => { cds => 'tracks' },
- });
- $rs_hashrefinf->result_class('DBIx::Class::ResultClass::HashRefInflator');
- my @stuff = $rs_hashrefinf->all;
+ # if there is at least one defined column consider the resultset real
+ # (and not an emtpy has_many rel containing one empty hashref)
+ for (values %$hash) {
+ return $hash if defined $_;
+ }
+
+ return undef;
+ }
};
-
-my $results;
-for my $b (@bench) {
- die "No such subroutine '$b' defined!\n" if not __PACKAGE__->can ($b);
- print "Timing $b... ";
-
- # switch the inflator
- no warnings qw/redefine/;
- no strict qw/refs/;
- local *DBIx::Class::ResultClass::HashRefInflator::mk_hash = \&$b;
-
- $results->{$b} = timethis (-2, $test_sub);
-}
-cmpthese ($results);
-
-#-----------------------------
-# mk_hash implementations
-#-----------------------------
-
# the (incomplete, fails a test) implementation before svn:4760
-sub old_mk_hash {
+my $old_mk_hash;
+$old_mk_hash = sub {
my ($me, $rest) = @_;
# $me is the hashref of cols/data from the immediate resultsource
@@ -74,35 +63,56 @@
map {
( $_ =>
ref($rest->{$_}[0]) eq 'ARRAY'
- ? [ grep defined, map old_mk_hash(@$_), @{$rest->{$_}} ]
- : old_mk_hash( @{$rest->{$_}} )
+ ? [ grep defined, map $old_mk_hash->(@$_), @{$rest->{$_}} ]
+ : $old_mk_hash->( @{$rest->{$_}} )
)
} keys %$rest
};
-}
+};
-# current implementation as of svn:4760
-sub current_mk_hash {
- if (ref $_[0] eq 'ARRAY') { # multi relationship
- return [ map { current_mk_hash (@$_) || () } (@_) ];
- }
- else {
- my $hash = {
- # the main hash could be an undef if we are processing a skipped-over join
- $_[0] ? %{$_[0]} : (),
- # the second arg is a hash of arrays for each prefetched relation
- map
- { $_ => current_mk_hash( @{$_[1]->{$_}} ) }
- ( $_[1] ? (keys %{$_[1]}) : () )
- };
+our %bench_list = (
+ current_implementation => $current_mk_hash,
+ old_implementation => $old_mk_hash,
+);
- # if there is at least one defined column consider the resultset real
- # (and not an emtpy has_many rel containing one empty hashref)
- for (values %$hash) {
- return $hash if defined $_;
- }
+1;
- return undef;
- }
+package benchmark_hashrefinflator;
+
+use warnings;
+use strict;
+
+use FindBin;
+use lib ("$FindBin::Bin/../lib", "$FindBin::Bin/../t/lib");
+
+use Benchmark qw/timethis cmpthese/;
+use DBICTest;
+
+chdir ("$FindBin::Bin/..");
+my $schema = DBICTest->init_schema();
+
+my $test_sub = sub {
+ my $rs_hashrefinf = $schema->resultset ('Artist')->search ({}, {
+ prefetch => { cds => 'tracks' },
+ });
+ $rs_hashrefinf->result_class('DBIx::Class::ResultClass::HashRefInflator::Bench');
+ my @stuff = $rs_hashrefinf->all;
+};
+
+
+my $results;
+for my $b (keys %DBIx::Class::ResultClass::HashRefInflator::Bench::bench_list) {
+
+ print "Timing $b... ";
+
+ # switch the inflator
+ no warnings qw/redefine once/;
+ no strict qw/refs/;
+ local *DBIx::Class::ResultClass::HashRefInflator::Bench::inflate_result = sub {
+ return $DBIx::Class::ResultClass::HashRefInflator::Bench::bench_list{$b}->(@_[2,3]);
+ };
+
+ $results->{$b} = timethis (-2, $test_sub);
}
+cmpthese ($results);
Modified: DBIx-Class/0.08/branches/view_support/t/100populate.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/100populate.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/100populate.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -5,7 +5,7 @@
use lib qw(t/lib);
use DBICTest;
-plan tests => 22;
+plan tests => 21;
# perl -le'my $letter = 'a'; for my $i (4..10000) { $letter++; print "[ $i, \"$letter\" ]," }' > tests.txt
@@ -10081,5 +10081,3 @@
is($link7->url, undef, 'Link 7 url');
is($link7->title, 'gtitle', 'Link 7 title');
-
-ok(-f "t/var/DBIxClass.db", 'Database created');
Modified: DBIx-Class/0.08/branches/view_support/t/32connect_code_ref.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/32connect_code_ref.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/32connect_code_ref.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -8,7 +8,7 @@
plan tests => 1;
# Set up the "usual" sqlite for DBICTest
-my $normal_schema = DBICTest->init_schema;
+my $normal_schema = DBICTest->init_schema( sqlite_use_file => 1 );
# Steal the dsn, which should be like 'dbi:SQLite:t/var/DBIxClass.db'
my $normal_dsn = $normal_schema->storage->connect_info->[0];
Modified: DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -13,7 +13,7 @@
my $db_tmp = "$db_orig.tmp";
# Set up the "usual" sqlite for DBICTest
-my $schema = DBICTest->init_schema;
+my $schema = DBICTest->init_schema( sqlite_use_file => 1 );
# Make sure we're connected by doing something
my @art = $schema->resultset("Artist")->search({ }, { order_by => 'name DESC'});
Modified: DBIx-Class/0.08/branches/view_support/t/66relationship.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/66relationship.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/66relationship.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -7,7 +7,7 @@
my $schema = DBICTest->init_schema();
-plan tests => 63;
+plan tests => 65;
# has_a test
my $cd = $schema->resultset("CD")->find(4);
@@ -213,7 +213,11 @@
my $undef_artist_cd = $schema->resultset("CD")->new_result({ 'title' => 'badgers', 'year' => 2007 });
is($undef_artist_cd->has_column_loaded('artist'), '', 'FK not loaded');
is($undef_artist_cd->search_related('artist')->count, 0, '0=1 search when FK does not exist and object not yet in db');
-
+eval{
+ $undef_artist_cd->related_resultset('artist')->new({name => 'foo'});
+};
+is( $@, '', "Object created on a resultset related to not yet inserted object");
+
my $def_artist_cd = $schema->resultset("CD")->new_result({ 'title' => 'badgers', 'year' => 2007, artist => undef });
is($def_artist_cd->has_column_loaded('artist'), 1, 'FK loaded');
is($def_artist_cd->search_related('artist')->count, 0, 'closed search on null FK');
@@ -250,3 +254,13 @@
cmp_ok($artist->cds->count, '==', 0, "Correct new #cds for artist");
cmp_ok($nartist->cds->count, '==', 2, "Correct new #cds for artist");
+my $new_artist = $schema->resultset("Artist")->new_result({ 'name' => 'Depeche Mode' });
+# why must i tell him: make a new related from me and me is me? that works!
+# my $new_related_cd = $new_artist->new_related('cds', { 'title' => 'Leave in Silence', 'year' => 1982, 'artist' => $new_artist });
+my $new_related_cd = $new_artist->new_related('cds', { 'title' => 'Leave in Silence', 'year' => 1982});
+eval {
+ $new_artist->insert;
+ $new_related_cd->insert;
+};
+$@ && diag($@);
+ok($new_related_cd->in_storage, 'new_related_cd insert ok');
Modified: DBIx-Class/0.08/branches/view_support/t/68inflate_resultclass_hashrefinflator.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/68inflate_resultclass_hashrefinflator.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/68inflate_resultclass_hashrefinflator.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -3,8 +3,6 @@
use Test::More qw(no_plan);
use lib qw(t/lib);
-use Scalar::Util qw/blessed/;
-use DateTime;
use DBICTest;
use DBIx::Class::ResultClass::HashRefInflator;
my $schema = DBICTest->init_schema();
@@ -117,23 +115,3 @@
is ($track->get_column ($col), $datahashref->{cds}{tracks}{$col}, "Correct track '$col'");
}
}
-
-# Test the data inflator
-
-$schema->class('CD')->inflate_column( 'year',
- { inflate => sub { DateTime->new( year => shift ) },
- deflate => sub { shift->year } }
-);
-
-my $cd_rs = $schema->resultset("CD")->search ({cdid => 3});
-$cd_rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
-
-my $cd = $cd_rs->first;
-ok ( (not blessed $cd->{year}), "Plain string returned for year");
-is ( $cd->{year}, '1997', "We are looking at the right year");
-
-# try it again with inflation requested
-local $DBIx::Class::ResultClass::HashRefInflator::inflate_data = 1;
-my $cd2 = $cd_rs->first;
-isa_ok ($cd2->{year}, 'DateTime', "Inflated object");
-is ($cd2->{year}, DateTime->new ( year => 1997 ), "Correct year was inflated");
Modified: DBIx-Class/0.08/branches/view_support/t/89dbicadmin.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/89dbicadmin.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/89dbicadmin.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -6,7 +6,7 @@
use lib qw(t/lib);
use DBICTest;
-my $schema = DBICTest->init_schema();
+my $schema = DBICTest->init_schema( sqlite_use_file => 1 );
eval 'require JSON::Any';
plan skip_all => 'Install JSON::Any to run this test' if ($@);
Modified: DBIx-Class/0.08/branches/view_support/t/92storage.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/92storage.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/92storage.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -34,7 +34,7 @@
plan tests => 6;
-my $schema = DBICTest->init_schema();
+my $schema = DBICTest->init_schema( sqlite_use_file => 1 );
is( ref($schema->storage), 'DBIx::Class::Storage::DBI::SQLite',
'Storage reblessed correctly into DBIx::Class::Storage::DBI::SQLite' );
Modified: DBIx-Class/0.08/branches/view_support/t/93single_accessor_object.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/93single_accessor_object.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/93single_accessor_object.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -56,7 +56,7 @@
{
my $artist = $schema->resultset('Artist')->create({ artistid => 666, name => 'bad religion' });
- my $genre = $schema->resultset('Genre')->create({ name => 'disco' });
+ my $genre = $schema->resultset('Genre')->create({ genreid => 88, name => 'disco' });
my $cd = $schema->resultset('CD')->create({ cdid => 187, artist => 1, title => 'how could hell be any worse?', year => 1982 });
dies_ok { $cd->genre } 'genre accessor throws without column';
Modified: DBIx-Class/0.08/branches/view_support/t/93storage_replication.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/93storage_replication.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/93storage_replication.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -62,6 +62,7 @@
my $class = shift @_;
my $schema = DBICTest->init_schema(
+ sqlite_use_file => 1,
storage_type=>{
'::DBI::Replicated' => {
balancer_type=>'::Random',
Modified: DBIx-Class/0.08/branches/view_support/t/96file_column.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/96file_column.t 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/96file_column.t 2008-10-06 23:29:20 UTC (rev 4896)
@@ -10,7 +10,7 @@
my $schema = DBICTest->init_schema();
-plan tests => 11;
+plan tests => 10;
my $rs = $schema->resultset('FileColumn');
my $fname = '96file_column.t';
@@ -66,22 +66,20 @@
ok ( ! -e $storage, 'storage deleted' );
-TODO: {
- local $TODO = 'need resultset delete override to delete_all';
+$fh = $source_file->openr or die "failed to open $source_file: $!\n";
+$fc = $rs->create({ file => { handle => $fh, filename => $fname } });
- $fh = $source_file->openr or die "failed to open $source_file: $!\n";
- $fc = $rs->create({ file => { handle => $fh, filename => $fname } });
+# read it back
+$fc->discard_changes;
- # read it back
- $fc->discard_changes;
+$storage = file(
+ $fc->column_info('file')->{file_column_path},
+ $fc->id,
+ $fc->file->{filename},
+);
- $storage = file(
- $fc->column_info('file')->{file_column_path},
- $fc->id,
- $fc->file->{filename},
- );
- ok ( -e $storage, 'storage exists (2)' );
-
+TODO: {
+ local $TODO = 'need resultset delete override to delete_all';
$rs->delete;
ok ( ! -e $storage, 'storage does not exist after $rs->delete' );
};
Modified: DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm 2008-10-06 20:04:50 UTC (rev 4895)
+++ DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm 2008-10-06 23:29:20 UTC (rev 4896)
@@ -51,12 +51,20 @@
}
sub _sqlite_dbfilename {
- return "t/var/DBIxClass.db";
+ return "t/var/DBIxClass.db";
}
+sub _sqlite_dbname {
+ my $self = shift;
+ my %args = @_;
+ return $self->_sqlite_dbfilename if $args{sqlite_use_file} or $ENV{"DBICTEST_SQLITE_USE_FILE"};
+ return ":memory:";
+}
+
sub _database {
my $self = shift;
- my $db_file = $self->_sqlite_dbfilename;
+ my %args = @_;
+ my $db_file = $self->_sqlite_dbname(%args);
unlink($db_file) if -e $db_file;
unlink($db_file . "-journal") if -e $db_file . "-journal";
@@ -76,10 +84,10 @@
my %args = @_;
my $schema;
-
+
if ($args{compose_connection}) {
$schema = DBICTest::Schema->compose_connection(
- 'DBICTest', $self->_database
+ 'DBICTest', $self->_database(%args)
);
} else {
$schema = DBICTest::Schema->compose_namespace('DBICTest');
@@ -88,7 +96,7 @@
$schema->storage_type($args{storage_type});
}
if ( !$args{no_connect} ) {
- $schema = $schema->connect($self->_database);
+ $schema = $schema->connect($self->_database(%args));
$schema->storage->on_connect_do(['PRAGMA synchronous = OFF'])
unless $self->has_custom_dsn;
}
More information about the Bast-commits
mailing list