From: Robert Bohne Date: Sat, 27 Mar 2010 11:03:23 +0000 (+0000) Subject: Support NOCYCLE parameter. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2ba03b1627e18f422a84948277b72fd1c80da3a0;p=dbsrgits%2FDBIx-Class-Historic.git Support NOCYCLE parameter. --- diff --git a/lib/DBIx/Class/SQLAHacks/Oracle.pm b/lib/DBIx/Class/SQLAHacks/Oracle.pm index 6046372..ca6700e 100644 --- a/lib/DBIx/Class/SQLAHacks/Oracle.pm +++ b/lib/DBIx/Class/SQLAHacks/Oracle.pm @@ -8,8 +8,7 @@ use Carp::Clan qw/^DBIx::Class|^SQL::Abstract/; # TODO: # - Check the parameter syntax of connect_by # - Review by experienced DBIC/SQL:A developers :-) -# - Check NOCYCLE parameter -# http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/pseudocolumns001.htm#i1009434 +# - Problem with count and connect_by look the TODO in t/73oracle.t # sub select { @@ -45,10 +44,11 @@ sub _connect_by { $sql .= $self->_sqlcase(' start with ') . $ws; push @bind, @wb; } - if ( my $connect_by = $attrs->{'connect_by'}) { + 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", - $self->_sqlcase('connect by'), + ( $attrs->{'nocycle'} ) ? $self->_sqlcase('connect by nocycle') + : $self->_sqlcase('connect by'), $connect_by_sql, ); push @bind, @connect_by_sql_bind; diff --git a/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm b/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm index 95e428d..37ddf7a 100644 --- a/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm +++ b/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm @@ -420,9 +420,10 @@ sub _select_args { my ($self, $ident, $select, $where, $attrs) = @_; my $connect_by_args = {}; - if ( $attrs->{connect_by} || $attrs->{start_with} || $attrs->{order_siblings_by} ) { + if ( $attrs->{connect_by} || $attrs->{start_with} || $attrs->{order_siblings_by} || $attrs->{nocycle} ) { $connect_by_args = { connect_by => $attrs->{connect_by}, + nocycle => $attrs->{nocycle}, start_with => $attrs->{start_with}, order_siblings_by => $attrs->{order_siblings_by}, } @@ -458,6 +459,28 @@ and child rows of the hierarchy. # CONNECT BY # parentid = prior persionid +=head2 nocycle + +=over 4 + +=item Value: [1|0] + +=back + +If you want to use NOCYCLE set to 1. + + connect_by => { parentid => 'prior personid' }, + nocycle => 1 + + # adds a connect by statement to the query: + # SELECT + # me.persionid me.firstname, me.lastname, me.parentid + # FROM + # person me + # CONNECT BY NOCYCLE + # parentid = prior persionid + + =head2 start_with =over 4 diff --git a/t/73oracle.t b/t/73oracle.t index a8ca401..f1c1ca0 100644 --- a/t/73oracle.t +++ b/t/73oracle.t @@ -586,27 +586,66 @@ if ( $schema->storage->isa('DBIx::Class::Storage::DBI::Oracle::Generic') ) { # after count_subq, # I will fix this later... # + # is_same_sql_bind ( + # $rs->count_rs->as_query, + # '( + # SELECT COUNT( * ) FROM ( + # SELECT * FROM ( + # SELECT A.*, ROWNUM r FROM ( + # SELECT + # me.artistid AS col1 + # FROM artist me + # START WITH name = ? + # CONNECT BY artistid = PRIOR( parentid ) + # ) A + # WHERE ROWNUM < 3 + # ) B + # WHERE r >= 1 + # ) count_subq + # )', + # [ [ name => 'greatgrandchild' ] ], + # ); + # + # is( $rs->count, 2, 'Connect By; LIMIT count ok' ); + } + + # select the whole tree with nocylce + { + my $rs = $schema->resultset('Artist')->search({}, { + nocycle => 1, + start_with => { name => 'root' }, + connect_by => { parentid => { -prior => \ 'artistid' } }, + }); + + is_same_sql_bind ( + $rs->as_query, + '( + SELECT me.artistid, me.name, me.rank, me.charfield, me.parentid + FROM artist me + START WITH name = ? + CONNECT BY NOCYCLE parentid = PRIOR( artistid ) + )', + [ [ name => 'root'] ], + ); + is_deeply ( + [ $rs->get_column ('name')->all ], + [ qw/root child1 grandchild greatgrandchild child2/ ], + 'got artist tree with nocycle', + ); + + is_same_sql_bind ( $rs->count_rs->as_query, - '( - SELECT COUNT( * ) FROM ( - SELECT * FROM ( - SELECT A.*, ROWNUM r FROM ( - SELECT - me.artistid AS col1 - FROM artist me - START WITH name = ? - CONNECT BY artistid = PRIOR( parentid ) - ) A - WHERE ROWNUM < 3 - ) B - WHERE r >= 1 - ) count_subq + '( + SELECT COUNT( * ) + FROM artist me + START WITH name = ? + CONNECT BY NOCYCLE parentid = PRIOR( artistid ) )', - [ [ name => 'greatgrandchild' ] ], + [ [ name => 'root'] ], ); - is( $rs->count, 2, 'Connect By; LIMIT count ok' ); + is( $rs->count, 5, 'Connect By Nocycle count ok' ); } }