StevieD
StevieD

Reputation: 7433

How do write a dispatch table for methods?

I'm trying to get rid of the if statements at the end of a subroutine I'm writing to handle SELECT queries:

sub select_query {
  my ($params, $query, $return_type) = @_; 
  my $qh = $dbx->prepare($query);
  my $param_count = 1;
  foreach my $param (@$params) {
    $qh->bind_param($param_count++, $param);
  }
  $qh->execute;

  if ($return_type eq 'fetchrow_array') {
    return $qh->fetchrow_array;
  }
  if ($return_type eq 'fetchall_arrayref') {
    return $qh->fetchall_arrayref;
  }
  ... AND SO ON ...
}

I'm familiar with the idea of a dispatch table to call different subroutines. What code could I use to efficiently call the various dbi methods on the $qh handle?

Upvotes: 1

Views: 203

Answers (2)

ikegami
ikegami

Reputation: 385496

All you need is $qh->$return_type(...).

If you wish to validate, you can use a trivial lookup table.

my @valid_return_types = qw( fetchrow_array ... );
my %valid_return_types = map { $_ => 1 } @valid_return_types;

die "..." if !$valid_return_types{$return_type};

Upvotes: 5

Ron Bergin
Ron Bergin

Reputation: 1068

You will need to define the dispatch table after creating the statement handle.

use strict;
use warnings;
use DBI;
use Data::Dumper;

my $dbh = DBI->connect("DBI:mysql:mysql:localhost", 'user', 'password');
my $sth = $dbh->prepare("select * from user");
my $return_type = 'fetchall_arrayref';

my %dispatch  = (fetchall_arrayref => sub {return $sth->fetchall_arrayref},
                 fetchrow_array    => sub {return $sth->fetchrow_array});


$sth->execute;
print Dumper $dispatch{$return_type}->();

UPDATE: Actually, let me make a correction. You can, if you wish, define the dispatch table prior creating the statement handle.

my %dispatch  = (fetchall_arrayref => sub {return $_[0]->fetchall_arrayref},
                 fetchall_hashref  => sub {return $_[0]->fetchall_hashref('User')},
                 fetchrow_array    => sub {return $_[0]->fetchrow_array});

my $dbh = DBI->connect("DBI:mysql:mysql:localhost", 'root', 'password') or die;
my $sth = $dbh->prepare("select * from user");

foreach my $type (qw(fetchall_arrayref fetchall_hashref fetchrow_array)) {
    $sth->execute;
    print Dumper $dispatch{$type}->($sth);
}

Upvotes: 0

Related Questions