Fixed broken count query, because of new count query implementation.
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / SQLAHacks / Oracle.pm
CommitLineData
c0024355 1package # Hide from PAUSE
2 DBIx::Class::SQLAHacks::Oracle;
3
9ab1e5f0 4use warnings;
5use strict;
6
c0024355 7use base qw( DBIx::Class::SQLAHacks );
8use Carp::Clan qw/^DBIx::Class|^SQL::Abstract/;
9
43426175 10#
11# TODO:
2df1857d 12# - Review by experienced DBIC/SQL:A developers :-)
2ba03b16 13# - Problem with count and connect_by look the TODO in t/73oracle.t
3e4ed6a2 14# - Rename option nocycle to connect_by_nocycle
43426175 15#
16
9ab1e5f0 17sub new {
18 my $self = shift;
19 my %opts = (ref $_[0] eq 'HASH') ? %{$_[0]} : @_;
20 push @{$opts{special_ops}}, {
21 regex => qr/^prior$/i,
22 handler => '_where_field_PRIOR',
23 };
24
25 $self->SUPER::new (\%opts);
26}
27
c0024355 28sub select {
2e4dd241 29 my ($self, $table, $fields, $where, $rs_attrs, @rest) = @_;
c0024355 30
2e4dd241 31 my ($sql, @bind) = $self->SUPER::select($table, $fields, $where, $rs_attrs, @rest);
c0024355 32 push @bind, @{$self->{_oracle_connect_by_binds}};
33
34 return wantarray ? ($sql, @bind) : $sql;
35}
36
37sub _emulate_limit {
2e4dd241 38 my ( $self, $syntax, $sql, $rs_attrs, $rows, $offset ) = @_;
c0024355 39
2e4dd241 40 my ($cb_sql, @cb_bind) = $self->_connect_by($rs_attrs);
c0024355 41 $sql .= $cb_sql;
42 $self->{_oracle_connect_by_binds} = \@cb_bind;
43
2e4dd241 44 return $self->SUPER::_emulate_limit($syntax, $sql, $rs_attrs, $rows, $offset);
c0024355 45}
46
47sub _connect_by {
2e4dd241 48 my ($self, $attrs) = @_;
49
c0024355 50 my $sql = '';
51 my @bind;
52
53 if ( ref($attrs) eq 'HASH' ) {
54 if ( $attrs->{'start_with'} ) {
55 my ($ws, @wb) = $self->_recurse_where( $attrs->{'start_with'} );
56 $sql .= $self->_sqlcase(' start with ') . $ws;
57 push @bind, @wb;
58 }
2ba03b16 59 if ( my $connect_by = $attrs->{'connect_by'} ) {
43426175 60 my ($connect_by_sql, @connect_by_sql_bind) = $self->_recurse_where( $attrs->{'connect_by'} );
61 $sql .= sprintf(" %s %s",
2ba03b16 62 ( $attrs->{'nocycle'} ) ? $self->_sqlcase('connect by nocycle')
63 : $self->_sqlcase('connect by'),
43426175 64 $connect_by_sql,
65 );
66 push @bind, @connect_by_sql_bind;
67 # $sql .= $self->_sqlcase(' connect by');
68 # foreach my $key ( keys %$connect_by ) {
69 # $sql .= " $key = " . $connect_by->{$key};
70 # }
c0024355 71 }
72 if ( $attrs->{'order_siblings_by'} ) {
73 $sql .= $self->_order_siblings_by( $attrs->{'order_siblings_by'} );
74 }
75 }
76
77 return wantarray ? ($sql, @bind) : $sql;
78}
79
80sub _order_siblings_by {
2a770efe 81 my ( $self, $arg ) = @_;
82
83 my ( @sql, @bind );
84 for my $c ( $self->_order_by_chunks($arg) ) {
85 $self->_SWITCH_refkind(
86 $c,
87 {
88 SCALAR => sub { push @sql, $c },
89 ARRAYREF => sub { push @sql, shift @$c; push @bind, @$c },
90 }
91 );
92 }
c0024355 93
2a770efe 94 my $sql =
95 @sql
96 ? sprintf( '%s %s', $self->_sqlcase(' order siblings by'), join( ', ', @sql ) )
97 : '';
c0024355 98
2a770efe 99 return wantarray ? ( $sql, @bind ) : $sql;
c0024355 100}
101
9ab1e5f0 102# we need to add a '=' only when PRIOR is used against a column diretly
103# i.e. when it is invoked by a special_op callback
104sub _where_field_PRIOR {
105 my ($self, $lhs, $op, $rhs) = @_;
106 my ($sql, @bind) = $self->_recurse_where ($rhs);
107
108 $sql = sprintf ('%s = %s %s ',
109 $self->_convert($self->_quote($lhs)),
110 $self->_sqlcase ($op),
111 $sql
112 );
113
114 return ($sql, @bind);
115}
116
c0024355 1171;
118
119__END__
120
121=pod
122
123=head1 NAME
124
125DBIx::Class::SQLAHacks::Oracle - adds hierarchical query support for Oracle to SQL::Abstract
126
127=head1 DESCRIPTION
128
129See L<DBIx::Class::Storage::DBI::Oracle::Generic> for more informations about
130how to use hierarchical queries with DBIx::Class.
131
132=cut