X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI%2FOracle%2FGeneric.pm;h=e6bf5ae1fe85862eb959935aa3f02c6b9918ab1e;hb=3895349e454e6b3fd36188b27e565acfa7da601e;hp=c6491abe24ad94feda2271029b2f8d11bff77f27;hpb=032b2366870757d95623b65fd3272f3a466ba51a;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm b/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm index c6491ab..e6bf5ae 100644 --- a/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm +++ b/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm @@ -17,6 +17,51 @@ DBIx::Class::Storage::DBI::Oracle::Generic - Oracle Support for DBIx::Class __PACKAGE__->set_primary_key('id'); __PACKAGE__->sequence('mysequence'); + # Somewhere in your Code + # add some data to a table with a hierarchical relationship + $schema->resultset('Person')->create ({ + firstname => 'foo', + lastname => 'bar', + children => [ + { + firstname => 'child1', + lastname => 'bar', + children => [ + { + firstname => 'grandchild', + lastname => 'bar', + } + ], + }, + { + firstname => 'child2', + lastname => 'bar', + }, + ], + }); + + # select from the hierarchical relationship + my $rs = $schema->resultset('Person')->search({}, + { + 'start_with' => { 'firstname' => 'foo', 'lastname' => 'bar' }, + 'connect_by' => { 'parentid' => { '-prior' => \'persionid' }, + 'order_siblings_by' => { -asc => 'name' }, + }; + ); + + # this will select the whole tree starting from person "foo bar", creating + # following query: + # SELECT + # me.persionid me.firstname, me.lastname, me.parentid + # FROM + # person me + # START WITH + # firstname = 'foo' and lastname = 'bar' + # CONNECT BY + # parentid = prior persionid + # ORDER SIBLINGS BY + # firstname ASC + =head1 DESCRIPTION This class implements base Oracle support. The subclass @@ -30,6 +75,8 @@ versions before 9. use base qw/DBIx::Class::Storage::DBI/; use mro 'c3'; +__PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks::Oracle'); + sub deployment_statements { my $self = shift;; my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_; @@ -68,8 +115,8 @@ sub _dbh_get_autoinc_seq { } else { $source_name = $source->name; - $source_name = uc($source_name) unless $sql_maker->quote_char; } + $source_name = uc($source_name) unless $sql_maker->quote_char; # trigger_body is a LONG local $dbh->{LongReadLen} = 64 * 1024 if ($dbh->{LongReadLen} < 64 * 1024); @@ -95,7 +142,7 @@ sub _dbh_get_autoinc_seq { while (my ($insert_trigger) = $sth->fetchrow_array) { return $1 if $insert_trigger =~ m!("?\w+"?)\.nextval!i; # col name goes here??? } - $self->throw_exception("Unable to find a sequence INSERT trigger on table '" . $source->name . "'."); + $self->throw_exception("Unable to find a sequence INSERT trigger on table '$source_name'."); } sub _sequence_fetch { @@ -110,9 +157,10 @@ sub _ping { my $dbh = $self->_dbh or return 0; local $dbh->{RaiseError} = 1; + local $dbh->{PrintError} = 0; eval { - $dbh->do("select 1 from dual"); + $dbh->do('select 1 from dual'); }; return $@ ? 0 : 1; @@ -149,7 +197,7 @@ sub _dbh_execute { $self->throw_exception($exception) if $exception; - wantarray ? @res : $res[0] + $wantarray ? @res : $res[0] } =head2 get_autoinc_seq @@ -192,10 +240,10 @@ Used as: on_connect_call => 'datetime_setup' -In L to set the session nls date, and -timestamp values for use with L and the -necessary environment variables for L, which is used -by it. +In L to set the session nls +date, and timestamp values for use with L +and the necessary environment variables for L, which +is used by it. Maximum allowable precision is used, unless the environment variables have already been set. @@ -360,7 +408,7 @@ sub with_deferred_fk_checks { my $txn_scope_guard = $self->txn_scope_guard; $self->_do_query('alter session set constraints = deferred'); - + my $sg = Scope::Guard->new(sub { $self->_do_query('alter session set constraints = immediate'); }); @@ -369,6 +417,117 @@ sub with_deferred_fk_checks { after => sub { $txn_scope_guard->commit }); } +sub _select_args { + my ($self, $ident, $select, $where, $attrs) = @_; + + my $connect_by_args = {}; + 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}, + } + } + + my @rv = $self->next::method($ident, $select, $where, $attrs); + + return (@rv, $connect_by_args); +} + +=head1 ATTRIBUTES + +Following additional attributes can be used in resultsets. + +=head2 connect_by + +=over 4 + +=item Value: \%connect_by + +=back + +A hashref of conditions used to specify the relationship between parent rows +and child rows of the hierarchy. + + connect_by => { parentid => 'prior personid' } + + # adds a connect by statement to the query: + # SELECT + # me.persionid me.firstname, me.lastname, me.parentid + # FROM + # person me + # 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 + +=item Value: \%condition + +=back + +A hashref of conditions which specify the root row(s) of the hierarchy. + +It uses the same syntax as L + + start_with => { firstname => 'Foo', lastname => 'Bar' } + + # SELECT + # me.persionid me.firstname, me.lastname, me.parentid + # FROM + # person me + # START WITH + # firstname = 'foo' and lastname = 'bar' + # CONNECT BY + # parentid = prior persionid + +=head2 order_siblings_by + +=over 4 + +=item Value: ($order_siblings_by | \@order_siblings_by) + +=back + +Which column(s) to order the siblings by. + +It uses the same syntax as L + + 'order_siblings_by' => 'firstname ASC' + + # SELECT + # me.persionid me.firstname, me.lastname, me.parentid + # FROM + # person me + # CONNECT BY + # parentid = prior persionid + # ORDER SIBLINGS BY + # firstname ASC + =head1 AUTHOR See L.