From: Gianni Ceccarelli Date: Thu, 26 Aug 2010 10:21:11 +0000 (+0100) Subject: use "dbms capabilities" and storage accessors X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2d4928e365f6cfd3b647425baf9dd722be96fc3b;p=dbsrgits%2FDBIx-Class.git use "dbms capabilities" and storage accessors 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. --- diff --git a/lib/DBIx/Class/Storage/DBI/Pg.pm b/lib/DBIx/Class/Storage/DBI/Pg.pm index 45a2093..25e9049 100644 --- a/lib/DBIx/Class/Storage/DBI/Pg.pm +++ b/lib/DBIx/Class/Storage/DBI/Pg.pm @@ -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 attribute, which defines how many rows to +C attribute, which defines how many rows to fetch at a time (defaults to 1000). =head1 POSTGRESQL SCHEMA SUPPORT diff --git a/t/72pg_cursors.t b/t/72pg_cursors.t index 1a933ea..a2cca05 100644 --- a/t/72pg_cursors.t +++ b/t/72pg_cursors.t @@ -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'); }