[Rt-commit] r4254 - in DBIx-SearchBuilder/trunk: . SearchBuilder SearchBuilder/Handle

alexmv at bestpractical.com alexmv at bestpractical.com
Tue Dec 6 13:01:52 EST 2005


Author: alexmv
Date: Tue Dec  6 13:01:51 2005
New Revision: 4254

Modified:
   DBIx-SearchBuilder/trunk/   (props changed)
   DBIx-SearchBuilder/trunk/SearchBuilder.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Handle.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Informix.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Handle/ODBC.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Oracle.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Pg.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Sybase.pm
Log:
 r7569 at zoq-fot-pik:  chmrr | 2005-12-06 12:53:01 -0500
  * _DistinctQuery (and hence SB::Handle::DistinctQuery) are now
    responsible for putting OrdersBy and GroupBy clauses in the right
    place
  * _OrderClause and _GroupClause are now computed on the fly, to allow
    munging them just before they are needed
  * ORDER BY across JOIN and DISTINCT now works on Mysql, Pg, and Oracle


Modified: DBIx-SearchBuilder/trunk/SearchBuilder.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder.pm	Tue Dec  6 13:01:51 2005
@@ -328,15 +328,9 @@
 sub _DistinctQuery {
     my $self = shift;
     my $statementref = shift;
-    my $table = shift;
 
     # XXX - Postgres gets unhappy with distinct and OrderBy aliases
-    if (exists $self->{'order_clause'} && $self->{'order_clause'} =~ /(?<!main)\./) {
-        $$statementref = "SELECT main.* FROM $$statementref";
-    }
-    else {
-	$self->_Handle->DistinctQuery($statementref, $table)
-    }
+    $self->_Handle->DistinctQuery($statementref, $self)
 }
 
 =head2 _BuildJoins
@@ -432,15 +426,13 @@
 
     # DISTINCT query only required for multi-table selects
     if ($self->_isJoined) {
-        $self->_DistinctQuery(\$QueryString, $self->Table);
+        $self->_DistinctQuery(\$QueryString);
     } else {
         $QueryString = "SELECT main.* FROM $QueryString";
+        $QueryString .= $self->_GroupClause;
+        $QueryString .= $self->_OrderClause;
     }
 
-    $QueryString .= ' ' . $self->_GroupClause . ' ';
-
-    $QueryString .= ' ' . $self->_OrderClause . ' ';
-
     $self->_ApplyLimits(\$QueryString);
 
     return($QueryString)
@@ -1044,9 +1036,24 @@
 sub OrderByCols {
     my $self = shift;
     my @args = @_;
-    my $clause = '';
 
-    foreach my $row ( @args ) {
+    $self->{'order_by'} = \@args;
+    $self->RedoSearch();
+}
+
+=head2 _OrderClause
+
+returns the ORDER BY clause for the search.
+
+=cut
+
+sub _OrderClause {
+    my $self = shift;
+
+    return '' unless $self->{'order_by'};
+
+    my $clause = '';
+    foreach my $row ( @{$self->{'order_by'}} ) {
 
         my %rowhash = ( ALIAS => 'main',
 			FIELD => undef,
@@ -1076,25 +1083,9 @@
             $clause .= $rowhash{'ORDER'};
         }
     }
-    $clause = "ORDER BY$clause" if $clause;
-
-    if ( ($self->{'order_clause'} || '') ne $clause ) {
-	$self->RedoSearch();
-    }
-    $self->{'order_clause'} = $clause;
-}
-
-=head2 _OrderClause
-
-returns the ORDER BY clause for the search.
-
-=cut
+    $clause = " ORDER BY$clause " if $clause;
 
-sub _OrderClause {
-    my $self = shift;
-
-    return '' unless $self->{'order_clause'};
-    return ($self->{'order_clause'});
+    return $clause;
 }
 
 
@@ -1120,10 +1111,26 @@
 sub GroupByCols {
     my $self = shift;
     my @args = @_;
+
+    $self->{'group_by'} = \@args;
+    $self->RedoSearch();
+}
+
+
+=head2 _GroupClause
+
+Private function to return the "GROUP BY" clause for this query.
+
+=cut
+
+sub _GroupClause {
+    my $self = shift;
+    return '' unless $self->{'group_by'};
+
     my $row;
     my $clause;
 
-    foreach $row ( @args ) {
+    foreach $row ( @{$self->{'group_by'}} ) {
         my %rowhash = ( ALIAS => 'main',
 			FIELD => undef,
 			%$row
@@ -1143,26 +1150,11 @@
     }
 
     if ($clause) {
-	$self->{'group_clause'} = "GROUP BY" . $clause;
+	return " GROUP BY" . $clause . " ";
     }
     else {
-	$self->{'group_clause'} = "";
+	return '';
     }
-    $self->RedoSearch();
-}
-
-
-=head2 _GroupClause
-
-Private function to return the "GROUP BY" clause for this query.
-
-=cut
-
-sub _GroupClause {
-    my $self = shift;
-
-    return '' unless $self->{'group_clause'};
-    return ($self->{'group_clause'});
 }
 
 

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Handle.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Handle.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Handle.pm	Tue Dec  6 13:01:51 2005
@@ -991,11 +991,12 @@
 sub DistinctQuery {
     my $self = shift;
     my $statementref = shift;
-    #my $table = shift;
+    my $sb = shift;
 
     # Prepend select query for DBs which allow DISTINCT on all column types.
     $$statementref = "SELECT DISTINCT main.* FROM $$statementref";
-
+    $$statementref .= $sb->_GroupClause;
+    $$statementref .= $sb->_OrderClause;
 }
 
 

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Informix.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Informix.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Informix.pm	Tue Dec  6 13:01:51 2005
@@ -127,12 +127,20 @@
 sub DistinctQuery {
     my $self = shift;
     my $statementref = shift;
-    my $table = shift;
-
-    # Wrapper select query in a subselect as Informix doesn't allow
-    # DISTINCT against CLOB/BLOB column types.
-    $$statementref = "SELECT * FROM $table main WHERE id IN ( SELECT DISTINCT main.id FROM $$statementref )";
+    my $sb = shift;
+    my $table = $sb->Table;
 
+    if ($sb->_OrderClause =~ /(?<!main)\./) {
+        # Don't know how to do ORDER BY when the DISTINCT is in a subquery
+        warn "Query will contain duplicate rows; don't how how to ORDER BY across DISTINCT";
+        $$statementref = "SELECT main.* FROM $$statementref";
+    } else {
+        # Wrapper select query in a subselect as Informix doesn't allow
+        # DISTINCT against CLOB/BLOB column types.
+        $$statementref = "SELECT * FROM $table main WHERE id IN ( SELECT DISTINCT main.id FROM $$statementref )";
+    }
+    $$statementref .= $sb->_GroupClause;
+    $$statementref .= $sb->_OrderClause;
 }
 
 

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Handle/ODBC.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Handle/ODBC.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Handle/ODBC.pm	Tue Dec  6 13:01:51 2005
@@ -77,8 +77,11 @@
 sub DistinctQuery {
     my $self         = shift;
     my $statementref = shift;
+    my $sb = shift;
 
     $$statementref = "SELECT main.* FROM $$statementref";
+    $$statementref .= $sb->_GroupClause;
+    $$statementref .= $sb->_OrderClause;
 }
 
 sub Encoding {

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Oracle.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Oracle.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Oracle.pm	Tue Dec  6 13:01:51 2005
@@ -238,18 +238,29 @@
 
 takes an incomplete SQL SELECT statement and massages it to return a DISTINCT result set.
 
-
 =cut
 
 sub DistinctQuery {
     my $self = shift;
     my $statementref = shift;
-    my $table = shift;
+    my $sb = shift;
+    my $table = $sb->Table;
 
-    # Wrapper select query in a subselect as Oracle doesn't allow
+    # Wrapp select query in a subselect as Oracle doesn't allow
     # DISTINCT against CLOB/BLOB column types.
-    $$statementref = "SELECT main.* FROM ( SELECT DISTINCT main.id FROM $$statementref ) distinctquery, $table main WHERE (main.id = distinctquery.id) ";
-
+    if ($sb->_OrderClause =~ /(?<!main)\./) {
+        # If we are ordering by something not in 'main', we need to GROUP
+        # BY and adjust the ORDER_BY accordingly
+        local $sb->{group_by} = [@{$sb->{group_by} || []}, {FIELD => 'id'}];
+        local $sb->{order_by} = [map {($_->{ALIAS} and $_->{ALIAS} ne "main") ? {%{$_}, FIELD => "min(".$_->{FIELD}.")"}: $_} @{$sb->{order_by}}];
+        my $group = $sb->_GroupClause;
+        my $order = $sb->_OrderClause;
+        $$statementref = "SELECT main.* FROM ( SELECT main.id FROM $$statementref $group $order ) distinctquery, $table main WHERE (main.id = distinctquery.id)";
+    } else {
+        $$statementref = "SELECT main.* FROM ( SELECT DISTINCT main.id FROM $$statementref ) distinctquery, $table main WHERE (main.id = distinctquery.id) ";
+        $$statementref .= $sb->_GroupClause;
+        $$statementref .= $sb->_OrderClause;
+    }
 }
 
 

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Pg.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Pg.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Pg.pm	Tue Dec  6 13:01:51 2005
@@ -164,6 +164,33 @@
     }
 }
 
+=head2 DistinctQuery STATEMENTREF
+
+takes an incomplete SQL SELECT statement and massages it to return a DISTINCT result set.
+
+=cut
+
+sub DistinctQuery {
+    my $self = shift;
+    my $statementref = shift;
+    my $sb = shift;
+    my $table = $sb->Table;
+
+    if ($sb->_OrderClause =~ /(?<!main)\./) {
+        # If we are ordering by something not in 'main', we need to GROUP
+        # BY and adjust the ORDER_BY accordingly
+        local $sb->{group_by} = [@{$sb->{group_by} || []}, {FIELD => 'id'}];
+        local $sb->{order_by} = [map {($_->{ALIAS} and $_->{ALIAS} ne "main") ? {%{$_}, FIELD => "min(".$_->{FIELD}.")"}: $_} @{$sb->{order_by}}];
+        my $group = $sb->_GroupClause;
+        my $order = $sb->_OrderClause;
+        $$statementref = "SELECT main.* FROM ( SELECT main.id FROM $$statementref $group $order ) distinctquery, $table main WHERE (main.id = distinctquery.id)";
+    } else {
+        $$statementref = "SELECT DISTINCT main.* FROM $$statementref";
+        $$statementref .= $sb->_GroupClause;
+        $$statementref .= $sb->_OrderClause;
+    }
+}
+
 1;
 
 __END__

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Sybase.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Sybase.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Handle/Sybase.pm	Tue Dec  6 13:01:51 2005
@@ -107,12 +107,20 @@
 sub DistinctQuery {
     my $self = shift;
     my $statementref = shift;
-    my $table = shift;
-
-    # Wrapper select query in a subselect as Oracle doesn't allow
-    # DISTINCT against CLOB/BLOB column types.
-    $$statementref = "SELECT main.* FROM ( SELECT DISTINCT main.id FROM $$statementref ) distinctquery, $table main WHERE (main.id = distinctquery.id) ";
+    my $sb = shift;
+    my $table = $sb->Table;
 
+    if ($sb->_OrderClause =~ /(?<!main)\./) {
+        # Don't know how to do ORDER BY when the DISTINCT is in a subquery
+        warn "Query will contain duplicate rows; don't how how to ORDER BY across DISTINCT";
+        $$statementref = "SELECT main.* FROM $$statementref";
+    } else {
+        # Wrapper select query in a subselect as Sybase doesn't allow
+        # DISTINCT against CLOB/BLOB column types.
+        $$statementref = "SELECT main.* FROM ( SELECT DISTINCT main.id FROM $$statementref ) distinctquery, $table main WHERE (main.id = distinctquery.id) ";
+    }
+    $$statementref .= $sb->_GroupClause;
+    $$statementref .= $sb->_OrderClause;
 }
 
 


More information about the Rt-commit mailing list