This page last modified: Jun 08 2007
title:PLPerl Notes description:Brief notes about Perl inside PostgreSQL keywords:plsql,perl,plperl,pl,postgres,sql To see a full working example of this code, download the Perl SQL example and see pal.pl which is in the tar file: http://defindit.com/readme_files/perl_sql_example.tar There are additional notes included in the example files. The example does not create the 20,000 record table, so you'd need to do a little extra work to reproduce my results. PostgreSQL (aka Postgres) has support available for Perl as an internal language. This is a neat idea, but it turns out that comparing carefully crafted examples, normal Perl and DBI is faster. Below is most of the code I used. The parts you don't see are standard DBI connection, etc. I'll post those later (they are also components of my open source Bioinformatics code). Thanks to Andrew Dunstan for his example PL/Perl at: http://www.oreillynet.com/pub/a/databases/2005/11/10/using-perl-in-postgresql.html I created a little demo table with around 20,000 records. Run times were 16 or 17 seconds for the Perl DBI subroutine, and 18 or 19 seconds for the PL/Perl version. -- My working version of the PL/Perl function. -- I didn't try the trinary operator, but speed should be unchanged. -- (I think the trinary operator is hard to read) create or replace function palindrome(text) returns boolean language plperl immutable as $$ my $canonical = lc($_[0]); $canonical =~ s/\s+//g; if ($canonical eq reverse($canonical)) { return "true"; } return "false"; $$; # This is the Perl DBI used to call the PL/Perl function in a SQL # query. sub sql_pal_internal { my $q_name = "sql_pal_internal"; my $dbh = get_db_handle("demo"); my $sql = "select * from demo where palindrome(name)"; my $sth = $dbh->prepare($sql); if ($dbh->err()) { die "$q_name 1\n$DBI::errstr\n"; } $sth->execute(); if ($dbh->err()) { die "$q_name 2\n$DBI::errstr\n"; } my %pal_hash; while((my $de_pk, my $name) = $sth->fetchrow_array()) { $pal_hash{$de_pk} = $name; } return %pal_hash; } Below is the Perl DBI subroutine I compared the PL/Perl function to. The PL/Perl is called from a similar subroutine so we'd be comparing apples-to-apples in a more or less realy world example. sub sql_palindrome { my $q_name = "sql_palindrome"; my $dbh = get_db_handle("demo"); my $sql = "select * from demo"; my $sth = $dbh->prepare($sql); if ($dbh->err()) { die "$q_name 1\n$DBI::errstr\n"; } $sth->execute(); if ($dbh->err()) { die "$q_name 2\n$DBI::errstr\n"; } my %pal_hash; while((my $de_pk, my $name) = $sth->fetchrow_array()) { my $canonical = lc($name); $canonical =~ s/\s+//g; if ($canonical eq reverse($canonical)) { $pal_hash{$de_pk} = $name; } } return %pal_hash; }