I am pondering writing a simple little package and sticking it on CPAN that 
would try and do a little generic sql caching.  The topic seems to come up 
about once a week, and I think I have a pretty good solution, kind of gleaned 
from much discussion on the list over the years.  The code is at the end of 
this message.

You have sql with ?s as place holders.  You pass the sql and what will fill the 
place holders ($binds).  There is also a memcache_version_key which tries to 
keep a bit of state.  The memcache_version_key might look like

'mvk.product_id.15'

When data_fallback runs, it generates a memkey like so

my $memkey = 'df.' . ( $memcache->get($memcache_version_key) || 0 ) . '.' . 
md5_hex($sql) . '.' . md5_hex( join( ', ', @$binds ) );

if data_fallback can find anything based on that memkey, it returns it, 
otherwise, it queries and sets memcache.

This is not a panacea, as you need to know when certain queries have become 
invalid and invalidate the cache yourself, so when you know that the data for 
the product with id 15 changes, you do something like

$memcache->incr($memcache_version_key);

Anyway, I think it works well, and the paradigm has worked well in the past, 
though the code below is from last night.  The tactic is especially good for 
querying a table in many different ways.

There are also a couple niceties; like getting hash refs back, or making 
queries that return only one column into a simple array ref.

Ideas for a name are welcome.  It would be nice to have some simple CPAN code 
to point to when the discussion comes up again.  This strategy alleviated my 
need for namespaces, and might be a nice stopgap until tags are incorporated.

Thoughts?


Thanks,
Earl

use Carp qw(confess);
use Digest::MD5 qw(md5_hex);

sub data_fallback {
    my $hash = shift || confess 'need a hash';

    my $dbh   = $hash->{dbh}   || confess 'need a dbh';
    my $sql   = $hash->{sql}   || confess 'need some sql';
    my $binds = $hash->{binds} || confess 'need some binds';
    my $memcache_version_key = $hash->{memcache_version_key}
        || confess 'need a memcache_version_key';
    my $ttl      = $hash->{ttl}      || 3600;
    my $memcache = $hash->{memcache} || confess 'need a memcache object';
    my $as_hash_ref = $hash->{as_hash_ref};

    my $memkey = 'df.'
        . ( $memcache->get($memcache_version_key) || 0 ) . '.'
        . md5_hex($sql) . '.'
        . md5_hex( join( ', ', @$binds ) );

    my $data;
    if ( $data = $memcache->get($memkey) ) {
    } else {
        $data = [];

        my $sth = $dbh->prepare($sql);
        $sth->execute( @$binds );

        if ($as_hash_ref) {
            while ( my $hash_ref = $sth->fetchrow_hashref('NAME_lc') ) {
                push @$data, $hash_ref;
            }
        } else {
            while ( my @array = $sth->fetchrow_array ) {
                if ( scalar @array == 1 ) {
                    push @$data, $array[0];
                } else {
                    push @$data, [EMAIL PROTECTED];
                }
            }
        }
        $memcache->set( $memkey, $data, $ttl );
    }
    return $data;
}




       
____________________________________________________________________________________
Moody friends. Drama queens. Your life? Nope! - their life, your story. Play 
Sims Stories at Yahoo! Games.
http://sims.yahoo.com/  

Reply via email to