[Bast-commits] r5491 - in DBIx-Class/0.08/trunk: . lib/DBIx/Class lib/DBIx/Class/Manual lib/DBIx/Class/Storage lib/DBIx/Class/Storage/DBI t t/resultset

robkinyon at dev.catalyst.perl.org robkinyon at dev.catalyst.perl.org
Mon Feb 16 22:09:12 GMT 2009


Author: robkinyon
Date: 2009-02-16 22:09:12 +0000 (Mon, 16 Feb 2009)
New Revision: 5491

Added:
   DBIx-Class/0.08/trunk/t/resultset/
   DBIx-Class/0.08/trunk/t/resultset/as_query.t
Modified:
   DBIx-Class/0.08/trunk/
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod
   DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSetColumn.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Cursor.pm
Log:
 r5378 at rkinyon-lt-osx (orig r5377):  robkinyon | 2009-01-29 15:58:53 -0500
 Branch for subquery support
 r5443 at rkinyon-lt-osx (orig r5442):  robkinyon | 2009-02-10 15:10:10 -0500
 Added as_query to ResultSet with a couple tests
 r5444 at rkinyon-lt-osx (orig r5443):  robkinyon | 2009-02-10 15:23:27 -0500
 Added as_query() support to ResultSetColumn
 r5446 at rkinyon-lt-osx (orig r5445):  robkinyon | 2009-02-10 17:53:48 -0500
 Switched to use is_same_sql_bind() per ribasushi's suggestion
 r5453 at rkinyon-lt-osx (orig r5452):  robkinyon | 2009-02-11 09:45:23 -0500
 check in bombing test for subquery-with-as_query
 r5458 at rkinyon-lt-osx (orig r5457):  robkinyon | 2009-02-11 11:24:11 -0500
 Checking in failing test
 r5470 at rkinyon-lt-osx (orig r5469):  robkinyon | 2009-02-13 14:43:12 -0500
 Added as_sql and as_subselect as wrappers around as_query
 r5471 at rkinyon-lt-osx (orig r5470):  robkinyon | 2009-02-13 14:56:40 -0500
 Added a passing test for initial simple subqueries
 r5479 at rkinyon-lt-osx (orig r5478):  robkinyon | 2009-02-15 11:23:46 -0500
 Subqueries are done



Property changes on: DBIx-Class/0.08/trunk
___________________________________________________________________
Name: svk:merge
   - 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5420
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:10772
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
   + 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5420
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:10772
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5490
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod	2009-02-16 22:03:55 UTC (rev 5490)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod	2009-02-16 22:09:12 UTC (rev 5491)
@@ -295,6 +295,27 @@
 are in any way unsure about the use of the attributes above (C< join
 >, C< select >, C< as > and C< group_by >).
 
+=head2 Subqueries
+
+You can write subqueries relatively easily in DBIC.
+
+  my $inside_rs = $schema->resultset('Artist')->search({
+    name => [ 'Billy Joel', 'Brittany Spears' ],
+  });
+
+  my $rs = $schema->resulset('CD')->search({
+    artist_id => { 'IN' => $inside_rs->get_column('id')->as_query },
+  });
+
+The usual operators ( =, !=, IN, NOT IN, etc) are supported.
+
+B<NOTE>: You have to explicitly use '=' when doing an equality comparison.
+The following will B<not> work:
+
+  my $rs = $schema->resulset('CD')->search({
+    artist_id => $inside_rs->get_column('id')->as_query,
+  });
+
 =head2 Predefined searches
 
 You can write your own L<DBIx::Class::ResultSet> class by inheriting from it

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm	2009-02-16 22:03:55 UTC (rev 5490)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm	2009-02-16 22:09:12 UTC (rev 5491)
@@ -1802,6 +1802,24 @@
   return \%unaliased;
 }
 
+=head2 as_query
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: \[ $sql, @bind ]
+
+=back
+
+Returns the SQL query and bind vars associated with the invocant.
+
+This is generally used as the RHS for a subquery.
+
+=cut
+
+sub as_query { return shift->cursor->as_query(@_) }
+
 =head2 find_or_new
 
 =over 4

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSetColumn.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSetColumn.pm	2009-02-16 22:03:55 UTC (rev 5490)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSetColumn.pm	2009-02-16 22:09:12 UTC (rev 5491)
@@ -54,6 +54,24 @@
   return $new;
 }
 
+=head2 as_query
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: \[ $sql, @bind ]
+
+=back
+
+Returns the SQL query and bind vars associated with the invocant.
+
+This is generally used as the RHS for a subquery.
+
+=cut
+
+sub as_query { return shift->_resultset->as_query }
+
 =head2 next
 
 =over 4
@@ -278,7 +296,6 @@
   );
 }
 
-
 1;
 
 =head1 AUTHORS

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Cursor.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Cursor.pm	2009-02-16 22:03:55 UTC (rev 5490)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Cursor.pm	2009-02-16 22:09:12 UTC (rev 5491)
@@ -49,6 +49,32 @@
   return bless ($new, $class);
 }
 
+=head2 as_query
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: \[ $sql, @bind ]
+
+=back
+
+Returns the SQL statement and bind vars associated with the invocant.
+
+=cut
+
+sub as_query {
+  my $self = shift;
+
+  my $storage = $self->{storage};
+  my $sql_maker = $storage->sql_maker;
+  local $sql_maker->{for};
+
+  my @args = $storage->_select_args(@{$self->{args}});
+  my ($sql, $bind)  = $storage->_prep_for_execute(@args[0 .. 2], [@args[4 .. $#args]]);
+  return \[ $sql, @$bind ];
+}
+
 =head2 next
 
 =over 4

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm	2009-02-16 22:03:55 UTC (rev 5490)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm	2009-02-16 22:09:12 UTC (rev 5491)
@@ -1173,11 +1173,15 @@
 sub _prep_for_execute {
   my ($self, $op, $extra_bind, $ident, $args) = @_;
 
+  if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
+    $ident = $ident->from();
+  }
+
   my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
+
   unshift(@bind,
     map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
       if $extra_bind;
-
   return ($sql, \@bind);
 }
 
@@ -1219,10 +1223,6 @@
 sub _dbh_execute {
   my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
   
-  if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
-    $ident = $ident->from();
-  }
-
   my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
 
   $self->_query_start( $sql, @$bind );
@@ -1357,6 +1357,13 @@
 }
 
 sub _select {
+  my $self = shift;
+  my $sql_maker = $self->sql_maker;
+  local $sql_maker->{for};
+  return $self->_execute($self->_select_args(@_));
+}
+
+sub _select_args {
   my ($self, $ident, $select, $condition, $attrs) = @_;
   my $order = $attrs->{order_by};
 
@@ -1393,7 +1400,7 @@
     push @args, $attrs->{rows}, $attrs->{offset};
   }
 
-  return $self->_execute(@args);
+  return @args;
 }
 
 sub source_bind_attributes {

Added: DBIx-Class/0.08/trunk/t/resultset/as_query.t
===================================================================
--- DBIx-Class/0.08/trunk/t/resultset/as_query.t	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/resultset/as_query.t	2009-02-16 22:09:12 UTC (rev 5491)
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings FATAL => 'all';
+
+use Data::Dumper;
+
+use Test::More;
+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');
+
+{
+  my $arr = $art_rs->as_query;
+  my ($query, @bind) = @{$$arr};
+
+  is_same_sql_bind(
+    $query, \@bind,
+    "SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me", [],
+  );
+}
+
+$art_rs = $art_rs->search({ name => 'Billy Joel' });
+
+{
+  my $arr = $art_rs->as_query;
+  my ($query, @bind) = @{$$arr};
+
+  is_same_sql_bind(
+    $query, \@bind,
+    "SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me WHERE ( name = ? )",
+    [ [ name => 'Billy Joel' ] ],
+  );
+}
+
+$art_rs = $art_rs->search({ rank => 2 });
+
+{
+  my $arr = $art_rs->as_query;
+  my ($query, @bind) = @{$$arr};
+
+  is_same_sql_bind(
+    $query, \@bind,
+    "SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me WHERE ( ( rank = ? ) AND ( name = ? ) )",
+    [ [ rank => 2 ], [ name => 'Billy Joel' ] ],
+  );
+}
+
+my $rscol = $art_rs->get_column( 'charfield' );
+
+{
+  my $arr = $rscol->as_query;
+  my ($query, @bind) = @{$$arr};
+
+  is_same_sql_bind(
+    $query, \@bind,
+    "SELECT me.charfield FROM artist me WHERE ( ( ( rank = ? ) AND ( name = ? ) ) )",
+    [ [ rank => 2 ], [ name => 'Billy Joel' ] ],
+  );
+}
+
+# This is an actual subquery.
+{
+  my $cdrs2 = $cdrs->search({
+    artist_id => { 'in' => $art_rs->search({}, { rows => 1 })->get_column( 'id' )->as_query },
+  });
+
+  my $arr = $cdrs2->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE artist_id IN ( SELECT id FROM artist me WHERE ( rank = ? ) AND ( name = ? ) LIMIT 1 )",
+    [ [ rank => 2 ], [ name => 'Billy Joel' ] ],
+  );
+}
+
+__END__




More information about the Bast-commits mailing list