X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSQLAHacks%2FOracle.pm;h=5caf0a2631ecd8206575127250c9463af10f023b;hb=9ab1e5f01d9c869a08f87301e18a518d5f11edc5;hp=3af05cee1c0e549bed3c49d84ad35cebccb9c75d;hpb=c00243555c65c5df61de5578f3a19afb939dd212;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/SQLAHacks/Oracle.pm b/lib/DBIx/Class/SQLAHacks/Oracle.pm index 3af05ce..5caf0a2 100644 --- a/lib/DBIx/Class/SQLAHacks/Oracle.pm +++ b/lib/DBIx/Class/SQLAHacks/Oracle.pm @@ -1,9 +1,29 @@ package # Hide from PAUSE DBIx::Class::SQLAHacks::Oracle; +use warnings; +use strict; + use base qw( DBIx::Class::SQLAHacks ); use Carp::Clan qw/^DBIx::Class|^SQL::Abstract/; +# +# TODO: +# - Review by experienced DBIC/SQL:A developers :-) +# - Problem with count and connect_by look the TODO in t/73oracle.t +# + +sub new { + my $self = shift; + my %opts = (ref $_[0] eq 'HASH') ? %{$_[0]} : @_; + push @{$opts{special_ops}}, { + regex => qr/^prior$/i, + handler => '_where_field_PRIOR', + }; + + $self->SUPER::new (\%opts); +} + sub select { my ($self, $table, $fields, $where, $order, @rest) = @_; @@ -37,11 +57,18 @@ sub _connect_by { $sql .= $self->_sqlcase(' start with ') . $ws; push @bind, @wb; } - if ( my $connect_by = $attrs->{'connect_by'}) { - $sql .= $self->_sqlcase(' connect by'); - foreach my $key ( keys %$connect_by ) { - $sql .= " $key = " . $connect_by->{$key}; - } + if ( my $connect_by = $attrs->{'connect_by'} ) { + my ($connect_by_sql, @connect_by_sql_bind) = $self->_recurse_where( $attrs->{'connect_by'} ); + $sql .= sprintf(" %s %s", + ( $attrs->{'nocycle'} ) ? $self->_sqlcase('connect by nocycle') + : $self->_sqlcase('connect by'), + $connect_by_sql, + ); + push @bind, @connect_by_sql_bind; + # $sql .= $self->_sqlcase(' connect by'); + # foreach my $key ( keys %$connect_by ) { + # $sql .= " $key = " . $connect_by->{$key}; + # } } if ( $attrs->{'order_siblings_by'} ) { $sql .= $self->_order_siblings_by( $attrs->{'order_siblings_by'} ); @@ -52,16 +79,40 @@ sub _connect_by { } sub _order_siblings_by { - my $self = shift; - my $ref = ref $_[0]; + my ( $self, $arg ) = @_; + + my ( @sql, @bind ); + for my $c ( $self->_order_by_chunks($arg) ) { + $self->_SWITCH_refkind( + $c, + { + SCALAR => sub { push @sql, $c }, + ARRAYREF => sub { push @sql, shift @$c; push @bind, @$c }, + } + ); + } + + my $sql = + @sql + ? sprintf( '%s %s', $self->_sqlcase(' order siblings by'), join( ', ', @sql ) ) + : ''; + + return wantarray ? ( $sql, @bind ) : $sql; +} + +# we need to add a '=' only when PRIOR is used against a column diretly +# i.e. when it is invoked by a special_op callback +sub _where_field_PRIOR { + my ($self, $lhs, $op, $rhs) = @_; + my ($sql, @bind) = $self->_recurse_where ($rhs); - my @vals = $ref eq 'ARRAY' ? @{$_[0]} : - $ref eq 'SCALAR' ? ${$_[0]} : - $ref eq '' ? $_[0] : - puke( "Unsupported data struct $ref for ORDER SIBILINGS BY" ); + $sql = sprintf ('%s = %s %s ', + $self->_convert($self->_quote($lhs)), + $self->_sqlcase ($op), + $sql + ); - my $val = join ', ', map { $self->_quote($_) } @vals; - return $val ? $self->_sqlcase(' order siblings by')." $val" : ''; + return ($sql, @bind); } 1;