X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=22477fe948050b65e3241e7cc84617382e233497;hb=6c0230de282983fa588795e3f81ce16fcd9ef316;hp=60c6277ee6434f8a44bce8b478bae5d5eee82fe9;hpb=bac6c4fb44d23391b40e5fcf53809c0ca0c75dc7;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 60c6277..22477fe 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -14,6 +14,7 @@ use DBIx::Class::Storage::Statistics; use Scalar::Util(); use List::Util(); use Data::Dumper::Concise(); +use Sub::Name (); # what version of sqlt do we require if deploy() without a ddl_dir is invoked # when changing also adjust the corresponding author_require in Makefile.PL @@ -63,7 +64,7 @@ for my $meth (@rdbms_specific_methods) { no strict qw/refs/; no warnings qw/redefine/; - *{__PACKAGE__ ."::$meth"} = sub { + *{__PACKAGE__ ."::$meth"} = Sub::Name::subname $meth => sub { if (not $_[0]->_driver_determined) { $_[0]->_determine_driver; goto $_[0]->can($meth); @@ -1580,6 +1581,14 @@ sub _subq_update_delete { # quick check if we got a sane rs on our hands my @pcols = $rsrc->primary_columns; + unless (@pcols) { + $self->throw_exception ( + sprintf ( + "You must declare primary key(s) on source '%s' (via set_primary_key) in order to update or delete complex resultsets", + $rsrc->source_name || $rsrc->from + ) + ); + } my $sel = $rs->_resolved_attrs->{select}; $sel = [ $sel ] unless ref $sel eq 'ARRAY'; @@ -1764,12 +1773,52 @@ sub _select_args { if ( ( $attrs->{rows} && keys %{$attrs->{collapse}} ) || - ( $attrs->{group_by} && @{$attrs->{group_by}} && - $attrs->{_prefetch_select} && @{$attrs->{_prefetch_select}} ) + ( $attrs->{group_by} + && + @{$attrs->{group_by}} + && + $attrs->{_prefetch_select} + && + @{$attrs->{_prefetch_select}} + ) ) { + ($ident, $select, $where, $attrs) = $self->_adjust_select_args_for_complex_prefetch ($ident, $select, $where, $attrs); } + + elsif ( + ($attrs->{rows} || $attrs->{offset}) + && + $sql_maker->limit_dialect eq 'RowNumberOver' + && + (ref $ident eq 'ARRAY' && @$ident > 1) # indicates a join + && + scalar $sql_maker->_order_by_chunks ($attrs->{order_by}) + ) { + # the RNO limit dialect above mangles the SQL such that the join gets lost + # wrap a subquery here + + push @limit, delete @{$attrs}{qw/rows offset/}; + + my $subq = $self->_select_args_to_query ( + $ident, + $select, + $where, + $attrs, + ); + + $ident = { + -alias => $attrs->{alias}, + -source_handle => $ident->[0]{-source_handle}, + $attrs->{alias} => $subq, + }; + + # all part of the subquery now + delete @{$attrs}{qw/order_by group_by having/}; + $where = undef; + } + elsif (! $attrs->{software_limit} ) { push @limit, $attrs->{rows}, $attrs->{offset}; } @@ -1991,7 +2040,7 @@ sub last_insert_id { This API is B, will almost definitely change in the future, and currently only used by L<::AutoCast|DBIx::Class::Storage::DBI::AutoCast> and -L<::Sybase|DBIx::Class::Storage::DBI::Sybase>. +L<::Sybase::ASE|DBIx::Class::Storage::DBI::Sybase::ASE>. The default implementation returns C, implement in your Storage driver if you need this functionality. @@ -2324,10 +2373,19 @@ sub deployment_statements { data => $schema, ); - my $ret = $tr->translate - or $self->throw_exception( 'Unable to produce deployment statements: ' . $tr->error); + my @ret; + my $wa = wantarray; + if ($wa) { + @ret = $tr->translate; + } + else { + $ret[0] = $tr->translate; + } + + $self->throw_exception( 'Unable to produce deployment statements: ' . $tr->error) + unless (@ret && defined $ret[0]); - return $ret; + return $wa ? @ret : $ret[0]; } sub deploy { @@ -2452,6 +2510,30 @@ sub lag_behind_master { sub _sqlt_minimum_version { $minimum_sqlt_version }; } +=head2 relname_to_table_alias + +=over 4 + +=item Arguments: $relname, $join_count + +=back + +L uses L names as table aliases in +queries. + +This hook is to allow specific C drivers to change the way these +aliases are named. + +=cut + +sub relname_to_table_alias { + my ($self, $relname, $join_count) = @_; + + my $alias = ($join_count > 1 ? join('_', $relname, $join_count) : $relname); + + return $alias; +} + sub DESTROY { my $self = shift;