Merge 'subquery' into 'trunk'
Rob Kinyon [Fri, 20 Feb 2009 04:54:26 +0000 (04:54 +0000)]
Changes
lib/DBIx/Class/Storage/DBI.pm
t/resultset/as_query.t
t/search/subquery.t

diff --git a/Changes b/Changes
index 6adb26f..9bdf1b9 100644 (file)
--- a/Changes
+++ b/Changes
@@ -8,6 +8,8 @@ Revision history for DBIx::Class
           was NULL and the row was not stored would unexpectedly fail (groditi)
         - Split sql statements for deploy only if SQLT::Producer returned a scalar
           containing all statements to be executed
+        - Add as_query() for ResultSet and ResultSetColumn. This makes subqueries
+          possible. See the Cookbook for details. (robkinyon, michaelr)
 
 0.08099_06 2009-01-23 07:30:00 (UTC)
         - Allow a scalarref to be supplied to the 'from' resultset attribute
index 00a6c19..f017252 100644 (file)
@@ -259,10 +259,20 @@ sub _recurse_from {
   return join('', @sqlf);
 }
 
+sub _bind_to_sql {
+  my $self = shift;
+  my $arr  = shift;
+  my $sql = shift @$$arr;
+  $sql =~ s/\?/$self->_quote((shift @$$arr)->[1])/eg;
+  return $sql
+}
+
 sub _make_as {
   my ($self, $from) = @_;
-  return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ : $self->_quote($_)) }
-                     reverse each %{$self->_skip_options($from)});
+  return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ 
+                        : ref $_ eq 'REF'    ? $self->_bind_to_sql($_) 
+                        : $self->_quote($_)) 
+                       } reverse each %{$self->_skip_options($from)});
 }
 
 sub _skip_options {
index b573606..5071f0c 100644 (file)
@@ -6,12 +6,18 @@ use warnings FATAL => 'all';
 use Data::Dumper;
 
 use Test::More;
+
+BEGIN {
+    eval "use SQL::Abstract 1.49";
+    plan $@
+        ? ( skip_all => "Needs SQLA 1.49+" )
+        : ( tests => 4 );
+}
+
 use lib qw(t/lib);
 use DBICTest;
 use DBIC::SqlMakerTest;
 
-plan tests => 4;
-
 my $schema = DBICTest->init_schema();
 my $art_rs = $schema->resultset('Artist');
 my $cdrs = $schema->resultset('CD');
index 1a6861a..f8a7e79 100644 (file)
@@ -6,12 +6,18 @@ use warnings FATAL => 'all';
 use Data::Dumper;
 
 use Test::More;
+
+BEGIN {
+    eval "use SQL::Abstract 1.49";
+    plan $@
+        ? ( skip_all => "Needs SQLA 1.49+" )
+        : ( tests => 6 );
+}
+
 use lib qw(t/lib);
 use DBICTest;
 use DBIC::SqlMakerTest;
 
-plan tests => 5;
-
 my $schema = DBICTest->init_schema();
 my $art_rs = $schema->resultset('Artist');
 my $cdrs = $schema->resultset('CD');
@@ -53,8 +59,8 @@ TODO: {
   );
 }
 
-TODO: {
-  local $TODO = "'from' doesn't work with as_query yet.";
+# simple from
+{
   my $rs = $cdrs->search(
     {},
     {
@@ -69,14 +75,13 @@ TODO: {
   my ($query, @bind) = @{$$arr};
   is_same_sql_bind(
     $query, \@bind,
-    "SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.artistid, me.name, me.rank, me.charfield FROM cds me WHERE id > 20) cd2",
+    "SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE id > 20) cd2",
     [],
   );
 }
 
 # nested from
-TODO: {
-  local $TODO = "'from' doesn't work with as_query yet.";
+{
   my $art_rs2 = $schema->resultset('Artist')->search({}, 
   {
     from => [ { 'me' => 'artist' }, 
@@ -94,6 +99,41 @@ TODO: {
 
 }
 
+# nested subquery in from
+{
+  my $rs = $cdrs->search(
+    {},
+    {
+      alias => 'cd2',
+      from => [
+        { cd2 => $cdrs->search(
+            { id => { '>' => 20 } }, 
+            { 
+                alias => 'cd3',
+                from => [ 
+                { cd3 => $cdrs->search( { id => { '<' => 40 } } )->as_query }
+                ],
+            }, )->as_query },
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track 
+      FROM 
+        (SELECT cd3.cdid,cd3.artist,cd3.title,cd3.year,cd3.genreid,cd3.single_track 
+          FROM 
+            (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track 
+              FROM cd me WHERE id < 40) cd3
+          WHERE id > 20) cd2",
+    [],
+  );
+
+}
+
 {
   my $rs = $cdrs->search({
     year => {