Codebase list libdbix-class-perl / a7e6555
new upstream release 0.08112 Jose Luis Rivas Contreras 14 years ago
50 changed file(s) with 805 addition(s) and 578 deletion(s). Raw diff Collapse all Expand all
00 Revision history for DBIx::Class
1
2 0.08112 2009-09-21 10:57:00 (UTC)
3 - Remove the recommends from Makefile.PL, DBIx::Class is not
4 supposed to have optional dependencies. ever.
5 - Mangle the DBIx/Class.pm POD to be more clear about
6 copyright and license
7 - Put back PG's multiple autoinc per table support, accidentally
8 dropped during the serial-autodetection rewrite
9 - Make sure ResultSetColumn does not depend on the (undefined)
10 return value of ->cursor->reset()
11 - Add single() to ResultSetColumn (same semantics as ResultSet)
12 - Make sure to turn off IDENTITY_INSERT after insert() on MSSQL
13 tables that needed it
14 - More informative exception on failing _resolve_relationship
15 - Allow undef/NULL as the sole grouping value in Ordered
16 - Fix unreported rollback exceptions in TxnScopeGuard
17 - Fix overly-eager left-join chain enforcing code
18 - Warn about using distinct with an existing group_by
19 - Warn about attempting to $rs->get_column a non-unique column
20 when has_many joins are added to resultset
21 - Refactor of the exception handling system (now everything is a
22 DBIx::Class::Exception object)
123
224 0.08111 2009-09-06 21:58:00 (UTC)
325 - The hashref to connection_info now accepts a 'dbh_maker'
4062 - Support for MSSQL 'money' type
4163 - Support for 'smalldatetime' type used in MSSQL and Sybase for
4264 InflateColumn::DateTime
43 - support for Postgres 'timestamp without timezone' type in
65 - Support for Postgres 'timestamp without timezone' type in
4466 InflateColumn::DateTime (RT#48389)
4567 - Added new MySQL specific on_connect_call macro 'set_strict_mode'
4668 (also known as make_mysql_not_suck_as_much)
427427 t/prefetch/double_prefetch.t
428428 t/prefetch/grouped.t
429429 t/prefetch/incomplete.t
430 t/prefetch/join_type.t
430431 t/prefetch/multiple_hasmany.t
431432 t/prefetch/standard.t
432433 t/prefetch/via_search_related.t
2929 - examples
3030 - inc
3131 - t
32 recommends:
33 SQL::Translator: 0.11002
3432 requires:
3533 Carp::Clan: 6.0
3634 Class::Accessor::Grouped: 0.09000
5654 MailingList: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
5755 license: http://dev.perl.org/licenses/
5856 repository: http://dev.catalyst.perl.org/svnweb/bast/browse/DBIx-Class/
59 version: 0.08111
57 version: 0.08112
33 use POSIX ();
44
55 use 5.006001; # delete this line if you want to send patches for earlier.
6
7 # ****** DO NOT ADD OPTIONAL DEPENDENCIES. EVER. --mst ******
68
79 name 'DBIx-Class';
810 perl_version '5.006001';
5153 'Hash::Merge', => '0.11',
5254 );
5355
54 # when changing also adjust $DBIx::Class::minimum_sqlt_version
55 my $sqlt_recommends = '0.11002';
56
57 recommends 'SQL::Translator' => $sqlt_recommends;
58
56 #************************************************************************#
57 # Make *ABSOLUTELY SURE* that nothing on this list is a real require, #
58 # since every module listed in %force_requires_if_author is deleted #
59 # from the final META.yml (thus will never make it as a CPAN dependency) #
60 #************************************************************************#
5961 my %force_requires_if_author = (
6062 %replication_requires,
6163
64 # when changing also adjust $DBIx::Class::Storage::DBI::minimum_sqlt_version
65 'SQL::Translator' => '0.11002',
66
6267 # 'Module::Install::Pod::Inherit' => '0.01',
63 'SQL::Translator' => $sqlt_recommends,
6468
6569 # when changing also adjust version in t/02pod.t
6670 'Test::Pod' => '1.26',
110114 ) : ()
111115 ,
112116 );
117 #************************************************************************#
118 # Make ABSOLUTELY SURE that nothing on the list above is a real require, #
119 # since every module listed in %force_requires_if_author is deleted #
120 # from the final META.yml (thus will never make it as a CPAN dependency) #
121 #************************************************************************#
113122
114123
115124 install_script (qw|
176176
177177 bricas: Brian Cassidy <bricas@cpan.org>
178178
179 brunov: Bruno Vecchi <vecchi.b@gmail.com>
180
179181 caelum: Rafael Kitover <rkitover@cpan.org>
180182
181183 castaway: Jess Robinson
0 libdbix-class-perl (0.08111-1) UNRELEASED; urgency=low
0 libdbix-class-perl (0.08112-1) UNRELEASED; urgency=low
11
22 [ Jonathan Yu ]
33 WAITS for advice from Peter Rabbitson/ribasushi (upstream maintainer). He
2424 * Update environment variables for test suite in debian/rules.
2525 * debian/copyright: update list of copyright holders.
2626
27 -- Ryan Niebur <ryan@debian.org> Fri, 25 Sep 2009 00:24:35 -0700
27 [ Jose Luis Rivas ]
28 * New upstream release 0.08112
29
30 -- Jose Luis Rivas <ghostbar@debian.org> Fri, 25 Sep 2009 07:27:45 -0430
2831
2932 libdbix-class-perl (0.08108-1) unstable; urgency=low
3033
2222
2323 my @cds;
2424 foreach my $lp (keys %albums) {
25 my $artist = $schema->resultset('Artist')->search({
25 my $artist = $schema->resultset('Artist')->find({
2626 name => $albums{$lp}
2727 });
28 push @cds, [$lp, $artist->first];
28 push @cds, [$lp, $artist->id];
2929 }
3030
3131 $schema->populate('Cd', [
4646
4747 my @tracks;
4848 foreach my $track (keys %tracks) {
49 my $cdname = $schema->resultset('Cd')->search({
49 my $cd = $schema->resultset('Cd')->find({
5050 title => $tracks{$track},
5151 });
52 push @tracks, [$cdname->first, $track];
52 push @tracks, [$cd->id, $track];
5353 }
5454
5555 $schema->populate('Track',[
33 use strict;
44 use warnings;
55
6 ###
7 # Keep this class for backwards compatibility
8 ###
9
610 use base 'Class::C3::Componentised';
7 use Carp::Clan qw/^DBIx::Class/;
8
9 sub inject_base {
10 my ($class, $target, @to_inject) = @_;
11 {
12 no strict 'refs';
13 foreach my $to (reverse @to_inject) {
14 my @comps = qw(DigestColumns ResultSetManager Ordered UTF8Columns);
15 # Add components here that need to be loaded before Core
16 foreach my $first_comp (@comps) {
17 if ($to eq 'DBIx::Class::Core' &&
18 $target->isa("DBIx::Class::${first_comp}")) {
19 carp "Possible incorrect order of components in ".
20 "${target}::load_components($first_comp) call: Core loaded ".
21 "before $first_comp. See the documentation for ".
22 "DBIx::Class::$first_comp for more information";
23 }
24 }
25 unshift( @{"${target}::ISA"}, $to )
26 unless ($target eq $to || $target->isa($to));
27 }
28 }
29
30 $class->next::method($target, @to_inject);
31 }
3211
3312 1;
11
22 use strict;
33 use warnings;
4
5 use base qw/DBIx::Class/;
46
57 =head1 NAME
68
154154
155155 my @cds;
156156 foreach my $lp (keys %albums) {
157 my $artist = $schema->resultset('Artist')->search({
157 my $artist = $schema->resultset('Artist')->find({
158158 name => $albums{$lp}
159159 });
160 push @cds, [$lp, $artist->first];
160 push @cds, [$lp, $artist->id];
161161 }
162162
163163 $schema->populate('Cd', [
178178
179179 my @tracks;
180180 foreach my $track (keys %tracks) {
181 my $cdname = $schema->resultset('Cd')->search({
181 my $cdname = $schema->resultset('Cd')->find({
182182 title => $tracks{$track},
183183 });
184 push @tracks, [$cdname->first, $track];
184 push @tracks, [$cdname->id, $track];
185185 }
186186
187187 $schema->populate('Track',[
433433 sub move_to_group {
434434 my( $self, $to_group, $to_position ) = @_;
435435
436 $self->throw_exception ('move_to_group() expects a group specification')
437 unless defined $to_group;
438
439 # if we're given a string, turn it into a hashref
436 # if we're given a single value, turn it into a hashref
440437 unless (ref $to_group eq 'HASH') {
441438 my @gcols = $self->_grouping_columns;
442439
66 'bool' => "_bool",
77 fallback => 1;
88 use Carp::Clan qw/^DBIx::Class/;
9 use DBIx::Class::Exception;
910 use Data::Page;
1011 use Storable;
1112 use DBIx::Class::ResultSetColumn;
569570 my $where = $self->_collapse_cond($self->{attrs}{where} || {});
570571 my $num_where = scalar keys %$where;
571572
572 my @unique_queries;
573 my (@unique_queries, %seen_column_combinations);
573574 foreach my $name (@constraint_names) {
574 my @unique_cols = $self->result_source->unique_constraint_columns($name);
575 my $unique_query = $self->_build_unique_query($query, \@unique_cols);
576
577 my $num_cols = scalar @unique_cols;
575 my @constraint_cols = $self->result_source->unique_constraint_columns($name);
576
577 my $constraint_sig = join "\x00", sort @constraint_cols;
578 next if $seen_column_combinations{$constraint_sig}++;
579
580 my $unique_query = $self->_build_unique_query($query, \@constraint_cols);
581
582 my $num_cols = scalar @constraint_cols;
578583 my $num_query = scalar keys %$unique_query;
579584
580585 my $total = $num_query + $num_where;
21912196 a unique constraint that is not the primary key, or looking for
21922197 related rows.
21932198
2194 If you want objects to be saved immediately, use L</find_or_create> instead.
2195
2196 B<Note>: C<find_or_new> is probably not what you want when creating a
2197 new row in a table that uses primary keys supplied by the
2198 database. Passing in a primary key column with a value of I<undef>
2199 will cause L</find> to attempt to search for a row with a value of
2200 I<NULL>.
2199 If you want objects to be saved immediately, use L</find_or_create>
2200 instead.
2201
2202 B<Note>: Take care when using C<find_or_new> with a table having
2203 columns with default values that you intend to be automatically
2204 supplied by the database (e.g. an auto_increment primary key column).
2205 In normal usage, the value of such columns should NOT be included at
2206 all in the call to C<find_or_new>, even when set to C<undef>.
22012207
22022208 =cut
22032209
23392345 the find has completed and before the create has started. To avoid
23402346 this problem, use find_or_create() inside a transaction.
23412347
2342 B<Note>: C<find_or_create> is probably not what you want when creating
2343 a new row in a table that uses primary keys supplied by the
2344 database. Passing in a primary key column with a value of I<undef>
2345 will cause L</find> to attempt to search for a row with a value of
2346 I<NULL>.
2348 B<Note>: Take care when using C<find_or_create> with a table having
2349 columns with default values that you intend to be automatically
2350 supplied by the database (e.g. an auto_increment primary key column).
2351 In normal usage, the value of such columns should NOT be included at
2352 all in the call to C<find_or_create>, even when set to C<undef>.
23472353
23482354 See also L</find> and L</update_or_create>. For information on how to declare
23492355 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
24062412 See also L</find> and L</find_or_create>. For information on how to declare
24072413 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
24082414
2409 B<Note>: C<update_or_create> is probably not what you want when
2410 looking for a row in a table that uses primary keys supplied by the
2411 database, unless you actually have a key value. Passing in a primary
2412 key column with a value of I<undef> will cause L</find> to attempt to
2413 search for a row with a value of I<NULL>.
2415 B<Note>: Take care when using C<update_or_create> with a table having
2416 columns with default values that you intend to be automatically
2417 supplied by the database (e.g. an auto_increment primary key column).
2418 In normal usage, the value of such columns should NOT be included at
2419 all in the call to C<update_or_create>, even when set to C<undef>.
24142420
24152421 =cut
24162422
24672473 $cd->insert;
24682474 }
24692475
2470 See also L</find>, L</find_or_create> and L<find_or_new>.
2476 B<Note>: Take care when using C<update_or_new> with a table having
2477 columns with default values that you intend to be automatically
2478 supplied by the database (e.g. an auto_increment primary key column).
2479 In normal usage, the value of such columns should NOT be included at
2480 all in the call to C<update_or_new>, even when set to C<undef>.
2481
2482 See also L</find>, L</find_or_create> and L</find_or_new>.
24712483
24722484 =cut
24732485
27772789
27782790 # build columns (as long as select isn't set) into a set of as/select hashes
27792791 unless ( $attrs->{select} ) {
2780 @colbits = map {
2781 ( ref($_) eq 'HASH' )
2782 ? $_
2783 : {
2784 (
2785 /^\Q${alias}.\E(.+)$/
2786 ? "$1"
2787 : "$_"
2788 )
2789 =>
2790 (
2791 /\./
2792 ? "$_"
2793 : "${alias}.$_"
2794 )
2795 }
2796 } ( ref($attrs->{columns}) eq 'ARRAY' ) ? @{ delete $attrs->{columns}} : (delete $attrs->{columns} || $source->columns );
2797 }
2792
2793 my @cols = ( ref($attrs->{columns}) eq 'ARRAY' )
2794 ? @{ delete $attrs->{columns}}
2795 : (
2796 ( delete $attrs->{columns} )
2797 ||
2798 $source->columns
2799 )
2800 ;
2801
2802 @colbits = map {
2803 ( ref($_) eq 'HASH' )
2804 ? $_
2805 : {
2806 (
2807 /^\Q${alias}.\E(.+)$/
2808 ? "$1"
2809 : "$_"
2810 )
2811 =>
2812 (
2813 /\./
2814 ? "$_"
2815 : "${alias}.$_"
2816 )
2817 }
2818 } @cols;
2819 }
2820
27982821 # add the additional columns on
27992822 foreach ( 'include_columns', '+columns' ) {
28002823 push @colbits, map {
28912914 # generate the distinct induced group_by early, as prefetch will be carried via a
28922915 # subquery (since a group_by is present)
28932916 if (delete $attrs->{distinct}) {
2894 $attrs->{group_by} ||= [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
2917 if ($attrs->{group_by}) {
2918 carp ("Useless use of distinct on a grouped resultset ('distinct' is ignored when a 'group_by' is present)");
2919 }
2920 else {
2921 $attrs->{group_by} = [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
2922 }
28952923 }
28962924
28972925 $attrs->{collapse} ||= {};
30863114
30873115 sub throw_exception {
30883116 my $self=shift;
3117
30893118 if (ref $self && $self->_source_handle->schema) {
30903119 $self->_source_handle->schema->throw_exception(@_)
3091 } else {
3092 croak(@_);
3093 }
3094
3120 }
3121 else {
3122 DBIx::Class::Exception->throw(@_);
3123 }
30953124 }
30963125
30973126 # XXX: FIXME: Attributes docs need clearing up
35103539
35113540 =back
35123541
3513 Set to 1 to group by all columns.
3542 Set to 1 to group by all columns. If the resultset already has a group_by
3543 attribute, this setting is ignored and an appropriate warning is issued.
35143544
35153545 =head2 where
35163546
35443574 For more examples of using these attributes, see
35453575 L<DBIx::Class::Manual::Cookbook>.
35463576
3547 =head2 from
3548
3549 =over 4
3550
3551 =item Value: \@from_clause
3552
3553 =back
3554
3555 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
3556 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
3557 clauses.
3558
3559 NOTE: Use this on your own risk. This allows you to shoot off your foot!
3560
3561 C<join> will usually do what you need and it is strongly recommended that you
3562 avoid using C<from> unless you cannot achieve the desired result using C<join>.
3563 And we really do mean "cannot", not just tried and failed. Attempting to use
3564 this because you're having problems with C<join> is like trying to use x86
3565 ASM because you've got a syntax error in your C. Trust us on this.
3566
3567 Now, if you're still really, really sure you need to use this (and if you're
3568 not 100% sure, ask the mailing list first), here's an explanation of how this
3569 works.
3570
3571 The syntax is as follows -
3572
3573 [
3574 { <alias1> => <table1> },
3575 [
3576 { <alias2> => <table2>, -join_type => 'inner|left|right' },
3577 [], # nested JOIN (optional)
3578 { <table1.column1> => <table2.column2>, ... (more conditions) },
3579 ],
3580 # More of the above [ ] may follow for additional joins
3581 ]
3582
3583 <table1> <alias1>
3584 JOIN
3585 <table2> <alias2>
3586 [JOIN ...]
3587 ON <table1.column1> = <table2.column2>
3588 <more joins may follow>
3589
3590 An easy way to follow the examples below is to remember the following:
3591
3592 Anything inside "[]" is a JOIN
3593 Anything inside "{}" is a condition for the enclosing JOIN
3594
3595 The following examples utilize a "person" table in a family tree application.
3596 In order to express parent->child relationships, this table is self-joined:
3597
3598 # Person->belongs_to('father' => 'Person');
3599 # Person->belongs_to('mother' => 'Person');
3600
3601 C<from> can be used to nest joins. Here we return all children with a father,
3602 then search against all mothers of those children:
3603
3604 $rs = $schema->resultset('Person')->search(
3605 undef,
3606 {
3607 alias => 'mother', # alias columns in accordance with "from"
3608 from => [
3609 { mother => 'person' },
3610 [
3611 [
3612 { child => 'person' },
3613 [
3614 { father => 'person' },
3615 { 'father.person_id' => 'child.father_id' }
3616 ]
3617 ],
3618 { 'mother.person_id' => 'child.mother_id' }
3619 ],
3620 ]
3621 },
3622 );
3623
3624 # Equivalent SQL:
3625 # SELECT mother.* FROM person mother
3626 # JOIN (
3627 # person child
3628 # JOIN person father
3629 # ON ( father.person_id = child.father_id )
3630 # )
3631 # ON ( mother.person_id = child.mother_id )
3632
3633 The type of any join can be controlled manually. To search against only people
3634 with a father in the person table, we could explicitly use C<INNER JOIN>:
3635
3636 $rs = $schema->resultset('Person')->search(
3637 undef,
3638 {
3639 alias => 'child', # alias columns in accordance with "from"
3640 from => [
3641 { child => 'person' },
3642 [
3643 { father => 'person', -join_type => 'inner' },
3644 { 'father.id' => 'child.father_id' }
3645 ],
3646 ]
3647 },
3648 );
3649
3650 # Equivalent SQL:
3651 # SELECT child.* FROM person child
3652 # INNER JOIN person father ON child.father_id = father.id
3653
3654 You can select from a subquery by passing a resultset to from as follows.
3655
3656 $schema->resultset('Artist')->search(
3657 undef,
3658 { alias => 'artist2',
3659 from => [ { artist2 => $artist_rs->as_query } ],
3660 } );
3661
3662 # and you'll get sql like this..
3663 # SELECT artist2.artistid, artist2.name, artist2.rank, artist2.charfield FROM
3664 # ( SELECT me.artistid, me.name, me.rank, me.charfield FROM artists me ) artist2
3665
3666 If you need to express really complex joins, you
3667 can supply literal SQL to C<from> via a scalar reference. In this case
3668 the contents of the scalar will replace the table name associated with the
3669 resultsource.
3670
3671 WARNING: This technique might very well not work as expected on chained
3672 searches - you have been warned.
3673
3674 # Assuming the Event resultsource is defined as:
3675
3676 MySchema::Event->add_columns (
3677 sequence => {
3678 data_type => 'INT',
3679 is_auto_increment => 1,
3680 },
3681 location => {
3682 data_type => 'INT',
3683 },
3684 type => {
3685 data_type => 'INT',
3686 },
3687 );
3688 MySchema::Event->set_primary_key ('sequence');
3689
3690 # This will get back the latest event for every location. The column
3691 # selector is still provided by DBIC, all we do is add a JOIN/WHERE
3692 # combo to limit the resultset
3693
3694 $rs = $schema->resultset('Event');
3695 $table = $rs->result_source->name;
3696 $latest = $rs->search (
3697 undef,
3698 { from => \ "
3699 (SELECT e1.* FROM $table e1
3700 JOIN $table e2
3701 ON e1.location = e2.location
3702 AND e1.sequence < e2.sequence
3703 WHERE e2.sequence is NULL
3704 ) me",
3705 },
3706 );
3707
3708 # Equivalent SQL (with the DBIC chunks added):
3709
3710 SELECT me.sequence, me.location, me.type FROM
3711 (SELECT e1.* FROM events e1
3712 JOIN events e2
3713 ON e1.location = e2.location
3714 AND e1.sequence < e2.sequence
3715 WHERE e2.sequence is NULL
3716 ) me;
3717
37183577 =head2 for
37193578
37203579 =over 4
00 package DBIx::Class::ResultSetColumn;
1
12 use strict;
23 use warnings;
4
35 use base 'DBIx::Class';
6
7 use Carp::Clan qw/^DBIx::Class/;
8 use DBIx::Class::Exception;
49 use List::Util;
510
611 =head1 NAME
6065 my $select = defined $as_index ? $select_list->[$as_index] : $column;
6166
6267 # {collapse} would mean a has_many join was injected, which in turn means
63 # we need to group IF WE CAN (only if the column in question is unique)
68 # we need to group *IF WE CAN* (only if the column in question is unique)
6469 if (!$new_attrs->{group_by} && keys %{$orig_attrs->{collapse}}) {
6570
6671 # scan for a constraint that would contain our column only - that'd be proof
7580
7681 if ($col eq $select or $fqcol eq $select) {
7782 $new_attrs->{group_by} = [ $select ];
83 delete $new_attrs->{distinct}; # it is ignored when group_by is present
7884 last;
7985 }
8086 }
87
88 if (!$new_attrs->{group_by}) {
89 carp (
90 "Attempting to retrieve non-unique column '$column' on a resultset containing "
91 . 'one-to-many joins will return duplicate results.'
92 );
93 }
8194 }
8295
8396 my $new = bless { _select => $select, _as => $column, _parent_resultset => $new_parent_rs }, $class;
124137
125138 sub next {
126139 my $self = shift;
140
141 # using cursor so we don't inflate anything
127142 my ($row) = $self->_resultset->cursor->next;
143
128144 return $row;
129145 }
130146
148164
149165 sub all {
150166 my $self = shift;
167
168 # using cursor so we don't inflate anything
151169 return map { $_->[0] } $self->_resultset->cursor->all;
152170 }
153171
193211
194212 sub first {
195213 my $self = shift;
196 my ($row) = $self->_resultset->cursor->reset->next;
214
215 # using cursor so we don't inflate anything
216 $self->_resultset->cursor->reset;
217 my ($row) = $self->_resultset->cursor->next;
218
219 return $row;
220 }
221
222 =head2 single
223
224 =over 4
225
226 =item Arguments: none
227
228 =item Return Value: $value
229
230 =back
231
232 Much like L<DBIx::Class::ResultSet/single> fetches one and only one column
233 value using the cursor directly. If additional rows are present a warning
234 is issued before discarding the cursor.
235
236 =cut
237
238 sub single {
239 my $self = shift;
240
241 my $attrs = $self->_resultset->_resolved_attrs;
242 my ($row) = $self->_resultset->result_source->storage->select_single(
243 $attrs->{from}, $attrs->{select}, $attrs->{where}, $attrs
244 );
245
197246 return $row;
198247 }
199248
377426
378427 sub throw_exception {
379428 my $self=shift;
429
380430 if (ref $self && $self->{_parent_resultset}) {
381 $self->{_parent_resultset}->throw_exception(@_)
382 } else {
383 croak(@_);
431 $self->{_parent_resultset}->throw_exception(@_);
432 }
433 else {
434 DBIx::Class::Exception->throw(@_);
384435 }
385436 }
386437
394445 #
395446 # Returns the underlying resultset. Creates it from the parent resultset if
396447 # necessary.
397 #
448 #
398449 sub _resultset {
399450 my $self = shift;
400451
44
55 use DBIx::Class::ResultSet;
66 use DBIx::Class::ResultSourceHandle;
7
8 use DBIx::Class::Exception;
79 use Carp::Clan qw/^DBIx::Class/;
810
911 use base qw/DBIx::Class/;
11931195
11941196 # Returns the {from} structure used to express JOIN conditions
11951197 sub _resolve_join {
1196 my ($self, $join, $alias, $seen, $jpath, $force_left) = @_;
1198 my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_;
11971199
11981200 # we need a supplied one, because we do in-place modifications, no returns
11991201 $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
12041206
12051207 $jpath = [@$jpath];
12061208
1207 if (ref $join eq 'ARRAY') {
1209 if (not defined $join) {
1210 return ();
1211 }
1212 elsif (ref $join eq 'ARRAY') {
12081213 return
12091214 map {
1210 $self->_resolve_join($_, $alias, $seen, $jpath, $force_left);
1215 $self->_resolve_join($_, $alias, $seen, $jpath, $parent_force_left);
12111216 } @$join;
1212 } elsif (ref $join eq 'HASH') {
1213 return
1214 map {
1215 my $as = ($seen->{$_} ? join ('_', $_, $seen->{$_} + 1) : $_); # the actual seen value will be incremented below
1216 local $force_left->{force} = $force_left->{force};
1217 (
1218 $self->_resolve_join($_, $alias, $seen, [@$jpath], $force_left),
1219 $self->related_source($_)->_resolve_join(
1220 $join->{$_}, $as, $seen, [@$jpath, $_], $force_left
1221 )
1222 );
1223 } keys %$join;
1224 } elsif (ref $join) {
1217 }
1218 elsif (ref $join eq 'HASH') {
1219
1220 my @ret;
1221 for my $rel (keys %$join) {
1222
1223 my $rel_info = $self->relationship_info($rel)
1224 or $self->throw_exception("No such relationship ${rel}");
1225
1226 my $force_left = $parent_force_left;
1227 $force_left ||= lc($rel_info->{attrs}{join_type}||'') eq 'left';
1228
1229 # the actual seen value will be incremented by the recursion
1230 my $as = ($seen->{$rel} ? join ('_', $rel, $seen->{$rel} + 1) : $rel);
1231
1232 push @ret, (
1233 $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left),
1234 $self->related_source($rel)->_resolve_join(
1235 $join->{$rel}, $as, $seen, [@$jpath, $rel], $force_left
1236 )
1237 );
1238 }
1239 return @ret;
1240
1241 }
1242 elsif (ref $join) {
12251243 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
1226 } else {
1227
1228 return() unless defined $join;
1229
1244 }
1245 else {
12301246 my $count = ++$seen->{$join};
12311247 my $as = ($count > 1 ? "${join}_${count}" : $join);
12321248
1233 my $rel_info = $self->relationship_info($join);
1234 $self->throw_exception("No such relationship ${join}") unless $rel_info;
1235 my $type;
1236 if ($force_left) {
1237 $type = 'left';
1238 }
1239 else {
1240 $type = $rel_info->{attrs}{join_type};
1241 $force_left = 1 if lc($type||'') eq 'left';
1242 }
1249 my $rel_info = $self->relationship_info($join)
1250 or $self->throw_exception("No such relationship ${join}");
12431251
12441252 my $rel_src = $self->related_source($join);
12451253 return [ { $as => $rel_src->from,
12461254 -source_handle => $rel_src->handle,
1247 -join_type => $type,
1255 -join_type => $parent_force_left
1256 ? 'left'
1257 : $rel_info->{attrs}{join_type}
1258 ,
12481259 -join_path => [@$jpath, $join],
12491260 -alias => $as,
12501261 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
13211332 #warn "$self $k $for $v";
13221333 unless ($for->has_column_loaded($v)) {
13231334 if ($for->in_storage) {
1324 $self->throw_exception(
1325 "Column ${v} not loaded or not passed to new() prior to insert()"
1326 ." on ${for} trying to resolve relationship (maybe you forgot "
1327 ."to call ->discard_changes to get defaults from the db)"
1335 $self->throw_exception(sprintf
1336 'Unable to resolve relationship from %s to %s: column %s.%s not '
1337 . 'loaded from storage (or not passed to new() prior to insert()). '
1338 . 'Maybe you forgot to call ->discard_changes to get defaults from the db.',
1339
1340 $for->result_source->source_name,
1341 $as,
1342 $as, $v,
13281343 );
13291344 }
13301345 return $UNRESOLVABLE_CONDITION;
14341449 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
14351450 $pref_path ||= [];
14361451
1437 if( ref $pre eq 'ARRAY' ) {
1452 if (not defined $pre) {
1453 return ();
1454 }
1455 elsif( ref $pre eq 'ARRAY' ) {
14381456 return
14391457 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
14401458 @$pre;
14571475 $p = $p->{$_} for (@$pref_path, $pre);
14581476
14591477 $self->throw_exception (
1460 "Unable to resolve prefetch $pre - join alias map does not contain an entry for path: "
1478 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
14611479 . join (' -> ', @$pref_path, $pre)
14621480 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
14631481
15741592
15751593 sub throw_exception {
15761594 my $self = shift;
1595
15771596 if (defined $self->schema) {
15781597 $self->schema->throw_exception(@_);
1579 } else {
1580 croak(@_);
1598 }
1599 else {
1600 DBIx::Class::Exception->throw(@_);
15811601 }
15821602 }
15831603
105105 $self->{schema} = $rs->schema if $rs;
106106 }
107107
108 carp "Unable to restore schema" unless $self->{schema};
108 carp "Unable to restore schema. Look at 'freeze' and 'thaw' methods in DBIx::Class::Schema."
109 unless $self->{schema};
109110 }
110111
111112 =head1 AUTHOR
33 use warnings;
44
55 use base qw/DBIx::Class/;
6 use Carp::Clan qw/^DBIx::Class/;
6
7 use DBIx::Class::Exception;
78 use Scalar::Util ();
8 use Scope::Guard;
99
1010 ###
1111 ### Internal method
167167 foreach my $key (keys %$attrs) {
168168 if (ref $attrs->{$key}) {
169169 ## Can we extract this lot to use with update(_or .. ) ?
170 confess "Can't do multi-create without result source" unless $source;
170 $new->throw_exception("Can't do multi-create without result source")
171 unless $source;
171172 my $info = $source->relationship_info($key);
172173 if ($info && $info->{attrs}{accessor}
173174 && $info->{attrs}{accessor} eq 'single')
13291330
13301331 sub throw_exception {
13311332 my $self=shift;
1333
13321334 if (ref $self && ref $self->result_source && $self->result_source->schema) {
1333 $self->result_source->schema->throw_exception(@_);
1334 } else {
1335 croak(@_);
1335 $self->result_source->schema->throw_exception(@_)
1336 }
1337 else {
1338 DBIx::Class::Exception->throw(@_);
13361339 }
13371340 }
13381341
519519 return;
520520 }
521521
522 $self->throw_exception($self->_sqlt_version_error)
523 if (not $self->_sqlt_version_ok);
524
525 my $db_tr = SQL::Translator->new({
526 add_drop_table => 1,
522 $self->throw_exception($self->storage->_sqlt_version_error)
523 if (not $self->storage->_sqlt_version_ok);
524
525 my $db_tr = SQL::Translator->new({
526 add_drop_table => 1,
527527 parser => 'DBI',
528528 parser_args => { dbh => $self->storage->dbh }
529529 });
6060 }
6161
6262
63 =head1 AUTHORS
63 =head1 AUTHOR
6464
6565 See L<DBIx::Class/CONTRIBUTORS>
6666
33 use warnings;
44
55 use base qw/DBIx::Class::Cursor/;
6
7 __PACKAGE__->mk_group_accessors('simple' =>
8 qw/sth/
9 );
610
711 =head1 NAME
812
7276 && $self->{attrs}{rows}
7377 && $self->{pos} >= $self->{attrs}{rows}
7478 ) {
75 $self->{sth}->finish if $self->{sth}->{Active};
76 delete $self->{sth};
79 $self->sth->finish if $self->sth->{Active};
80 $self->sth(undef);
7781 $self->{done} = 1;
7882 }
7983 return if $self->{done};
80 unless ($self->{sth}) {
81 $self->{sth} = ($storage->_select(@{$self->{args}}))[1];
84 unless ($self->sth) {
85 $self->sth(($storage->_select(@{$self->{args}}))[1]);
8286 if ($self->{attrs}{software_limit}) {
8387 if (my $offset = $self->{attrs}{offset}) {
84 $self->{sth}->fetch for 1 .. $offset;
88 $self->sth->fetch for 1 .. $offset;
8589 }
8690 }
8791 }
88 my @row = $self->{sth}->fetchrow_array;
92 my @row = $self->sth->fetchrow_array;
8993 if (@row) {
9094 $self->{pos}++;
9195 } else {
92 delete $self->{sth};
96 $self->sth(undef);
9397 $self->{done} = 1;
9498 }
9599 return @row;
119123 my ($storage, $dbh, $self) = @_;
120124
121125 $self->_check_dbh_gen;
122 $self->{sth}->finish if $self->{sth}->{Active};
123 delete $self->{sth};
126 $self->sth->finish if $self->sth && $self->sth->{Active};
127 $self->sth(undef);
124128 my ($rv, $sth) = $storage->_select(@{$self->{args}});
125129 return @{$sth->fetchall_arrayref};
126130 }
145149 my ($self) = @_;
146150
147151 # No need to care about failures here
148 eval { $self->{sth}->finish if $self->{sth} && $self->{sth}->{Active} };
152 eval { $self->sth->finish if $self->sth && $self->sth->{Active} };
149153 $self->_soft_reset;
154 return undef;
150155 }
151156
152157 sub _soft_reset {
153158 my ($self) = @_;
154159
155 delete $self->{sth};
160 $self->sth(undef);
156161 delete $self->{done};
157162 $self->{pos} = 0;
158 return $self;
159163 }
160164
161165 sub _check_dbh_gen {
172176
173177 # None of the reasons this would die matter if we're in DESTROY anyways
174178 local $@;
175 eval { $self->{sth}->finish if $self->{sth} && $self->{sth}->{Active} };
179 eval { $self->sth->finish if $self->sth && $self->sth->{Active} };
176180 }
177181
178182 1;
3131 }
3232 }
3333
34 sub _unset_identity_insert {
35 my ($self, $table) = @_;
36
37 my $sql = sprintf (
38 'SET IDENTITY_INSERT %s OFF',
39 $self->sql_maker->_quote ($table),
40 );
41
42 my $dbh = $self->_get_dbh;
43 $dbh->do ($sql);
44 }
45
3446 sub insert_bulk {
3547 my $self = shift;
3648 my ($source, $cols, $data) = @_;
3749
38 if (List::Util::first
50 my $is_identity_insert = (List::Util::first
3951 { $source->column_info ($_)->{is_auto_increment} }
4052 (@{$cols})
41 ) {
42 $self->_set_identity_insert ($source->name);
53 )
54 ? 1
55 : 0;
56
57 if ($is_identity_insert) {
58 $self->_set_identity_insert ($source->name);
4359 }
4460
4561 $self->next::method(@_);
62
63 if ($is_identity_insert) {
64 $self->_unset_identity_insert ($source->name);
65 }
4666 }
4767
4868 # support MSSQL GUID column types
82102 $updated_cols->{$guid_col} = $to_insert->{$guid_col} = $new_guid;
83103 }
84104
85 if (List::Util::first { $_->{is_auto_increment} } (values %$supplied_col_info) ) {
86 $self->_set_identity_insert ($source->name);
105 my $is_identity_insert = (List::Util::first { $_->{is_auto_increment} } (values %$supplied_col_info) )
106 ? 1
107 : 0;
108
109 if ($is_identity_insert) {
110 $self->_set_identity_insert ($source->name);
87111 }
88112
89113 $updated_cols = { %$updated_cols, %{ $self->next::method(@_) } };
114
115 if ($is_identity_insert) {
116 $self->_unset_identity_insert ($source->name);
117 }
118
90119
91120 return $updated_cols;
92121 }
3939 sub _prep_for_execute {
4040 my $self = shift;
4141
42 my ($op, $extra_bind, $ident) = @_;
43
4442 my ($sql, $bind) = $self->next::method(@_);
4543
46 # stringify args, quote via $dbh, and manually insert
44 # stringify bind args, quote via $dbh, and manually insert
45 #my ($op, $extra_bind, $ident, $args) = @_;
46 my $ident = $_[2];
4747
4848 my @sql_part = split /\?/, $sql;
4949 my $new_sql;
5050
51 my $col_info = $self->_resolve_column_info($ident, [ map $_->[0], @$bind ]);
52
5153 foreach my $bound (@$bind) {
5254 my $col = shift @$bound;
53 my $datatype = 'FIXME!!!';
55
56 my $datatype = $col_info->{$col}{data_type};
57
5458 foreach my $data (@$bound) {
55 if(ref $data) {
56 $data = ''.$data;
57 }
58 $data = $self->_dbh->quote($data);
59 $new_sql .= shift(@sql_part) . $data;
59 $data = ''.$data if ref $data;
60
61 $data = $self->_prep_interpolated_value($datatype, $data)
62 if $datatype;
63
64 $data = $self->_dbh->quote($data)
65 unless $self->interpolate_unquoted($datatype, $data);
66
67 $new_sql .= shift(@sql_part) . $data;
6068 }
6169 }
6270 $new_sql .= join '', @sql_part;
6472 return ($new_sql, []);
6573 }
6674
75 =head2 interpolate_unquoted
76
77 This method is called by L</_prep_for_execute> for every column in
78 order to determine if its value should be quoted or not. The arguments
79 are the current column data type and the actual bind value. The return
80 value is interpreted as: true - do not quote, false - do quote. You should
81 override this in you Storage::DBI::<database> subclass, if your RDBMS
82 does not like quotes around certain datatypes (e.g. Sybase and integer
83 columns). The default method always returns false (do quote).
84
85 WARNING!!!
86
87 Always validate that the bind-value is valid for the current datatype.
88 Otherwise you may very well open the door to SQL injection attacks.
89
90 =cut
91
92 sub interpolate_unquoted {
93 #my ($self, $datatype, $value) = @_;
94 return 0;
95 }
96
97 =head2 _prep_interpolated_value
98
99 Given a datatype and the value to be inserted directly into a SQL query, returns
100 the necessary string to represent that value (by e.g. adding a '$' sign)
101
102 =cut
103
104 sub _prep_interpolated_value {
105 #my ($self, $datatype, $value) = @_;
106 return $_[2];
107 }
108
67109 =head1 AUTHORS
68110
69 Brandon Black <blblack@gmail.com>
70
71 Trym Skaar <trym@tryms.no>
111 See L<DBIx::Class/CONTRIBUTORS>
72112
73113 =head1 LICENSE
74114
44 use base qw/DBIx::Class::Storage::DBI::MSSQL/;
55 use mro 'c3';
66
7 use Carp::Clan qw/^DBIx::Class/;
87 use List::Util();
98 use Scalar::Util ();
109
6160 my $self = shift;
6261
6362 if (ref($self->_dbi_connect_info->[0]) eq 'CODE') {
64 croak 'cannot set DBI attributes on a CODE ref connect_info';
63 $self->throw_exception ('cannot set DBI attributes on a CODE ref connect_info');
6564 }
6665
6766 my $dbi_attrs = $self->_dbi_connect_info->[-1];
9089 $dbh->do('SELECT @@IDENTITY');
9190 };
9291 if ($@) {
93 croak <<'EOF';
92 $self->throw_exception (<<'EOF');
9493
9594 Your drivers do not seem to support dynamic cursors (odbc_cursortype => 2),
9695 if you're using FreeTDS, make sure to set tds_version to 8.0 or greater.
101100 $self->_identity_method('@@identity');
102101 }
103102
104 sub _rebless {
105 no warnings 'uninitialized';
103 sub _init {
106104 my $self = shift;
107105
108 if (ref($self->_dbi_connect_info->[0]) ne 'CODE' &&
109 eval { $self->_dbi_connect_info->[-1]{odbc_cursortype} } == 2) {
106 no warnings qw/uninitialized/;
107
108 if (
109 ref($self->_dbi_connect_info->[0]) ne 'CODE'
110 &&
111 ref ($self->_dbi_connect_info->[-1]) eq 'HASH'
112 &&
113 $self->_dbi_connect_info->[-1]{odbc_cursortype} == 2
114 ) {
110115 $self->_set_dynamic_cursors;
111116 return;
112117 }
158163 my $dsn = $self->_dbi_connect_info->[0];
159164
160165 if (ref($dsn) eq 'CODE') {
161 croak 'cannot change the DBI DSN on a CODE ref connect_info';
166 $self->throw_exception('cannot change the DBI DSN on a CODE ref connect_info');
162167 }
163168
164169 if ($dsn !~ /MARS_Connection=/) {
205205 "alter session set nls_timestamp_tz_format='$timestamp_tz_format'");
206206 }
207207
208 sub _svp_begin {
209 my ($self, $name) = @_;
210
211 $self->_get_dbh->do("SAVEPOINT $name");
212 }
213
214208 =head2 source_bind_attributes
215209
216210 Handle LOB types in Oracle. Under a certain size (4k?), you can get away
255249 return \%bind_attributes;
256250 }
257251
252 sub _svp_begin {
253 my ($self, $name) = @_;
254
255 $self->_get_dbh->do("SAVEPOINT $name");
256 }
257
258258 # Oracle automatically releases a savepoint when you start another one with the
259259 # same name.
260260 sub _svp_release { 1 }
1818 ? 'DBIx::Class::Storage::DBI::Oracle::WhereJoins'
1919 : 'DBIx::Class::Storage::DBI::Oracle::Generic';
2020
21 # Load and rebless
22 eval "require $class";
23
24 bless $self, $class unless $@;
21 $self->ensure_class_loaded ($class);
22 bless $self, $class;
2523 }
2624 }
2725
1919 }
2020
2121 sub last_insert_id {
22 my ($self,$source,$col) = @_;
23 my $seq = ( $source->column_info($col)->{sequence} ||= $self->dbh_do('_dbh_get_autoinc_seq', $source, $col) )
22 my ($self,$source,@cols) = @_;
23
24 my @values;
25
26 for my $col (@cols) {
27 my $seq = ( $source->column_info($col)->{sequence} ||= $self->dbh_do('_dbh_get_autoinc_seq', $source, $col) )
2428 or $self->throw_exception( "could not determine sequence for "
2529 . $source->name
2630 . ".$col, please consider adding a "
2731 . "schema-qualified sequence to its column info"
2832 );
2933
30 $self->_dbh_last_insert_id ($self->_dbh, $seq);
34 push @values, $self->_dbh_last_insert_id ($self->_dbh, $seq);
35 }
36
37 return @values;
3138 }
3239
3340 # there seems to be absolutely no reason to have this as a separate method,
1616 my @didnt_load;
1717
1818 for my $module (keys %replication_required) {
19 eval "use $module $replication_required{$module}";
20 push @didnt_load, "$module $replication_required{$module}"
21 if $@;
19 eval "use $module $replication_required{$module}";
20 push @didnt_load, "$module $replication_required{$module}"
21 if $@;
2222 }
2323
2424 croak("@{[ join ', ', @didnt_load ]} are missing and are required for Replication")
3232 use DBIx::Class::Storage::DBI::Replicated::Types qw/BalancerClassNamePart DBICSchema DBICStorageDBI/;
3333 use MooseX::Types::Moose qw/ClassName HashRef Object/;
3434 use Scalar::Util 'reftype';
35 use Carp::Clan qw/^DBIx::Class/;
3635 use Hash::Merge 'merge';
3736
3837 use namespace::clean -except => 'meta';
221220 isa=>'DBIx::Class::Storage::DBI::Replicated::Pool',
222221 lazy_build=>1,
223222 handles=>[qw/
224 connect_replicants
223 connect_replicants
225224 replicants
226225 has_replicants
227226 /],
276275 select
277276 select_single
278277 columns_info_for
279 /],
278 /],
280279 );
281280
282281 =head2 write_handler
289288 is=>'ro',
290289 isa=>Object,
291290 lazy_build=>1,
292 handles=>[qw/
291 handles=>[qw/
293292 on_connect_do
294 on_disconnect_do
293 on_disconnect_do
295294 connect_info
296295 throw_exception
297296 sql_maker
299298 create_ddl_dir
300299 deployment_statements
301300 datetime_parser
302 datetime_parser_type
303 build_datetime_parser
301 datetime_parser_type
302 build_datetime_parser
304303 last_insert_id
305304 insert
306305 insert_bulk
315314 sth
316315 deploy
317316 with_deferred_fk_checks
318 dbh_do
317 dbh_do
319318 reload_row
320 with_deferred_fk_checks
319 with_deferred_fk_checks
321320 _prep_for_execute
322321
323 backup
324 is_datatype_numeric
325 _count_select
326 _subq_count_select
327 _subq_update_delete
328 svp_rollback
329 svp_begin
330 svp_release
322 backup
323 is_datatype_numeric
324 _count_select
325 _subq_count_select
326 _subq_update_delete
327 svp_rollback
328 svp_begin
329 svp_release
331330 /],
332331 );
333332
363362 );
364363
365364 $self->pool($self->_build_pool)
366 if $self->pool;
365 if $self->pool;
367366 }
368367
369368 if (@opts{qw/balancer_type balancer_args/}) {
375374 );
376375
377376 $self->balancer($self->_build_balancer)
378 if $self->balancer;
377 if $self->balancer;
379378 }
380379
381380 $self->_master_connect_info_opts(\%opts);
412411 my ($class, $schema, $storage_type_args, @args) = @_;
413412
414413 return {
415 schema=>$schema,
416 %$storage_type_args,
417 @args
414 schema=>$schema,
415 %$storage_type_args,
416 @args
418417 }
419418 }
420419
451450 sub _build_balancer {
452451 my $self = shift @_;
453452 $self->create_balancer(
454 pool=>$self->pool,
453 pool=>$self->pool,
455454 master=>$self->master,
456455 %{$self->balancer_args},
457456 );
493492 for my $r (@args) {
494493 $r = [ $r ] unless reftype $r eq 'ARRAY';
495494
496 croak "coderef replicant connect_info not supported"
495 $self->throw_exception('coderef replicant connect_info not supported')
497496 if ref $r->[0] && reftype $r->[0] eq 'CODE';
498497
499498 # any connect_info options?
500499 my $i = 0;
501500 $i++ while $i < @$r && (reftype($r->[$i])||'') ne 'HASH';
502501
503 # make one if none
502 # make one if none
504503 $r->[$i] = {} unless $r->[$i];
505504
506505 # merge if two hashes
507506 my @hashes = @$r[$i .. $#{$r}];
508507
509 croak "invalid connect_info options"
508 $self->throw_exception('invalid connect_info options')
510509 if (grep { reftype($_) eq 'HASH' } @hashes) != @hashes;
511510
512 croak "too many hashrefs in connect_info"
511 $self->throw_exception('too many hashrefs in connect_info')
513512 if @hashes > 2;
514513
515514 my %opts = %{ merge(reverse @hashes) };
599598 ($result[0]) = ($coderef->(@args));
600599 } else {
601600 $coderef->(@args);
602 }
601 }
603602 };
604603
605604 ##Reset to the original state
606 $self->read_handler($current);
605 $self->read_handler($current);
607606
608607 ##Exception testing has to come last, otherwise you might leave the
609608 ##read_handler set to master.
737736 if(@_) {
738737 foreach my $source ($self->all_storages) {
739738 $source->debug(@_);
740 }
739 }
741740 }
742741 return $self->master->debug;
743742 }
753752 if(@_) {
754753 foreach my $source ($self->all_storages) {
755754 $source->debugobj(@_);
756 }
755 }
757756 }
758757 return $self->master->debugobj;
759758 }
769768 if(@_) {
770769 foreach my $source ($self->all_storages) {
771770 $source->debugfh(@_);
772 }
771 }
773772 }
774773 return $self->master->debugfh;
775774 }
785784 if(@_) {
786785 foreach my $source ($self->all_storages) {
787786 $source->debugcb(@_);
788 }
787 }
789788 }
790789 return $self->master->debugcb;
791790 }
88 /;
99 use mro 'c3';
1010
11 sub _rebless {
11 sub _init {
1212 my $self = shift;
13
1413 $self->disable_sth_caching(1);
1514 }
1615
1212 my $self = shift;
1313 my $dbh = $self->_get_dbh;
1414
15 if (not $self->_placeholders_supported) {
15 if (not $self->_typeless_placeholders_supported) {
1616 bless $self,
1717 'DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server::NoBindVars';
1818 $self->_rebless;
1212 use DBIx::Class::Storage::Statistics;
1313 use Scalar::Util();
1414 use List::Util();
15
16 # what version of sqlt do we require if deploy() without a ddl_dir is invoked
17 # when changing also adjust the corresponding author_require in Makefile.PL
18 my $minimum_sqlt_version = '0.11002';
19
1520
1621 __PACKAGE__->mk_group_accessors('simple' =>
1722 qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid
680685
681686 $self->_do_connection_actions(disconnect_call_ => $_) for @actions;
682687
683 $self->_dbh->rollback unless $self->_dbh_autocommit;
688 $self->_dbh_rollback unless $self->_dbh_autocommit;
689
684690 $self->_dbh->disconnect;
685691 $self->_dbh(undef);
686692 $self->{_dbh_gen}++;
834840 return $self->_sql_maker;
835841 }
836842
843 # nothing to do by default
837844 sub _rebless {}
845 sub _init {}
838846
839847 sub _populate_dbh {
840848 my ($self) = @_;
901909
902910 $self->_driver_determined(1);
903911
912 $self->_init; # run driver-specific initializations
913
904914 $self->_run_connection_actions
905915 if $started_unconnected && defined $self->_dbh;
906916 }
9961006 $weak_self->throw_exception("DBI Exception: $_[0]");
9971007 }
9981008 else {
1009 # the handler may be invoked by something totally out of
1010 # the scope of DBIC
9991011 croak ("DBI Exception: $_[0]");
10001012 }
10011013 };
11051117 if($self->{transaction_depth} == 0) {
11061118 $self->debugobj->txn_begin()
11071119 if $self->debug;
1108
1109 # being here implies we have AutoCommit => 1
1110 # if the user is utilizing txn_do - good for
1111 # him, otherwise we need to ensure that the
1112 # $dbh is healthy on BEGIN
1113 my $dbh_method = $self->{_in_dbh_do} ? '_dbh' : 'dbh';
1114 $self->$dbh_method->begin_work;
1115
1116 } elsif ($self->auto_savepoint) {
1120 $self->_dbh_begin_work;
1121 }
1122 elsif ($self->auto_savepoint) {
11171123 $self->svp_begin;
11181124 }
11191125 $self->{transaction_depth}++;
1126 }
1127
1128 sub _dbh_begin_work {
1129 my $self = shift;
1130
1131 # if the user is utilizing txn_do - good for him, otherwise we need to
1132 # ensure that the $dbh is healthy on BEGIN.
1133 # We do this via ->dbh_do instead of ->dbh, so that the ->dbh "ping"
1134 # will be replaced by a failure of begin_work itself (which will be
1135 # then retried on reconnect)
1136 if ($self->{_in_dbh_do}) {
1137 $self->_dbh->begin_work;
1138 } else {
1139 $self->dbh_do(sub { $_[1]->begin_work });
1140 }
11201141 }
11211142
11221143 sub txn_commit {
11251146 my $dbh = $self->_dbh;
11261147 $self->debugobj->txn_commit()
11271148 if ($self->debug);
1128 $dbh->commit;
1149 $self->_dbh_commit;
11291150 $self->{transaction_depth} = 0
11301151 if $self->_dbh_autocommit;
11311152 }
11341155 $self->svp_release
11351156 if $self->auto_savepoint;
11361157 }
1158 }
1159
1160 sub _dbh_commit {
1161 my $self = shift;
1162 $self->_dbh->commit;
11371163 }
11381164
11391165 sub txn_rollback {
11451171 if ($self->debug);
11461172 $self->{transaction_depth} = 0
11471173 if $self->_dbh_autocommit;
1148 $dbh->rollback;
1174 $self->_dbh_rollback;
11491175 }
11501176 elsif($self->{transaction_depth} > 1) {
11511177 $self->{transaction_depth}--;
11661192 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
11671193 $self->throw_exception($error);
11681194 }
1195 }
1196
1197 sub _dbh_rollback {
1198 my $self = shift;
1199 $self->_dbh->rollback;
11691200 }
11701201
11711202 # This used to be the top-half of _execute. It was split out to make it
13741405 }
13751406
13761407 sub update {
1377 my $self = shift @_;
1378 my $source = shift @_;
1379 $self->_determine_driver;
1408 my ($self, $source, @args) = @_;
1409
1410 # redispatch to update method of storage we reblessed into, if necessary
1411 if (not $self->_driver_determined) {
1412 $self->_determine_driver;
1413 goto $self->can('update');
1414 }
1415
13801416 my $bind_attributes = $self->source_bind_attributes($source);
13811417
1382 return $self->_execute('update' => [], $source, $bind_attributes, @_);
1418 return $self->_execute('update' => [], $source, $bind_attributes, @args);
13831419 }
13841420
13851421
21532189 return undef
21542190 }
21552191
2192 # Check if placeholders are supported at all
2193 sub _placeholders_supported {
2194 my $self = shift;
2195 my $dbh = $self->_get_dbh;
2196
2197 # some drivers provide a $dbh attribute (e.g. Sybase and $dbh->{syb_dynamic_supported})
2198 # but it is inaccurate more often than not
2199 eval {
2200 local $dbh->{PrintError} = 0;
2201 local $dbh->{RaiseError} = 1;
2202 $dbh->do('select ?', {}, 1);
2203 };
2204 return $@ ? 0 : 1;
2205 }
2206
2207 # Check if placeholders bound to non-string types throw exceptions
2208 #
2209 sub _typeless_placeholders_supported {
2210 my $self = shift;
2211 my $dbh = $self->_get_dbh;
2212
2213 eval {
2214 local $dbh->{PrintError} = 0;
2215 local $dbh->{RaiseError} = 1;
2216 # this specifically tests a bind that is NOT a string
2217 $dbh->do('select 1 where 1 = ?', {}, 1);
2218 };
2219 return $@ ? 0 : 1;
2220 }
2221
21562222 =head2 sqlt_type
21572223
21582224 Returns the database driver name.
25442610 return;
25452611 }
25462612
2613 # SQLT version handling
2614 {
2615 my $_sqlt_version_ok; # private
2616 my $_sqlt_version_error; # private
2617
2618 sub _sqlt_version_ok {
2619 if (!defined $_sqlt_version_ok) {
2620 eval "use SQL::Translator $minimum_sqlt_version";
2621 if ($@) {
2622 $_sqlt_version_ok = 0;
2623 $_sqlt_version_error = $@;
2624 }
2625 else {
2626 $_sqlt_version_ok = 1;
2627 }
2628 }
2629 return $_sqlt_version_ok;
2630 }
2631
2632 sub _sqlt_version_error {
2633 shift->_sqlt_version_ok unless defined $_sqlt_version_ok;
2634 return $_sqlt_version_error;
2635 }
2636
2637 sub _sqlt_minimum_version { $minimum_sqlt_version };
2638 }
2639
25472640 sub DESTROY {
25482641 my $self = shift;
25492642
11 use strict;
22 use warnings;
33
4 use base qw/Class::Accessor::Grouped/;
4 use base qw/DBIx::Class/;
55 use IO::File;
66
77 __PACKAGE__->mk_group_accessors(simple => qw/callback debugfh silence/);
11
22 use strict;
33 use warnings;
4 use Carp ();
4 use Carp::Clan qw/^DBIx::Class/;
55
66 sub new {
77 my ($class, $storage) = @_;
2323 return if $dismiss;
2424
2525 my $exception = $@;
26 Carp::cluck("A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or an error - bad")
27 unless $exception;
26
2827 {
2928 local $@;
29
30 carp 'A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back.'
31 unless $exception;
32
3033 eval { $storage->txn_rollback };
3134 my $rollback_exception = $@;
32 if($rollback_exception) {
33 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
3435
35 $storage->throw_exception(
36 "Transaction aborted: ${exception}. "
37 . "Rollback failed: ${rollback_exception}"
38 ) unless $rollback_exception =~ /$exception_class/;
36 if ($rollback_exception && $rollback_exception !~ /DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION/) {
37 if ($exception) {
38 $exception = "Transaction aborted: ${exception} "
39 ."Rollback failed: ${rollback_exception}";
40 }
41 else {
42 carp (join ' ',
43 "********************* ROLLBACK FAILED!!! ********************",
44 "\nA rollback operation failed after the guard went out of scope.",
45 'This is potentially a disastrous situation, check your data for',
46 "consistency: $rollback_exception"
47 );
48 }
3949 }
4050 }
51
52 $@ = $exception;
4153 }
4254
4355 1;
55 use base qw/DBIx::Class/;
66 use mro 'c3';
77
8 use Scalar::Util qw/weaken/;
9 use Carp::Clan qw/^DBIx::Class/;
8 use DBIx::Class::Exception;
9 use Scalar::Util();
1010 use IO::File;
1111 use DBIx::Class::Storage::TxnScopeGuard;
1212
8282 sub set_schema {
8383 my ($self, $schema) = @_;
8484 $self->schema($schema);
85 weaken($self->{schema}) if ref $self->{schema};
85 Scalar::Util::weaken($self->{schema}) if ref $self->{schema};
8686 }
8787
8888 =head2 connected
119119 sub throw_exception {
120120 my $self = shift;
121121
122 $self->schema->throw_exception(@_) if $self->schema;
123 croak @_;
122 if ($self->schema) {
123 $self->schema->throw_exception(@_);
124 }
125 else {
126 DBIx::Class::Exception->throw(@_);
127 }
124128 }
125129
126130 =head2 txn_do
55 use MRO::Compat;
66
77 use vars qw($VERSION);
8 use base qw/DBIx::Class::Componentised Class::Accessor::Grouped/;
8 use base qw/Class::C3::Componentised Class::Accessor::Grouped/;
99 use DBIx::Class::StartupCheck;
1010
1111 sub mk_classdata {
2323 # Always remember to do all digits for the version even if they're 0
2424 # i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports
2525 # brain damage and presumably various other packaging systems too
26
27 $VERSION = '0.08111';
26 $VERSION = '0.08112';
2827
2928 $VERSION = eval $VERSION; # numify for warning-free dev releases
30
31 # what version of sqlt do we require if deploy() without a ddl_dir is invoked
32 # when changing also adjust $sqlt_recommends in Makefile.PL
33 my $minimum_sqlt_version = '0.11002';
3429
3530 sub MODIFY_CODE_ATTRIBUTES {
3631 my ($class,$code,@attrs) = @_;
4641 my $rest = eval { $self->next::method };
4742 return $@ ? $cache : { %$cache, %$rest };
4843 }
49
50 # SQLT version handling
51 {
52 my $_sqlt_version_ok; # private
53 my $_sqlt_version_error; # private
54
55 sub _sqlt_version_ok {
56 if (!defined $_sqlt_version_ok) {
57 eval "use SQL::Translator $minimum_sqlt_version";
58 if ($@) {
59 $_sqlt_version_ok = 0;
60 $_sqlt_version_error = $@;
61 }
62 else {
63 $_sqlt_version_ok = 1;
64 }
65 }
66 return $_sqlt_version_ok;
67 }
68
69 sub _sqlt_version_error {
70 shift->_sqlt_version_ok unless defined $_sqlt_version_ok;
71 return $_sqlt_version_error;
72 }
73
74 sub _sqlt_minimum_version { $minimum_sqlt_version };
75 }
76
7744
7845 1;
7946
261228
262229 bricas: Brian Cassidy <bricas@cpan.org>
263230
231 brunov: Bruno Vecchi <vecchi.b@gmail.com>
232
264233 caelum: Rafael Kitover <rkitover@cpan.org>
265234
266235 castaway: Jess Robinson
55
66 use lib qw(t/lib);
77 use DBICTest::ForeignComponent;
8
9 plan tests => 6;
108
119 # Tests if foreign component was loaded by calling foreign's method
1210 ok( DBICTest::ForeignComponent->foreign_test_method, 'foreign component' );
3432 'inject_base filters duplicates'
3533 );
3634
37 # Test for a warning with incorrect order in load_components
38 my @warnings = ();
39 {
40 package A::Test;
41 our @ISA = 'DBIx::Class';
42 {
43 local $SIG{__WARN__} = sub { push @warnings, shift};
44 __PACKAGE__->load_components(qw(Core UTF8Columns));
45 }
46 }
47 like( $warnings[0], qr/Core loaded before UTF8Columns/,
48 'warning issued for incorrect order in load_components()' );
49 is( scalar @warnings, 1,
50 'only one warning issued for incorrect load_components call' );
35 use_ok('DBIx::Class::AccessorGroup');
36 use_ok('DBIx::Class::Componentised');
5137
52 # Test that no warning is issued for the correct order in load_components
53 {
54 @warnings = ();
55 package B::Test;
56 our @ISA = 'DBIx::Class';
57 {
58 local $SIG{__WARN__} = sub { push @warnings, shift };
59 __PACKAGE__->load_components(qw(UTF8Columns Core));
60 }
61 }
62 is( scalar @warnings, 0,
63 'warning not issued for correct order in load_components()' );
64
65 use_ok('DBIx::Class::AccessorGroup');
38 done_testing;
22
33 use Test::More;
44 use Test::Exception;
5 use Test::Warn;
56 use lib qw(t/lib);
67 use DBICTest;
78 use DBIC::SqlMakerTest;
3435 my %not_dirty = $art->get_dirty_columns();
3536 is(scalar(keys(%not_dirty)), 0, 'Nothing is dirty');
3637
37 eval {
38 throws_ok ( sub {
3839 my $ret = $art->make_column_dirty('name2');
39 };
40 ok(defined($@), 'Failed to make non-existent column dirty');
40 }, qr/No such column 'name2'/, 'Failed to make non-existent column dirty');
41
4142 $art->make_column_dirty('name');
4243 my %fake_dirty = $art->get_dirty_columns();
4344 is(scalar(keys(%fake_dirty)), 1, '1 fake dirty column');
107108 {
108109 ok(my $artist = $schema->resultset('Artist')->create({name => 'store_column test'}));
109110 is($artist->name, 'X store_column test'); # used to be 'X X store...'
111
112 # call store_column even though the column doesn't seem to be dirty
113 ok($artist->update({name => 'X store_column test'}));
114 is($artist->name, 'X X store_column test');
110115 $artist->delete;
111116 }
112117
216221 isa_ok($tdata{'last_updated_on'}, 'DateTime', 'inflated accessored column');
217222 }
218223
219 eval { $schema->class("Track")->load_components('DoesNotExist'); };
220
221 ok $@, $@;
224 throws_ok (sub {
225 $schema->class("Track")->load_components('DoesNotExist');
226 }, qr!Can't locate DBIx/Class/DoesNotExist.pm!, 'exception on nonexisting component');
222227
223228 is($schema->class("Artist")->field_name_for->{name}, 'artist name', 'mk_classdata usage ok');
224229
232237 my $collapsed_or_rs = $or_rs->search ({}, { distinct => 1 }); # induce collapse
233238 is ($collapsed_or_rs->all, 4, 'Collapsed joined search with OR returned correct number of rows');
234239 is ($collapsed_or_rs->count, 4, 'Collapsed search count with OR ok');
240
241 # make sure sure distinct on a grouped rs is warned about
242 my $cd_rs = $schema->resultset ('CD')
243 ->search ({}, { distinct => 1, group_by => 'title' });
244 warnings_exist (sub {
245 $cd_rs->next;
246 }, qr/Useless use of distinct/, 'UUoD warning');
235247
236248 {
237249 my $tcount = $schema->resultset('Track')->search(
00 use strict;
1 use warnings;
1 use warnings;
22
33 use Test::More;
44 use Test::Exception;
00 use strict;
1 use warnings;
1 use warnings;
22
33 use Test::More;
44 use lib qw(t/lib);
55 use DBICTest;
6 use DBIC::SqlMakerTest;
7 use DBIC::DebugObj;
68
79 my $schema = DBICTest->init_schema();
8
9 plan tests => 49;
1010
1111 # Check the defined unique constraints
1212 is_deeply(
208208 );
209209 ok($cd2->in_storage, 'Updating year using update_or_new was successful');
210210 is($cd2->id, $cd1->id, 'Got the same CD using update_or_new');
211 }
211 }
212
213 # make sure the ident condition is assembled sanely
214 {
215 my $artist = $schema->resultset('Artist')->next;
216
217 my ($sql, @bind);
218 $schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind)),
219 $schema->storage->debug(1);
220
221 $artist->discard_changes;
222
223 is_same_sql_bind (
224 $sql,
225 \@bind,
226 'SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me WHERE me.artistid = ?',
227 [qw/'1'/],
228 );
229
230 $schema->storage->debug(0);
231 $schema->storage->debugobj(undef);
232 }
233
234 done_testing;
00 use strict;
1 use warnings;
1 use warnings;
22
33 use Test::More;
4 use Test::Warn;
45 use Test::Exception;
56 use lib qw(t/lib);
67 use DBICTest;
78
89 my $schema = DBICTest->init_schema();
910
10 plan tests => 64;
11
1211 my $code = sub {
1312 my ($artist, @cd_titles) = @_;
14
13
1514 $artist->create_related('cds', {
1615 title => $_,
1716 year => 2006,
1817 }) foreach (@cd_titles);
19
18
2019 return $artist->cds->all;
2120 };
2221
257256 name => 'Death Cab for Cutie',
258257 made_up_column => 1,
259258 });
260
259
261260 $guard->commit;
262261 } qr/No such column made_up_column .*? at .*?81transactions.t line \d+/s, "Error propogated okay";
263262
264263 ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
265264
266 my $inner_exception;
265 my $inner_exception; # set in inner() below
267266 eval {
268267 outer($schema, 1);
269268 };
272271 ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
273272
274273 lives_ok (sub {
275 my $w;
276 local $SIG{__WARN__} = sub { $w = shift };
277
278 # The 0 arg says don't die, just let the scope guard go out of scope
279 # forcing a txn_rollback to happen
280 outer($schema, 0);
281
282 like ($w, qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or an error/, 'Out of scope warning detected');
274 warnings_exist ( sub {
275 # The 0 arg says don't die, just let the scope guard go out of scope
276 # forcing a txn_rollback to happen
277 outer($schema, 0);
278 }, qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back./, 'Out of scope warning detected');
283279 ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
284280 }, 'rollback successful withot exception');
285281
318314 $inner_guard->commit;
319315 }
320316 }
317
318 # make sure the guard does not eat exceptions
319 {
320 my $schema = DBICTest->init_schema();
321 throws_ok (sub {
322 my $guard = $schema->txn_scope_guard;
323 $schema->resultset ('Artist')->create ({ name => 'bohhoo'});
324
325 $schema->storage->disconnect; # this should freak out the guard rollback
326
327 die 'Deliberate exception';
328 }, qr/Deliberate exception.+Rollback failed/s);
329 }
330
331 # make sure it warns *big* on failed rollbacks
332 {
333 my $schema = DBICTest->init_schema();
334
335 # something is really confusing Test::Warn here, no time to debug
336 =begin
337 warnings_exist (
338 sub {
339 my $guard = $schema->txn_scope_guard;
340 $schema->resultset ('Artist')->create ({ name => 'bohhoo'});
341
342 $schema->storage->disconnect; # this should freak out the guard rollback
343 },
344 [
345 qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back./,
346 qr/\*+ ROLLBACK FAILED\!\!\! \*+/,
347 ],
348 'proper warnings generated on out-of-scope+rollback failure'
349 );
350 =cut
351
352 my @want = (
353 qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back./,
354 qr/\*+ ROLLBACK FAILED\!\!\! \*+/,
355 );
356
357 my @w;
358 local $SIG{__WARN__} = sub {
359 if (grep {$_[0] =~ $_} (@want)) {
360 push @w, $_[0];
361 }
362 else {
363 warn $_[0];
364 }
365 };
366 {
367 my $guard = $schema->txn_scope_guard;
368 $schema->resultset ('Artist')->create ({ name => 'bohhoo'});
369
370 $schema->storage->disconnect; # this should freak out the guard rollback
371 }
372
373 is (@w, 2, 'Both expected warnings found');
374 }
375
376 done_testing;
55 use DBICTest;
66
77 BEGIN {
8 require DBIx::Class;
8 require DBIx::Class::Storage::DBI;
99 plan skip_all =>
10 'Test needs SQL::Translator ' . DBIx::Class->_sqlt_minimum_version
11 if not DBIx::Class->_sqlt_version_ok;
10 'Test needs SQL::Translator ' . DBIx::Class::Storage::DBI->_sqlt_minimum_version
11 if not DBIx::Class::Storage::DBI->_sqlt_version_ok;
1212 }
1313
1414 my $schema = DBICTest->init_schema (no_deploy => 1);
00 use strict;
1 use warnings;
1 use warnings;
22
33 use Test::More;
4 use Test::Warn;
45 use Test::Exception;
56 use lib qw(t/lib);
67 use DBICTest;
78
89 my $schema = DBICTest->init_schema();
9
10 plan tests => 20;
1110
1211 my $rs = $schema->resultset("CD")->search({}, { order_by => 'cdid' });
1312
3130 is($rs_year->next, 1999, "reset okay");
3231
3332 is($rs_year->first, 1999, "first okay");
33
34 warnings_exist (sub {
35 is($rs_year->single, 1999, "single okay");
36 }, qr/Query returned more than one row/, 'single warned');
3437
3538 # test +select/+as for single column
3639 my $psrs = $schema->resultset('CD')->search({},
9396 [ $rs->get_column ('cdid')->all ],
9497 'prefetch properly collapses amount of rows from get_column',
9598 );
99
100 done_testing;
1515 plan skip_all => 'Set $ENV{DBICTEST_MYSQL_DSN}, _USER and _PASS to run this test'
1616 unless ($dsn);
1717
18 require DBIx::Class;
18 require DBIx::Class::Storage::DBI;
1919 plan skip_all =>
20 'Test needs SQL::Translator ' . DBIx::Class->_sqlt_minimum_version
21 if not DBIx::Class->_sqlt_version_ok;
20 'Test needs SQL::Translator ' . DBIx::Class::Storage::DBI->_sqlt_minimum_version
21 if not DBIx::Class::Storage::DBI->_sqlt_version_ok;
2222 }
2323
2424 my $version_table_name = 'dbix_class_schema_versions';
55 use DBICTest;
66
77 BEGIN {
8 require DBIx::Class;
8 require DBIx::Class::Storage::DBI;
99 plan skip_all =>
10 'Test needs SQL::Translator ' . DBIx::Class->_sqlt_minimum_version
11 if not DBIx::Class->_sqlt_version_ok;
10 'Test needs SQL::Translator ' . DBIx::Class::Storage::DBI->_sqlt_minimum_version
11 if not DBIx::Class::Storage::DBI->_sqlt_version_ok;
1212 }
1313
1414 my $schema = DBICTest->init_schema();
9494 }
9595 eval { Film->constrain_column(codirector => Untaint => 'date') };
9696 is $@, '', 'Can constrain with untaint';
97
9798 my $freeaa =
9899 eval { Film->create({ title => "The Freaa", codirector => 'today' }) };
99 TODO: {
100 local $TODO = "no idea what this is supposed to do";
101 is $@, '', "Can create codirector";
102 is $freeaa && $freeaa->codirector, '2001-03-03', "Set the codirector";
103 }
100 is $@, '', "Can create codirector";
101 is $freeaa && $freeaa->codirector, '2001-03-03', "Set the codirector";
104102 }
105103
106104 __DATA__
2929 },
3030 );
3131 __PACKAGE__->set_primary_key('artistid');
32 __PACKAGE__->add_unique_constraint(artist => ['artistid']); # do not remove, part of a test
3233
3334 __PACKAGE__->mk_classdata('field_name_for', {
3435 artistid => 'primary key',
6970
7071 sub store_column {
7172 my ($self, $name, $value) = @_;
72 $value = 'X '.$value if ($name eq 'name' && $value && $value =~ /store_column test/);
73 $value = 'X '.$value if ($name eq 'name' && $value && $value =~ /(X )?store_column test/);
7374 $self->next::method($name, $value);
7475 }
7576
00 --
11 -- Created by SQL::Translator::Producer::SQLite
2 -- Created on Tue Aug 25 12:34:34 2009
2 -- Created on Mon Sep 21 00:11:34 2009
33 --
44
55
0 use warnings;
1
2 use Test::More;
3 use Test::Exception;
4 use lib qw(t/lib);
5 use DBIC::SqlMakerTest;
6 use DBICTest;
7
8 my $schema = DBICTest->init_schema();
9
10
11 # a regular belongs_to prefetch
12 my $cds = $schema->resultset('CD')->search ({}, { prefetch => 'artist' } );
13
14 my $nulls = {
15 hashref => {},
16 arrayref => [],
17 undef => undef,
18 };
19
20 # make sure null-prefetches do not screw with the final sql:
21 for my $type (keys %$nulls) {
22 # is_same_sql_bind (
23 # $cds->search({}, { prefetch => { artist => $nulls->{$type} } })->as_query,
24 # $cds->as_query,
25 # "same sql with null $type prefetch"
26 # );
27 }
28
29 # make sure left join is carried only starting from the first has_many
30 is_same_sql_bind (
31 $cds->search({}, { prefetch => { artist => { cds => 'artist' } } })->as_query,
32 '(
33 SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track,
34 artist.artistid, artist.name, artist.rank, artist.charfield,
35 cds.cdid, cds.artist, cds.title, cds.year, cds.genreid, cds.single_track,
36 artist_2.artistid, artist_2.name, artist_2.rank, artist_2.charfield
37 FROM cd me
38 JOIN artist artist ON artist.artistid = me.artist
39 LEFT JOIN cd cds ON cds.artist = artist.artistid
40 LEFT JOIN artist artist_2 ON artist_2.artistid = cds.artist
41 ORDER BY cds.artist, cds.year
42 )',
43 [],
44 );
45
46 done_testing;
5656
5757
5858 # test where conditions at the root of the related chain
59 my $artist_rs = $schema->resultset("Artist")->search({artistid => 11});
60
59 my $artist_rs = $schema->resultset("Artist")->search({artistid => 2});
60 my $artist = $artist_rs->next;
61 $artist->create_related ('cds', $_) for (
62 {
63 year => 1999, title => 'vague cd', genre => { name => 'vague genre' }
64 },
65 {
66 year => 1999, title => 'vague cd2', genre => { name => 'vague genre' }
67 },
68 );
6169
6270 $rs = $artist_rs->search_related('cds')->search_related('genre',
63 { 'genre.name' => 'foo' },
71 { 'genre.name' => 'vague genre' },
6472 { prefetch => 'cds' },
6573 );
66 is($rs->all, 0, 'prefetch without distinct (objects)');
67 is($rs->count, 0, 'prefetch without distinct (count)');
68
74 is($rs->all, 1, 'base without distinct (objects)');
75 is($rs->count, 1, 'base without distinct (count)');
76 # artist -> 2 cds -> 2 genres -> 2 cds for each genre = 4
77 is($rs->search_related('cds')->all, 4, 'prefetch without distinct (objects)');
78 is($rs->search_related('cds')->count, 4, 'prefetch without distinct (count)');
6979
7080
7181 $rs = $artist_rs->search(undef, {distinct => 1})
7282 ->search_related('cds')->search_related('genre',
73 { 'genre.name' => 'foo' },
83 { 'genre.name' => 'vague genre' },
7484 );
75 is($rs->all, 0, 'distinct without prefetch (objects)');
76 is($rs->count, 0, 'distinct without prefetch (count)');
77
85 is($rs->all, 1, 'distinct without prefetch (objects)');
86 is($rs->count, 1, 'distinct without prefetch (count)');
7887
7988
8089 $rs = $artist_rs->search({}, {distinct => 1})
8190 ->search_related('cds')->search_related('genre',
82 { 'genre.name' => 'foo' },
91 { 'genre.name' => 'vague genre' },
8392 { prefetch => 'cds' },
8493 );
85 is($rs->all, 0, 'distinct with prefetch (objects)');
86 is($rs->count, 0, 'distinct with prefetch (count)');
94 is($rs->all, 1, 'distinct with prefetch (objects)');
95 is($rs->count, 1, 'distinct with prefetch (count)');
96 # artist -> 2 cds -> 2 genres -> 2 cds for each genre + distinct = 2
97 is($rs->search_related('cds')->all, 2, 'prefetched distinct with prefetch (objects)');
98 is($rs->search_related('cds')->count, 2, 'prefetched distinct with prefetch (count)');
8799
88100
89101
0 #!/usr/bin/perl -w
1
20 use strict;
3 use warnings;
1 use warnings;
42
53 use Test::More;
64 use lib qw(t/lib);
0 #!/usr/bin/perl -w
1
20 use strict;
3 use warnings;
1 use warnings;
42
53 use Test::More;
64 use lib qw(t/lib);
7777
7878
7979 # expect a year update on the only related row
80 # (non-qunique column only)
80 # (non-unique column only)
8181 $genre->update_or_create_related ('model_cd', {
8282 year => 2011,
8383 });
9494 },
9595 'CD year column updated correctly without a disambiguator',
9696 );
97
98