2

Could someone please assist to rectify the errors in this piece of code.

(this is just a simplified version of my code, but it identifies the issues).

DROP FUNCTION perl_func(VARIADIC params character varying[]);

CREATE OR REPLACE FUNCTION perl_func(VARIADIC params character varying[])
  RETURNS character varying AS
$BODY$   
   $val = spi_query("array_to_string($1,'###');");
   $s = `echo $val`;
   return $s; 
$BODY$
  LANGUAGE plperlu VOLATILE
  COST 100;

SELECT * from perl_func('a','d');

This returns a syntax error:

ERROR:  syntax error at or near "," at line 2.
CONTEXT:  PL/Perl function “perl_func”

The main aim: Is to formulate the input params as a string, and use it to call some command-line program, which returns a String. Then output this string as the return of this function.

Larry
  • 11,439
  • 15
  • 61
  • 84

1 Answers1

0

Original attempt:

The variable $1 means something different in Perl than it does in plpgsql functions. Try

CREATE OR REPLACE FUNCTION perl_func(VARIADIC params character varying[])
  RETURNS character varying AS
$BODY$
   use strict;
   use warnings;
   my $val = join("###",@_);
   my $s = `echo $val`;
   chomp($s);
   return $s; 
$BODY$
  LANGUAGE plperlu VOLATILE
  COST 100;

Unfortunately, this doesn't work (as noted below) because it doesn't split the strings properly. Unfortunately, plperl considers the arguments to be a single string:

CREATE OR REPLACE FUNCTION perl_str(VARIADIC text[])
  RETURNS text AS
$BODY$
   use strict;
   use warnings;
   my $array_str=shift;
   return $array_str;
$BODY$
  LANGUAGE plperl VOLATILE;

And when we select it:

> select perl_str(ARRAY['abc','def']);
 perl_str
-----------
 {abc,def}
(1 row)

And to find out for certain that it's a single string, we can turn to our old friend Data::Dumper:

CREATE OR REPLACE FUNCTION perl_dump(VARIADIC text[])
  RETURNS text AS
$BODY$
   use strict;
   use warnings;
   use Data::Dumper;
   my $array_str=shift;
   return Dumper($array_str);
$BODY$
  LANGUAGE plperl VOLATILE; 

And this returns:

> select perl_dump(ARRAY['abc','def']);
      perl_dump
----------------------
 $VAR1 = '{abc,def}';

(1 row)

So, the output is considered an actual string with curly braces on the end and the entries separated by commas. Okay, well...this is annoying, but at least we can deal with it:

CREATE OR REPLACE FUNCTION final_perl_func(VARIADIC text[])
  RETURNS text AS
$BODY$
   use strict;
   use warnings;
   my $array_string=shift;
   $array_string=substr($array_string,1,length($array_string)-2);
   my @array=split(/,/,$array_string);
   my $val=join("###",@array);
   my $s=`echo $val`;
   chomp($s);
   return $s;
$BODY$
  LANGUAGE plperl VOLATILE;

And this gets us what we want:

> select final_perl_func(ARRAY['abc','def']);
 final_perl_func
-----------------
 abc###def
(1 row)

Note that, for reasons I don't understand, I had to resort to the use of substr instead of a simple regex replace ($array_string=~s/{}//g;), as the plperl function kept returning the curly brackets when I tried the regex replacement.

I hadn't dealt with plperl a lot before answering your questions about it, and the main thing that I've learned is that it's a major pain...you might want to consider manipulating the database from Perl using the Perl DBI.

  • I still seem to be getting a syntax error: `ERROR: syntax error at or near "array_to_string" at line 5. CONTEXT: PL/Perl function “perl_func”` – Larry Apr 18 '12 at 16:39
  • Also what is $x, and how does it know which attribute is which. For example, if the function signature looked something like (a text, b text), how do we refer to each param? Any help would be much appreciated, thnx! – Larry Apr 18 '12 at 17:25
  • `$x` is the first variable that is [`shift`](http://perldoc.perl.org/5.12.0/functions/shift.html)ed off of [`@_`](http://perldoc.perl.org/perlvar.html). What exactly are you trying to do, here? Why are you calling [`spi_query`](http://www.postgresql.org/docs/8.2/static/plperl-database.html) but then not calling `spi_fetchrow`? –  Apr 18 '12 at 18:06
  • What I really want to try to do is have a way to transform the input params into a string that I can pass into some command-line function. So I don’t really mind using anything. Although I just tried spi_fetchrow, it compiles ok, but returns an empty cell for some reason. Any ideas please, thnx. – Larry Apr 18 '12 at 18:11
  • What, exactly, do you mean by "transform the input parameters into a string"? Transform how? Via [`join`](http://perldoc.perl.org/functions/join.html)? –  Apr 18 '12 at 18:12
  • Well I want to pass it into another program where it can interpret it, so for example, if we have an input such as (a,b,c), it can be transformed into a single string like "a###b###c”, and then be passed this into the command-line program. – Larry Apr 18 '12 at 18:15
  • Perl is good at string manipulation, so if you're using plperl, then use Perl. If not, then use plgpsql. Don't try to force the syntax of one on the other... Take a look at the edited code above. –  Apr 18 '12 at 18:16
  • Perfect... this is just what I needed. Btw: where can I read more about the syntax about Pl/Perl and it’s relation to SQL. For example, you use @_, where does it mention that this is the input argument. Just want to know for my further reference... Otherwise, thanks again... ! – Larry Apr 18 '12 at 18:18
  • You're most welcome. I'd recommend looking at either [Learning Perl](http://www.amazon.com/Learning-Perl-Randal-L-Schwartz/dp/1449303587) and/or [Modern Perl](http://www.onyxneon.com/books/modern_perl/index.html) (the latter is for people who know some programming already and serves as an introduction to idiomatic modern Perl, whereas the former is written for beginners to programming). The array `@_` is one of Perl's magic variables, and represents the array of arguments passed to a subroutine. –  Apr 18 '12 at 18:24
  • Btw: actually the output seems to be whitespace delimited and not delimited by “###”. Any reason why, for example input of (‘abc’,’def’) seems to return "abd def” in the output cell? – Larry Apr 18 '12 at 18:26
  • Hmmm, lemme see if I can reproduce that...one sec. –  Apr 18 '12 at 18:28
  • Ah ha! I've figured it out....plperl sucks a pile of rancid yak fetuses. Lemme edit... –  Apr 18 '12 at 18:59
  • There you go. This should get you what you want. –  Apr 18 '12 at 19:11