SlideShare a Scribd company logo
Using Perl Stored
Procedures
with MariaDB
Antony T Curtis <atcurtis@gmail.com>
Special thanks to LinkedIn for permitting personal projects
Why Perl?
• CPAN
• "Multiplicity" / Thread-friendly.
• Lots of Perl code already written.
• MySQL UDFs have no access control.
• MySQL UDFs cannot execute dynamic SQL.
• Faster than “native” Stored Procedures.
Perl Stored Procedures
• Implemented as Perl modules.
• Use DBD::mysql to access database.
• Runs in-process with MariaDB.
• Easier to debug than SQL stored routines.
Hello World
MariaDB [Demo]> CREATE PROCEDURE PerlHello()
-> DYNAMIC RESULT SETS 1
-> NO SQL
-> LANGUAGE Perl
-> EXTERNAL NAME "HelloWorld::test";
Query OK, 0 rows affected (0.02 sec)
MariaDB [Demo]> call PerlHello();
+-----------------------+
| message |
+-----------------------+
| Hello World from Perl |
+-----------------------+
1 row in set (0.03 sec)
Query OK, 0 rows affected (0.03 sec)
package HelloWorld;
# put this file in <prefix>/lib/mysql/perl
use 5.008008;
use strict;
use warnings;
use Symbol qw(delete_package);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw( );
our @EXPORT = qw( test );
our $VERSION = '0.01';
sub test()
{
return {
'message' => 'Hello World from Perl',
};
}
1;
Hello World
MariaDB [Demo]> CREATE PROCEDURE PerlHello()
-> DYNAMIC RESULT SETS 1
-> NO SQL
-> LANGUAGE Perl
-> EXTERNAL NAME "HelloWorld::test";
Query OK, 0 rows affected (0.02 sec)
MariaDB [Demo]> call PerlHello();
+-----------------------+
| message |
+-----------------------+
| Hello World from Perl |
+-----------------------+
1 row in set (0.03 sec)
Query OK, 0 rows affected (0.03 sec)
package HelloWorld;
# put this file in <prefix>/lib/mysql/perl
use 5.008008;
use strict;
use warnings;
use Symbol qw(delete_package);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw( );
our @EXPORT = qw( test );
our $VERSION = '0.01';
sub test()
{
return {
'message' => 'Hello World from Perl',
};
}
1;
Error handling or die
MariaDB [Demo]> CREATE PROCEDURE PerlError()
-> DYNAMIC RESULT SETS 1
-> NO SQL
-> LANGUAGE Perl
-> EXTERNAL NAME "GoodbyeWorld::test";
Query OK, 0 rows affected (0.00 sec)
MariaDB [Demo]> call PerlError();
ERROR 1220 (HY000): Cannot open file: No
such file or directory at /usr/local/mysql/
lib/plugin/perl/GoodbyeWorld.pm line 16.
package GoodbyeWorld;
# put this file in <prefix>/lib/mysql/perl
use 5.008008;
use strict;
use warnings;
use Symbol qw(delete_package);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw( );
our @EXPORT = qw( test );
our $VERSION = '0.01';
sub test(
{
open FILE, "</something/nonexist"
or die "Cannot open file: $!";
return {
'message' => 'Goodbye World from Perl',
};
}
1;
Reading Data
MariaDB [employees]> CREATE PROCEDURE employee(
-> empno INT)
-> DYNAMIC RESULT SETS 1
-> READS SQL DATA
-> LANGUAGE Perl
-> EXTERNAL NAME "ReadData::test";
Query OK, 0 rows affected (0.02 sec)
MariaDB [employees]> call employee(10034)G
*************************** 1. row
***************************
birth_date: 1962-12-29
emp_no: 10034
first_name: Bader
gender: M
hire_date: 1988-09-21
last_name: Swan
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
package ReadData;
# put this file in <prefix>/lib/mysql/perl
use 5.008008;
use strict;
use warnings;
use Symbol qw(delete_package);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw( );
our @EXPORT = qw( test );
our $VERSION = '0.01';
our $DSN = ‘dbi:mysql:employees’;
use DBI;
use DBD::mysql;
sub test($)
{
my($emp_no) = @_;
my $dbh = DBI->connect($DSN, undef, undef) ||
die "Failed in call to DBI->connect, $!";
my $s = $dbh->prepare(
“SELECT * FROM employees WHERE emp_no=?”);
$s->execute(int $emp_no);
return $s->fetchrow_hashref;
}
1;
Reading Data
MariaDB [employees]> CREATE PROCEDURE employee(
-> empno INT)
-> DYNAMIC RESULT SETS 1
-> READS SQL DATA
-> LANGUAGE Perl
-> EXTERNAL NAME "ReadData::test";
Query OK, 0 rows affected (0.02 sec)
MariaDB [employees]> call employee(10034)G
*************************** 1. row
***************************
birth_date: 1962-12-29
emp_no: 10034
first_name: Bader
gender: M
hire_date: 1988-09-21
last_name: Swan
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
package ReadData;
# put this file in <prefix>/lib/mysql/perl
use 5.008008;
use strict;
use warnings;
use Symbol qw(delete_package);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw( );
our @EXPORT = qw( test );
our $VERSION = '0.01';
our $DSN = ‘dbi:mysql:employees’;
use DBI;
use DBD::mysql;
sub test($)
{
my($emp_no) = @_;
my $dbh = DBI->connect($DSN, undef, undef) ||
die "Failed in call to DBI->connect, $!";
my $s = $dbh->prepare(
“SELECT * FROM employees WHERE emp_no=?”);
$s->execute(int $emp_no);
return $s->fetchrow_hashref;
}
1;
Modifying Data
MariaDB [employees]> CREATE PROCEDURE
-> makesummary(
-> empno INT)
-> MODIFIES SQL DATA
-> LANGUAGE Perl
-> EXTERNAL NAME "ModifyData::test";
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> call makesummary;
sub test()
{
my $dbh = DBI->connect($DSN, undef, undef) ||
die "Failed in call to DBI->connect, $!";
$dbh->begin_work or die $!;
my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");
my $emps = $dbh->selectall_arrayref(
"select emp_no, max(salary) salary from employees ".
"left join salaries using (emp_no) group by emp_no",
{ Slice => {} });
foreach my $emp (@$emps)
{
$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;
}
$dbh->commit or die $!;
return undef;
}
Modifying Data
MariaDB [employees]> CREATE PROCEDURE
-> makesummary(
-> empno INT)
-> MODIFIES SQL DATA
-> LANGUAGE Perl
-> EXTERNAL NAME "ModifyData::test";
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> call makesummary;
Query OK, 0 rows affected (18.02 sec)
sub test()
{
my $dbh = DBI->connect($DSN, undef, undef) ||
die "Failed in call to DBI->connect, $!";
$dbh->begin_work or die $!;
my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");
my $emps = $dbh->selectall_arrayref(
"select emp_no, max(salary) salary from employees ".
"left join salaries using (emp_no) group by emp_no",
{ Slice => {} });
foreach my $emp (@$emps)
{
$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;
}
$dbh->commit or die $!;
return undef;
}
Modifying Data
MariaDB [employees]> CREATE PROCEDURE
-> makesummary(
-> empno INT)
-> MODIFIES SQL DATA
-> LANGUAGE Perl
-> EXTERNAL NAME "ModifyData::test";
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> call makesummary;
Query OK, 0 rows affected (18.02 sec)
MariaDB [employees]> select count(*)
-> from summary;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.15 sec)
sub test()
{
my $dbh = DBI->connect($DSN, undef, undef) ||
die "Failed in call to DBI->connect, $!";
$dbh->begin_work or die $!;
my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");
my $emps = $dbh->selectall_arrayref(
"select emp_no, max(salary) salary from employees ".
"left join salaries using (emp_no) group by emp_no",
{ Slice => {} });
foreach my $emp (@$emps)
{
$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;
}
$dbh->commit or die $!;
return undef;
}
Modifying Data
MariaDB [employees]> CREATE PROCEDURE
-> makesummary(
-> empno INT)
-> MODIFIES SQL DATA
-> LANGUAGE Perl
-> EXTERNAL NAME "ModifyData::test";
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> call makesummary;
Query OK, 0 rows affected (18.02 sec)
MariaDB [employees]> select count(*)
-> from summary;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.15 sec)
sub test()
{
my $dbh = DBI->connect($DSN, undef, undef) ||
die "Failed in call to DBI->connect, $!";
$dbh->begin_work or die $!;
my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");
my $emps = $dbh->selectall_arrayref(
"select emp_no, max(salary) salary from employees ".
"left join salaries using (emp_no) group by emp_no",
{ Slice => {} });
foreach my $emp (@$emps)
{
$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;
}
$dbh->commit or die $!;
return undef;
}
select statement - 2 seconds
300k inserts in 16 seconds
== 18k inserts per second
More than just procs
• CPAN is a large library...
• Can extend MariaDB’s functionality.
• How about using HTTP::Daemon?
Server Monitoring
sub daemon()
{
my $d = HTTP::Daemon->new(
LocalAddr => '127.0.0.1',
LocalPort => 8080,
) ||
die "Failed in call to HTTP::Daemon->new, $!";
my $dbh = DBI->connect("dbi:mysql:mysql", undef, undef) ||
die "Failed in call to DBI->connect, $!";
while (my $c = $d->accept)
{
while (my $r = $c->get_request)
{
if (exists $pages{$r->url->path})
{
$pages{$r->url->path}->($dbh, $c, $r);
}
else
{
$c->send_error(RC_NOT_FOUND);
}
}
$c->close;
undef $c;
}
}
What if we can use
HTTP::Daemon?
Server Monitoring
'/statusz' => sub {
my ($dbh,$c,$r) = @_;
return $c->send_error(RC_FORBIDDEN)
if $r->method ne 'GET';
my $sth = $dbh->prepare_cached(q{
SELECT VARIABLE_NAME name, VARIABLE_VALUE value
FROM INFORMATION_SCHEMA.GLOBAL_STATUS
}, { Slice => {} });
$sth->execute() || die $sth->errstr;
my $response = HTTP::Response->new(200, undef,
HTTP::Headers->new(
Content_Type => "application/json",
));
my $result = {};
while (my $row = $sth->fetchrow_arrayref)
{
$result->{$row->[0]} = $row->[1];
}
$response->add_content(to_json($result,
{ ascii => 1, pretty => 1 }));
return $c->send_response($response);
},
Fetching current
server status could be
as simple as fetching
http://127.0.0.1/statusz
Status
• Code hosted at LaunchPad.
• Contributing to MariaDB 10.0 soon.
• Stuff needs to be tidied up.
• Future steps include better Table Functions.

More Related Content

What's hot (20)

PDF
New features in Performance Schema 5.7 in action
Sveta Smirnova
 
PDF
MySQL Performance Schema in Action
Sveta Smirnova
 
PDF
Developers’ mDay 2021: Bogdan Kecman, Oracle – MySQL nekad i sad
mCloud
 
PPTX
DBA Commands and Concepts That Every Developer Should Know
Alex Zaballa
 
PDF
MySQL Performance schema missing_manual_flossuk
Valeriy Kravchuk
 
PDF
Mysql 56-experiences-bugs-solutions-50mins
Valeriy Kravchuk
 
PDF
MariaDB for developers
Colin Charles
 
PDF
Summary tables with flexviews
Justin Swanhart
 
PDF
Building node.js applications with Database Jones
John David Duncan
 
PDF
Flame Graphs for MySQL DBAs - FOSDEM 2022 MySQL Devroom
Valeriy Kravchuk
 
PDF
Troubleshooting MySQL Performance
Sveta Smirnova
 
PPT
Php classes in mumbai
aadi Surve
 
PDF
Introduction to MySQL Query Tuning for Dev[Op]s
Sveta Smirnova
 
PDF
Developing for Node.JS with MySQL and NoSQL
John David Duncan
 
PDF
Performance Schema for MySQL Troubleshooting
Sveta Smirnova
 
PDF
Performance schema in_my_sql_5.6_pluk2013
Valeriy Kravchuk
 
PDF
Why Use EXPLAIN FORMAT=JSON?
Sveta Smirnova
 
PDF
Performance Schema for MySQL troubleshooting
Sveta Smirnova
 
PPTX
Flex Cluster e Flex ASM - GUOB Tech Day - OTN TOUR LA Brazil 2014
Alex Zaballa
 
ODP
MySQL 101 PHPTek 2017
Dave Stokes
 
New features in Performance Schema 5.7 in action
Sveta Smirnova
 
MySQL Performance Schema in Action
Sveta Smirnova
 
Developers’ mDay 2021: Bogdan Kecman, Oracle – MySQL nekad i sad
mCloud
 
DBA Commands and Concepts That Every Developer Should Know
Alex Zaballa
 
MySQL Performance schema missing_manual_flossuk
Valeriy Kravchuk
 
Mysql 56-experiences-bugs-solutions-50mins
Valeriy Kravchuk
 
MariaDB for developers
Colin Charles
 
Summary tables with flexviews
Justin Swanhart
 
Building node.js applications with Database Jones
John David Duncan
 
Flame Graphs for MySQL DBAs - FOSDEM 2022 MySQL Devroom
Valeriy Kravchuk
 
Troubleshooting MySQL Performance
Sveta Smirnova
 
Php classes in mumbai
aadi Surve
 
Introduction to MySQL Query Tuning for Dev[Op]s
Sveta Smirnova
 
Developing for Node.JS with MySQL and NoSQL
John David Duncan
 
Performance Schema for MySQL Troubleshooting
Sveta Smirnova
 
Performance schema in_my_sql_5.6_pluk2013
Valeriy Kravchuk
 
Why Use EXPLAIN FORMAT=JSON?
Sveta Smirnova
 
Performance Schema for MySQL troubleshooting
Sveta Smirnova
 
Flex Cluster e Flex ASM - GUOB Tech Day - OTN TOUR LA Brazil 2014
Alex Zaballa
 
MySQL 101 PHPTek 2017
Dave Stokes
 

Similar to Using Perl Stored Procedures for MariaDB (20)

DOCX
Miniproject on Employee Management using Perl/Database.
Sanchit Raut
 
PDF
Sqlite perl
Ashoka Vanjare
 
ODP
DBI
abrummett
 
ODP
perl usage at database applications
Joe Jiang
 
PPT
Perl DBI Scripting with the ILS
Roy Zimmer
 
PPT
Working with databases in Perl
Laurent Dami
 
ODP
Database Programming with Perl and DBIx::Class
Dave Cross
 
PPT
Mysql DBI
Joe Christensen
 
PDF
BITS: Introduction to relational databases and MySQL - Schema design
BITS
 
PDF
Modern solutions for modern database load: improvements in the latest MariaDB...
Sveta Smirnova
 
DOCX
PERL for QA - Important Commands and applications
Sunil Kumar Gunasekaran
 
PDF
Sql
YUCHENG HU
 
PDF
Getting by with just psql
Corey Huinker
 
PPT
Sql abstract from_query
Laurent Dami
 
PPT
PERL.ppt
Farmood Alam
 
ODP
Perl Teach-In (part 1)
Dave Cross
 
PPTX
Class 8 - Database Programming
Ahmed Swilam
 
PPT
Introduction to Perl
NBACriteria2SICET
 
KEY
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 
Miniproject on Employee Management using Perl/Database.
Sanchit Raut
 
Sqlite perl
Ashoka Vanjare
 
perl usage at database applications
Joe Jiang
 
Perl DBI Scripting with the ILS
Roy Zimmer
 
Working with databases in Perl
Laurent Dami
 
Database Programming with Perl and DBIx::Class
Dave Cross
 
Mysql DBI
Joe Christensen
 
BITS: Introduction to relational databases and MySQL - Schema design
BITS
 
Modern solutions for modern database load: improvements in the latest MariaDB...
Sveta Smirnova
 
PERL for QA - Important Commands and applications
Sunil Kumar Gunasekaran
 
Getting by with just psql
Corey Huinker
 
Sql abstract from_query
Laurent Dami
 
PERL.ppt
Farmood Alam
 
Perl Teach-In (part 1)
Dave Cross
 
Class 8 - Database Programming
Ahmed Swilam
 
Introduction to Perl
NBACriteria2SICET
 
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 
Ad

Recently uploaded (20)

PDF
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
PDF
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PPTX
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
PDF
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Ad

Using Perl Stored Procedures for MariaDB

  • 1. Using Perl Stored Procedures with MariaDB Antony T Curtis <[email protected]> Special thanks to LinkedIn for permitting personal projects
  • 2. Why Perl? • CPAN • "Multiplicity" / Thread-friendly. • Lots of Perl code already written. • MySQL UDFs have no access control. • MySQL UDFs cannot execute dynamic SQL. • Faster than “native” Stored Procedures.
  • 3. Perl Stored Procedures • Implemented as Perl modules. • Use DBD::mysql to access database. • Runs in-process with MariaDB. • Easier to debug than SQL stored routines.
  • 4. Hello World MariaDB [Demo]> CREATE PROCEDURE PerlHello() -> DYNAMIC RESULT SETS 1 -> NO SQL -> LANGUAGE Perl -> EXTERNAL NAME "HelloWorld::test"; Query OK, 0 rows affected (0.02 sec) MariaDB [Demo]> call PerlHello(); +-----------------------+ | message | +-----------------------+ | Hello World from Perl | +-----------------------+ 1 row in set (0.03 sec) Query OK, 0 rows affected (0.03 sec) package HelloWorld; # put this file in <prefix>/lib/mysql/perl use 5.008008; use strict; use warnings; use Symbol qw(delete_package); require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( ); our @EXPORT = qw( test ); our $VERSION = '0.01'; sub test() { return { 'message' => 'Hello World from Perl', }; } 1;
  • 5. Hello World MariaDB [Demo]> CREATE PROCEDURE PerlHello() -> DYNAMIC RESULT SETS 1 -> NO SQL -> LANGUAGE Perl -> EXTERNAL NAME "HelloWorld::test"; Query OK, 0 rows affected (0.02 sec) MariaDB [Demo]> call PerlHello(); +-----------------------+ | message | +-----------------------+ | Hello World from Perl | +-----------------------+ 1 row in set (0.03 sec) Query OK, 0 rows affected (0.03 sec) package HelloWorld; # put this file in <prefix>/lib/mysql/perl use 5.008008; use strict; use warnings; use Symbol qw(delete_package); require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( ); our @EXPORT = qw( test ); our $VERSION = '0.01'; sub test() { return { 'message' => 'Hello World from Perl', }; } 1;
  • 6. Error handling or die MariaDB [Demo]> CREATE PROCEDURE PerlError() -> DYNAMIC RESULT SETS 1 -> NO SQL -> LANGUAGE Perl -> EXTERNAL NAME "GoodbyeWorld::test"; Query OK, 0 rows affected (0.00 sec) MariaDB [Demo]> call PerlError(); ERROR 1220 (HY000): Cannot open file: No such file or directory at /usr/local/mysql/ lib/plugin/perl/GoodbyeWorld.pm line 16. package GoodbyeWorld; # put this file in <prefix>/lib/mysql/perl use 5.008008; use strict; use warnings; use Symbol qw(delete_package); require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( ); our @EXPORT = qw( test ); our $VERSION = '0.01'; sub test( { open FILE, "</something/nonexist" or die "Cannot open file: $!"; return { 'message' => 'Goodbye World from Perl', }; } 1;
  • 7. Reading Data MariaDB [employees]> CREATE PROCEDURE employee( -> empno INT) -> DYNAMIC RESULT SETS 1 -> READS SQL DATA -> LANGUAGE Perl -> EXTERNAL NAME "ReadData::test"; Query OK, 0 rows affected (0.02 sec) MariaDB [employees]> call employee(10034)G *************************** 1. row *************************** birth_date: 1962-12-29 emp_no: 10034 first_name: Bader gender: M hire_date: 1988-09-21 last_name: Swan 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) package ReadData; # put this file in <prefix>/lib/mysql/perl use 5.008008; use strict; use warnings; use Symbol qw(delete_package); require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( ); our @EXPORT = qw( test ); our $VERSION = '0.01'; our $DSN = ‘dbi:mysql:employees’; use DBI; use DBD::mysql; sub test($) { my($emp_no) = @_; my $dbh = DBI->connect($DSN, undef, undef) || die "Failed in call to DBI->connect, $!"; my $s = $dbh->prepare( “SELECT * FROM employees WHERE emp_no=?”); $s->execute(int $emp_no); return $s->fetchrow_hashref; } 1;
  • 8. Reading Data MariaDB [employees]> CREATE PROCEDURE employee( -> empno INT) -> DYNAMIC RESULT SETS 1 -> READS SQL DATA -> LANGUAGE Perl -> EXTERNAL NAME "ReadData::test"; Query OK, 0 rows affected (0.02 sec) MariaDB [employees]> call employee(10034)G *************************** 1. row *************************** birth_date: 1962-12-29 emp_no: 10034 first_name: Bader gender: M hire_date: 1988-09-21 last_name: Swan 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) package ReadData; # put this file in <prefix>/lib/mysql/perl use 5.008008; use strict; use warnings; use Symbol qw(delete_package); require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( ); our @EXPORT = qw( test ); our $VERSION = '0.01'; our $DSN = ‘dbi:mysql:employees’; use DBI; use DBD::mysql; sub test($) { my($emp_no) = @_; my $dbh = DBI->connect($DSN, undef, undef) || die "Failed in call to DBI->connect, $!"; my $s = $dbh->prepare( “SELECT * FROM employees WHERE emp_no=?”); $s->execute(int $emp_no); return $s->fetchrow_hashref; } 1;
  • 9. Modifying Data MariaDB [employees]> CREATE PROCEDURE -> makesummary( -> empno INT) -> MODIFIES SQL DATA -> LANGUAGE Perl -> EXTERNAL NAME "ModifyData::test"; Query OK, 0 rows affected (0.00 sec) MariaDB [employees]> call makesummary; sub test() { my $dbh = DBI->connect($DSN, undef, undef) || die "Failed in call to DBI->connect, $!"; $dbh->begin_work or die $!; my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)"); my $emps = $dbh->selectall_arrayref( "select emp_no, max(salary) salary from employees ". "left join salaries using (emp_no) group by emp_no", { Slice => {} }); foreach my $emp (@$emps) { $ins->execute($emp->{emp_no}, $emp->{salary}) or die $!; } $dbh->commit or die $!; return undef; }
  • 10. Modifying Data MariaDB [employees]> CREATE PROCEDURE -> makesummary( -> empno INT) -> MODIFIES SQL DATA -> LANGUAGE Perl -> EXTERNAL NAME "ModifyData::test"; Query OK, 0 rows affected (0.00 sec) MariaDB [employees]> call makesummary; Query OK, 0 rows affected (18.02 sec) sub test() { my $dbh = DBI->connect($DSN, undef, undef) || die "Failed in call to DBI->connect, $!"; $dbh->begin_work or die $!; my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)"); my $emps = $dbh->selectall_arrayref( "select emp_no, max(salary) salary from employees ". "left join salaries using (emp_no) group by emp_no", { Slice => {} }); foreach my $emp (@$emps) { $ins->execute($emp->{emp_no}, $emp->{salary}) or die $!; } $dbh->commit or die $!; return undef; }
  • 11. Modifying Data MariaDB [employees]> CREATE PROCEDURE -> makesummary( -> empno INT) -> MODIFIES SQL DATA -> LANGUAGE Perl -> EXTERNAL NAME "ModifyData::test"; Query OK, 0 rows affected (0.00 sec) MariaDB [employees]> call makesummary; Query OK, 0 rows affected (18.02 sec) MariaDB [employees]> select count(*) -> from summary; +----------+ | count(*) | +----------+ | 300024 | +----------+ 1 row in set (0.15 sec) sub test() { my $dbh = DBI->connect($DSN, undef, undef) || die "Failed in call to DBI->connect, $!"; $dbh->begin_work or die $!; my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)"); my $emps = $dbh->selectall_arrayref( "select emp_no, max(salary) salary from employees ". "left join salaries using (emp_no) group by emp_no", { Slice => {} }); foreach my $emp (@$emps) { $ins->execute($emp->{emp_no}, $emp->{salary}) or die $!; } $dbh->commit or die $!; return undef; }
  • 12. Modifying Data MariaDB [employees]> CREATE PROCEDURE -> makesummary( -> empno INT) -> MODIFIES SQL DATA -> LANGUAGE Perl -> EXTERNAL NAME "ModifyData::test"; Query OK, 0 rows affected (0.00 sec) MariaDB [employees]> call makesummary; Query OK, 0 rows affected (18.02 sec) MariaDB [employees]> select count(*) -> from summary; +----------+ | count(*) | +----------+ | 300024 | +----------+ 1 row in set (0.15 sec) sub test() { my $dbh = DBI->connect($DSN, undef, undef) || die "Failed in call to DBI->connect, $!"; $dbh->begin_work or die $!; my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)"); my $emps = $dbh->selectall_arrayref( "select emp_no, max(salary) salary from employees ". "left join salaries using (emp_no) group by emp_no", { Slice => {} }); foreach my $emp (@$emps) { $ins->execute($emp->{emp_no}, $emp->{salary}) or die $!; } $dbh->commit or die $!; return undef; } select statement - 2 seconds 300k inserts in 16 seconds == 18k inserts per second
  • 13. More than just procs • CPAN is a large library... • Can extend MariaDB’s functionality. • How about using HTTP::Daemon?
  • 14. Server Monitoring sub daemon() { my $d = HTTP::Daemon->new( LocalAddr => '127.0.0.1', LocalPort => 8080, ) || die "Failed in call to HTTP::Daemon->new, $!"; my $dbh = DBI->connect("dbi:mysql:mysql", undef, undef) || die "Failed in call to DBI->connect, $!"; while (my $c = $d->accept) { while (my $r = $c->get_request) { if (exists $pages{$r->url->path}) { $pages{$r->url->path}->($dbh, $c, $r); } else { $c->send_error(RC_NOT_FOUND); } } $c->close; undef $c; } } What if we can use HTTP::Daemon?
  • 15. Server Monitoring '/statusz' => sub { my ($dbh,$c,$r) = @_; return $c->send_error(RC_FORBIDDEN) if $r->method ne 'GET'; my $sth = $dbh->prepare_cached(q{ SELECT VARIABLE_NAME name, VARIABLE_VALUE value FROM INFORMATION_SCHEMA.GLOBAL_STATUS }, { Slice => {} }); $sth->execute() || die $sth->errstr; my $response = HTTP::Response->new(200, undef, HTTP::Headers->new( Content_Type => "application/json", )); my $result = {}; while (my $row = $sth->fetchrow_arrayref) { $result->{$row->[0]} = $row->[1]; } $response->add_content(to_json($result, { ascii => 1, pretty => 1 })); return $c->send_response($response); }, Fetching current server status could be as simple as fetching http://127.0.0.1/statusz
  • 16. Status • Code hosted at LaunchPad. • Contributing to MariaDB 10.0 soon. • Stuff needs to be tidied up. • Future steps include better Table Functions.