X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSQLMaker%2FOracleJoins.pm;h=0f50467edc5008330aa3d6926d7e8e463bf08e57;hb=f6fff270;hp=a9a92679b66fd9bae7c5bbb10250919e20a7d25f;hpb=70c288086248e5a4008490df22a56632341f2473;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/SQLMaker/OracleJoins.pm b/lib/DBIx/Class/SQLMaker/OracleJoins.pm index a9a9267..0f50467 100644 --- a/lib/DBIx/Class/SQLMaker/OracleJoins.pm +++ b/lib/DBIx/Class/SQLMaker/OracleJoins.pm @@ -1,16 +1,19 @@ -package # Hide from PAUSE - DBIx::Class::SQLMaker::OracleJoins; +package DBIx::Class::SQLMaker::OracleJoins; + +use warnings; +use strict; use base qw( DBIx::Class::SQLMaker::Oracle ); sub select { my ($self, $table, $fields, $where, $rs_attrs, @rest) = @_; + # pull out all join conds as regular WHEREs from all extra tables if (ref($table) eq 'ARRAY') { - $where = $self->_oracle_joins($where, @{ $table }); + $where = $self->_oracle_joins($where, @{ $table }[ 1 .. $#$table ]); } - return $self->SUPER::select($table, $fields, $where, $rs_attrs, @rest); + return $self->next::method($table, $fields, $where, $rs_attrs, @rest); } sub _recurse_from { @@ -33,9 +36,9 @@ sub _recurse_from { } sub _oracle_joins { - my ($self, $where, $from, @join) = @_; - my $join_where = {}; - $self->_recurse_oracle_joins($join_where, $from, @join); + my ($self, $where, @join) = @_; + my $join_where = $self->_recurse_oracle_joins(@join); + if (keys %$join_where) { if (!defined($where)) { $where = $join_where; @@ -50,42 +53,70 @@ sub _oracle_joins { } sub _recurse_oracle_joins { - my ($self, $where, $from, @join) = @_; + my $self = shift; - foreach my $j (@join) { + my @where; + for my $j (@_) { my ($to, $on) = @{ $j }; - if (ref $to eq 'ARRAY') { - $self->_recurse_oracle_joins($where, @{ $to }); - } + push @where, $self->_recurse_oracle_joins(@{ $to }) + if (ref $to eq 'ARRAY'); - my $to_jt = ref $to eq 'ARRAY' ? $to->[0] : $to; + my $join_opts = ref $to eq 'ARRAY' ? $to->[0] : $to; my $left_join = q{}; my $right_join = q{}; - if (ref $to_jt eq 'HASH' and exists $to_jt->{-join_type}) { + if (ref $join_opts eq 'HASH' and my $jt = $join_opts->{-join_type}) { #TODO: Support full outer joins -- this would happen much earlier in #the sequence since oracle 8's full outer join syntax is best #described as INSANE. $self->throw_exception("Can't handle full outer joins in Oracle 8 yet!\n") - if $to_jt->{-join_type} =~ /full/i; + if $jt =~ /full/i; - $left_join = q{(+)} if $to_jt->{-join_type} =~ /left/i - && $to_jt->{-join_type} !~ /inner/i; + $left_join = q{(+)} if $jt =~ /left/i + && $jt !~ /inner/i; - $right_join = q{(+)} if $to_jt->{-join_type} =~ /right/i - && $to_jt->{-join_type} !~ /inner/i; + $right_join = q{(+)} if $jt =~ /right/i + && $jt !~ /inner/i; } - foreach my $lhs (keys %{ $on }) { - $where->{$lhs . $left_join} = \"= $on->{ $lhs }$right_join"; - } + # FIXME - the code below *UTTERLY* doesn't work with custom conds... sigh + # for the time being do not do any processing with the likes of _collapse_cond + # instead only unroll the -and hack if present + $on = $on->{-and}[0] if ( + ref $on eq 'HASH' + and + keys %$on == 1 + and + ref $on->{-and} eq 'ARRAY' + and + @{$on->{-and}} == 1 + ); + + + push @where, map { \do { + my ($sql) = $self->_recurse_where({ + # FIXME - more borkage, more or less a copy of the kludge in ::SQLMaker::_join_condition() + $_ => ( length ref $on->{$_} + ? $on->{$_} + : { -ident => $on->{$_} } + ) + }); + + $sql =~ s/\s*\=/$left_join =/ + if $left_join; + + "$sql$right_join"; + } + } sort keys %$on; } + + return { -and => \@where }; } 1; -=pod +__END__ =head1 NAME @@ -93,9 +124,8 @@ DBIx::Class::SQLMaker::OracleJoins - Pre-ANSI Joins-via-Where-Clause Syntax =head1 PURPOSE -This module was originally written to support Oracle < 9i where ANSI joins -weren't supported at all, but became the module for Oracle >= 8 because -Oracle's optimising of ANSI joins is horrible. +This module is used with Oracle < 9.0 due to lack of support for standard +ANSI join syntax. =head1 SYNOPSIS @@ -121,25 +151,16 @@ it's already too late. =over -=item select ($\@$;$$@) - -Replaces DBIx::Class::SQLMaker's select() method, which calls _oracle_joins() -to modify the column and table list before calling SUPER::select(). +=item select -=item _recurse_from ($$\@) - -Recursive subroutine that builds the table list. - -=item _oracle_joins ($$$@) - -Creates the left/right relationship in the where query. +Overrides DBIx::Class::SQLMaker's select() method, which calls _oracle_joins() +to modify the column and table list before calling next::method(). =back =head1 BUGS -Does not support full outer joins. -Probably lots more. +Does not support full outer joins (however neither really does DBIC itself) =head1 SEE ALSO @@ -153,17 +174,13 @@ Probably lots more. =back -=head1 AUTHOR - -Justin Wheeler C<< >> - -=head1 CONTRIBUTORS - -David Jack Olrik C<< >> - -=head1 LICENSE +=head1 FURTHER QUESTIONS? -This module is licensed under the same terms as Perl itself. +Check the list of L. -=cut +=head1 COPYRIGHT AND LICENSE +This module is free software L +by the L. You can +redistribute it and/or modify it under the same terms as the +L.