Question

I am trying to work with UDFs, defined through SQL::Statement::Functions in Perl with a mySQL database in the backend. I am playing it by the book, as stated in http://metacpan.org/pod/SQL::Statement::Functions#User-Defined-Functions, however, before I even leave square one, an error in the CREATE FUNCTION statement is rearing its ugly head. Here's the code first ($dbh is a given and works fine, it is just part of a bigger construct of the framework I am working with, so I don't want to spam my question with all of it; if I replace foo() in the SELECT by 22, or by "_PK FROM locations", all is good and I get a 22 or a value corresponding to the query in Data::Dumper, so, the connection is ok):

use Data::Dumper;
use SQL::Statement::Functions;

sub foo {
    return 999;
}

#$dbh is defined elsewhere
$dbh->do("CREATE FUNCTION foo") or die "error creating function foo(); " . $dbh->errstr;

my $sth = $dbh->prepare("SELECT foo(22)") or die "error preparing query: " . $dbh->errstr;
$sth->execute or die "error executing query: " . $sth->errstr;

my $row = $sth->fetchrow_arrayref();
print "ROW " . Dumper($row);

The error message reads as follows: error creating function foo(); You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1, refering to the $dbh->do("CREATE...") line.

I have tried to dumb the CREATE FUNCTION part down as much as possible, but I also tried it with ...foo EXTERNAL and ...foo EXTERNAL NAME foo as suggested by the manual. Heck, I even created a package for the function, to no avail.

Any ideas what I am doing wrong here?

I checked, and the user I am connected to the database with does have all privileges, including alter_routine_priv and create_routine_priv, if that is what SQL::Statement is using.

Was it helpful?

Solution

You are not using the module as it is intended. It's an extension to the SQL::Parser module that is used by DBDs to implement SQL syntax and functions. The documentation states:

This module contains the built-in functions for SQL::Parser and SQL::Statement. All of the functions are also available in any DBDs that subclass those modules (e.g. DBD::CSV, DBD::DBM, DBD::File, DBD::AnyData, DBD::Excel, etc.).

To me, that sounds like it has nothing to do with mysql. The DBD::mysql is used as a wrapper around a real mysql database. It just connects, forwards the queries, prepares them and so on. It does not parse them, however. That's what the database is doing, just like if you were to connect to an Oracle or MSSQL database. In those cases, the driver is like an API wrapper.

On the other hand, DBD::CSV and the others mentioned above are parsing the sql themselves. DBD::CSV opens a CSV file, understands the SQL and (very simply described) translates it into Perl code to look for stuff in the CSV data. The same goes for the others. They use SQL::Parser to make sense of the SQL. SQL::Statement::Functions seems to be the module that provides the equivalent Perl functions for the SQL.

When using SQL::Statement/SQL::Parser directly to parse SQL ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top