[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