diff --git a/bench/lookup_vs_single.pl b/bench/lookup_vs_single.pl index 42823f7..6f3ee5e 100644 --- a/bench/lookup_vs_single.pl +++ b/bench/lookup_vs_single.pl @@ -9,6 +9,7 @@ package Bench; use parent 'Teng'; __PACKAGE__->load_plugin('Lookup'); + __PACKAGE__->load_plugin('LookupPK', {pk => 'id'}); __PACKAGE__->load_plugin('SingleBySQL'); package Bench::Schema; @@ -42,6 +43,7 @@ single_by_sql => sub {$db->single_by_sql('SELECT id,name,age FROM user WHERE id = ?', [1], 'user')}, lookup => sub {$db->lookup('user', +{id => 1})}, lookup_arrayref => sub {$db->lookup('user', [id => 1])}, + lookup_pk => sub {$db->lookup_pk('user', 1)}, }, 'all'); __END__ diff --git a/lib/Teng/Plugin/LookupPK.pm b/lib/Teng/Plugin/LookupPK.pm new file mode 100644 index 0000000..788f49c --- /dev/null +++ b/lib/Teng/Plugin/LookupPK.pm @@ -0,0 +1,77 @@ +package Teng::Plugin::LookupPK; +use strict; +use warnings; +use utf8; + +sub init { + my ( $class, $teng, $opt ) = @_; + + my $pk_name = defined $opt && exists $opt->{pk} ? $opt->{pk} : 'id'; + + no strict 'refs'; + *{$teng . '::lookup_pk'} = sub { + my ($self, $table_name, $pk, $opt) = @_; + + my $table = $self->{schema}->get_table( $table_name ); + Carp::croak("No such table $table_name") unless $table; + + my $sql = sprintf('SELECT * FROM %s WHERE %s = ? LIMIT 1 %s', + $table_name, + $pk_name, + $opt->{for_update} ? 'FOR UPDATE' : '', + ); + + my $sth = $self->_execute($sql, [$pk]); + my $row = $sth->fetchrow_hashref($self->{fields_case}); + + return unless $row; + return $row if $self->{suppress_row_objects}; + + $table->{row_class}->new( + { + sql => $sql, + row_data => $row, + teng => $self, + table => $table, + table_name => $table_name, + } + ); + }; +} + + +1; +__END__ + +=head1 NAME + +Teng::Plugin::LookupPK - lookup by single primary key. + +=head1 NAME + + package MyDB; + use parent qw/Teng/; + __PACKAGE__->load_plugin('LookupPK'); + # same as + # __PACKAGE__->load_plugin('LookupPK', { pk => 'id' }); + + package main; + my $db = MyDB->new(...); + $db->lookup_pk('user' => 1); # => get single row + +=head1 DESCRIPTION + +This plugin provides fast lookup row . + +=head1 METHODS + +=over 4 + +=item $row = $db->lookup_pk($table_name, $pk, [\%attr]); + +lookup single row records. + +Teng#single is heavy. + +=back + diff --git a/t/001_basic/034_lookup_pk.t b/t/001_basic/034_lookup_pk.t new file mode 100644 index 0000000..15f44cc --- /dev/null +++ b/t/001_basic/034_lookup_pk.t @@ -0,0 +1,46 @@ +use t::Utils; +use Mock::Basic; +use Test::More; + +my $dbh = t::Utils->setup_dbh; +my $db_basic = Mock::Basic->new({dbh => $dbh}); +$db_basic->setup_test_db; + +subtest 'lookup_pk default' => sub { + Mock::Basic->load_plugin('LookupPK'); + $db_basic->insert('mock_basic', => +{ + id => 1, + name => 'perl', + }); + + my $row = $db_basic->lookup_pk('mock_basic', 1); + isa_ok $row, 'Mock::Basic::Row::MockBasic'; + is_deeply $row->get_columns, +{ + id => 1, + name => 'perl', + delete_fg => 0, + }; + undef &Mock::Basic::lookup_pk; +}; + +subtest 'lookup_pk specify pk_name' => sub { + Mock::Basic->load_plugin('LookupPK', {pk => 'name'}); + + $db_basic->insert('mock_basic', => +{ + id => 2, + name => 'ruby', + }); + + my $row = $db_basic->lookup_pk('mock_basic', 'ruby'); + isa_ok $row, 'Mock::Basic::Row::MockBasic'; + is_deeply $row->get_columns, +{ + id => 2, + name => 'ruby', + delete_fg => 0, + }; + + undef &Mock::Basic::lookup_pk; +}; + +done_testing; +