Your SlideShare is downloading. ×
0
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Using Perl Stored Procedures for MariaDB
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Using Perl Stored Procedures for MariaDB

1,730

Published on

https://www.percona.com/live/mysql-conference-2013/sessions/perl-stored-procedures-mariadb …

https://www.percona.com/live/mysql-conference-2013/sessions/perl-stored-procedures-mariadb

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,730
On Slideshare
0
From Embeds
0
Number of Embeds
28
Actions
Shares
0
Downloads
16
Comments
0
Likes
4
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Using Perl StoredProcedureswith MariaDBAntony T Curtis <atcurtis@gmail.com>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 WorldMariaDB [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/perluse 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 WorldMariaDB [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/perluse 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 dieMariaDB [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: Nosuch file or directory at /usr/local/mysql/lib/plugin/perl/GoodbyeWorld.pm line 16.package GoodbyeWorld;# put this file in <prefix>/lib/mysql/perluse 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 DataMariaDB [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-29emp_no: 10034first_name: Badergender: Mhire_date: 1988-09-21last_name: Swan1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)package ReadData;# put this file in <prefix>/lib/mysql/perluse 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 DataMariaDB [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-29emp_no: 10034first_name: Badergender: Mhire_date: 1988-09-21last_name: Swan1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)package ReadData;# put this file in <prefix>/lib/mysql/perluse 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 DataMariaDB [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 DataMariaDB [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 DataMariaDB [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 DataMariaDB [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 seconds300k 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 Monitoringsub 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 useHTTP::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 valueFROM 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 currentserver status could beas simple as fetchinghttp://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.

×