Merge 'mssql_rno_pagination' into 'trunk'
Peter Rabbitson [Wed, 9 Dec 2009 22:13:59 +0000 (22:13 +0000)]
r8022@Thesaurus (orig r8010):  frew | 2009-12-02 17:57:17 +0100
branch for replacing TOP with RNO in MSSQL
r8027@Thesaurus (orig r8015):  frew | 2009-12-03 02:48:36 +0100
Switch to RowNumberOver for MSSQL
r8028@Thesaurus (orig r8016):  ribasushi | 2009-12-03 10:03:18 +0100
The correct top100 mssql solution and test
r8031@Thesaurus (orig r8019):  frew | 2009-12-03 15:56:35 +0100
fix RNO for MSSQL to not use a kludgy regexp
r8032@Thesaurus (orig r8020):  frew | 2009-12-04 01:33:28 +0100
initial (broken) version of 42rno.t
r8033@Thesaurus (orig r8021):  frew | 2009-12-04 01:37:06 +0100
first shot at moving stuff around
r8034@Thesaurus (orig r8022):  frew | 2009-12-04 01:45:42 +0100
rename files to get rid of numbers and use folders
r8035@Thesaurus (orig r8023):  frew | 2009-12-04 01:48:00 +0100
missed toplimit
r8036@Thesaurus (orig r8024):  frew | 2009-12-04 01:52:44 +0100
still broken rno test, but now it actually tests mssql
r8042@Thesaurus (orig r8030):  ribasushi | 2009-12-04 09:34:56 +0100
Variable clash
r8043@Thesaurus (orig r8031):  ribasushi | 2009-12-04 11:44:47 +0100
The complex prefetch rewrite actually takes care of this as cleanly as possible
r8044@Thesaurus (orig r8032):  ribasushi | 2009-12-04 11:47:22 +0100
Smarter implementation of the select top 100pct subselect handling
r8045@Thesaurus (orig r8033):  ribasushi | 2009-12-04 12:07:05 +0100
Add support for unordered limited resultsets
Rename the limit helper to signify it is MS specific
Make sure we don't lose group_by/having clauses
r8046@Thesaurus (orig r8034):  ribasushi | 2009-12-04 12:07:56 +0100
Un-todoify mssql limit tests - no changes necessary (throw away the obsolete generated sql checks)
r8047@Thesaurus (orig r8035):  ribasushi | 2009-12-04 12:24:13 +0100
Tests for bindvar propagation and Changes
r8049@Thesaurus (orig r8037):  ribasushi | 2009-12-04 15:01:32 +0100
KISS - a select(1) makes perfect ordering criteria
r8050@Thesaurus (orig r8038):  ribasushi | 2009-12-04 15:06:11 +0100
Unify the MSSQL and DB2 RNO implementations - they are the same
r8051@Thesaurus (orig r8039):  ribasushi | 2009-12-05 10:29:50 +0100
Wrap mssql selects in yet another subquery to make limited right-ordered join resultsets possible
r8052@Thesaurus (orig r8040):  ribasushi | 2009-12-05 10:46:41 +0100
Better not touch Top - it's too complex at this point
r8053@Thesaurus (orig r8041):  ribasushi | 2009-12-05 11:03:00 +0100
Extend test just a bit more
r8054@Thesaurus (orig r8042):  ribasushi | 2009-12-05 11:44:25 +0100
DB2 and MSSQL have different default order syntaxes
r8056@Thesaurus (orig r8044):  frew | 2009-12-08 02:10:06 +0100
add version check for mssql 2005 and greater
r8059@Thesaurus (orig r8047):  frew | 2009-12-08 16:15:50 +0100
real exception instead of die
r8061@Thesaurus (orig r8049):  ribasushi | 2009-12-09 00:19:49 +0100
Test for immediate connection with known storage type
r8062@Thesaurus (orig r8050):  frew | 2009-12-09 01:24:45 +0100
fix mssql version check so it's lazier
r8064@Thesaurus (orig r8052):  ribasushi | 2009-12-09 02:40:51 +0100
Fix comment
r8066@Thesaurus (orig r8054):  caelum | 2009-12-09 16:12:56 +0100
fix _get_mssql_version for ODBC

1  2 
Changes
lib/DBIx/Class/Storage/DBI.pm

diff --combined Changes
+++ b/Changes
@@@ -1,5 -1,6 +1,6 @@@
  Revision history for DBIx::Class
  
+         - Real limit/offset support for MSSQL server (via Row_Number)
          - Fix distinct => 1 with non-selecting order_by (the columns
            in order_by also need to be aded to the resulting group_by)
          - Do not attempt to deploy FK constraints pointing to a View
@@@ -10,7 -11,6 +11,7 @@@
          - Fix count/objects from search_related on limited resultset
          - Make get_inflated_columns behave identically to get_columns
            wrt +select/+as (RT#46953)
 +        - Fix problems with scalarrefs under InflateColumn (RT#51559)
  
  0.08114 2009-11-14 17:45:00 (UTC)
          - Preliminary support for MSSQL via DBD::ADO
@@@ -1290,12 -1290,6 +1290,12 @@@ sub _query_end 
      }
  }
  
 +sub _sth_bind_param {
 +  my ($self, $sth, $placeholder_index, $data, $attributes) = @_;
 +
 +  $sth->bind_param($placeholder_index, $data, $attributes);
 +}
 +
  sub _dbh_execute {
    my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
  
        my $ref = ref $data;
        $data = $ref && $ref ne 'ARRAY' ? ''.$data : $data; # stringify args (except arrayrefs)
  
 -      $sth->bind_param($placeholder_index, $data, $attributes);
 +      $self->_sth_bind_param($sth, $placeholder_index, $data, $attributes);
        $placeholder_index++;
      }
    }
@@@ -1587,14 -1581,6 +1587,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';
@@@ -1779,12 -1765,52 +1779,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};
    }