use "dbms capabilities" and storage accessors
Gianni Ceccarelli [Thu, 26 Aug 2010 10:21:11 +0000 (11:21 +0100)]
instead of package variables. We lost the ability to specify values as
connection attributes, but there were too many layers and it was getting
confusing.

lib/DBIx/Class/Storage/DBI/Pg.pm
t/72pg_cursors.t

index 45a2093..25e9049 100644 (file)
@@ -18,11 +18,9 @@ __PACKAGE__->datetime_parser_type ('DateTime::Format::Pg');
 __PACKAGE__->_use_multicolumn_in (1);
 
 __PACKAGE__->mk_group_accessors('simple' =>
-                                    '_pg_cursor_number');
-
-# these are package-vars to allow for evil global overrides
-our $DEFAULT_USE_PG_CURSORS=0;
-our $DEFAULT_PG_CURSORS_PAGE_SIZE=1000;
+                                    '_pg_cursor_number',
+                                    'cursor_page_size',
+                            );
 
 sub _determine_supports_insert_returning {
   return shift->_server_info->{normalized_dbms_version} >= 8.002
@@ -31,6 +29,10 @@ sub _determine_supports_insert_returning {
   ;
 }
 
+sub _determine_supports_server_cursors { 1 }
+
+sub _use_server_cursors { 0 } # temporary global off switch
+
 sub with_deferred_fk_checks {
   my ($self, $sub) = @_;
 
@@ -252,40 +254,31 @@ sub _get_next_pg_cursor_number {
     return $ret;
 }
 
-sub __get_tweak_value {
-    my ($self,$attrs,$slot,$default,$extra_test)=@_;
-
-    $extra_test||=sub{1};
+sub _should_use_pg_cursors {
+    my ($self,$attrs) = @_;
 
-    if (   exists $attrs->{$slot}
-        && defined $attrs->{$slot}
-        && $extra_test->($attrs->{$slot})
-    ) {
-        return $attrs->{$slot};
-    }
-    my @info=@{$self->_dbi_connect_info};
-    if (   @info
-        && ref($info[-1]) eq 'HASH'
-        && exists $info[-1]->{$slot}
-        && defined $info[-1]->{$slot}
-        && $extra_test->($info[-1]->{$slot})
+    if (   exists $attrs->{server_cursors}
+        && defined $attrs->{server_cursors}
     ) {
-        return $info[-1]->{$slot};
+        return $attrs->{server_cursors};
     }
-    return $default;
-}
-
-sub _should_use_pg_cursors {
-    my ($self,$attrs) = @_;
 
-    return $self->__get_tweak_value($attrs,'use_pg_cursors',$DEFAULT_USE_PG_CURSORS);
+    return $self->get_use_dbms_capability('server_cursors');
 }
 
 sub _get_pg_cursor_page_size {
     my ($self,$attrs) = @_;
 
-    return $self->__get_tweak_value($attrs,'pg_cursors_page_size',$DEFAULT_PG_CURSORS_PAGE_SIZE,
-                                    sub { $_[0] =~ /^\d+$/ });
+    if (   exists $attrs->{cursor_page_size}
+        && defined $attrs->{cursor_page_size}
+    ) {
+        return $attrs->{cursor_page_size};
+    }
+
+    if (defined $self->cursor_page_size) {
+        return $self->cursor_page_size;
+    }
+    return 1000;
 }
 
 sub _select {
@@ -331,14 +324,13 @@ Using PostgreSQL cursors on fetches:
 
   my $schema = MySchemaClass->connection(
                    $dsn, $user, $pass,
-                   {
-                      use_pg_cursors => 1,
-                      pg_cursors_page_size => 1000,
-                   });
+               );
+  $schema->storage->set_use_dbms_capability('sever_cursors');
+  $schema->storage->cursor_page_size(1000);
 
   # override at ResultSet level
   my $rs = $schema->resultset('Something')
-                  ->search({}, { use_pg_cursors => 0});
+                  ->search({}, { server_cursors => 0});
 
 =head1 DESCRIPTION
 
@@ -355,7 +347,7 @@ attributes (the latter take precedence).
 
 Fetching data using PostgreSQL cursors uses less memory, but is
 slightly slower. You can tune the memory / speed trade-off using the
-C<pg_cursors_page_size> attribute, which defines how many rows to
+C<cursor_page_size> attribute, which defines how many rows to
 fetch at a time (defaults to 1000).
 
 =head1 POSTGRESQL SCHEMA SUPPORT
index 1a933ea..a2cca05 100644 (file)
@@ -11,7 +11,7 @@ my ($dsn, $dbuser, $dbpass) = @ENV{map { "DBICTEST_PG_${_}" } qw/DSN USER PASS/}
 plan skip_all => 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test'
   unless ($dsn && $dbuser);
 
-plan tests => 10;
+plan tests => 14;
 
 sub create_test_schema {
     my ($schema)=@_;
@@ -42,7 +42,8 @@ sub drop_test_schema {
         });
 }
 
-my $schema = DBICTest::Schema->connection($dsn, $dbuser, $dbpass, { AutoCommit => 1, use_pg_cursors => 1 });
+my $schema = DBICTest::Schema->connection($dsn, $dbuser, $dbpass, { AutoCommit => 1 });
+$schema->storage->set_use_dbms_capability('server_cursors',1);
 drop_test_schema($schema);create_test_schema($schema);
 
 my ($called,$page_size)=(0,0);
@@ -77,12 +78,12 @@ is (
     $count++ while $rs->next;
     is($count,$rows,'get all the rows (loop)');
     is($called,1,'Pg::Sth called once per rs');
-    is($page_size,$DBIx::Class::Storage::DBI::Pg::DEFAULT_PG_CURSORS_PAGE_SIZE,'default page size used');
+    is($page_size,1000,'default page size used');
 }
 
 {
     $called=0;
-    my $rs=$schema->resultset('Artist')->search({},{pg_cursors_page_size=>10});
+    my $rs=$schema->resultset('Artist')->search({},{cursor_page_size=>10});
     $rs->first;
     is($called,1,'Pg::Sth called again per rs');
     is($page_size,10,'page size from attrs used');
@@ -91,9 +92,27 @@ is (
 {
     $called=0;
     my $rs=$schema->resultset('Artist')->search({});
+    $schema->storage->cursor_page_size(20);
+    $rs->first;
+    is($called,1,'Pg::Sth called again per rs');
+    is($page_size,20,'page size from storage used');
+    $schema->storage->cursor_page_size(undef);
+}
+
+{
+    $called=0;
+    my $rs=$schema->resultset('Artist')->search({});
     my @rows=$rs->all;
     is(scalar(@rows),$rows,'get all the rows (all)');
     is($called,1,'Pg::Sth called again per rs');
-    is($page_size,$DBIx::Class::Storage::DBI::Pg::DEFAULT_PG_CURSORS_PAGE_SIZE,'default page size used again');
+    is($page_size,1000,'default page size used again');
+}
+
+{
+    $called=0;
+    my $rs=$schema->resultset('Artist')->search({},{server_cursors=>0});
+    my @rows=$rs->all;
+    is(scalar(@rows),$rows,'get all the rows (all)');
+    is($called,0,'Pg::Sth *not* called');
 }