Why does my Perl CGI complain "Can't locate Mysql.pm"? - mysql

I have two folders php and perl. They contain index.php and index.pl, respectively.
My Perl code looks like:
#!/usr/bin/perl
use Mysql;
print "Content-type: text/html\n\n";
print "<h2>PERL-mySQL Connect</h2>";
print "page info";
$host = "localhost";
$database = "cdcol";
$user = "root";
$password = "";
$db = Mysql->connect($host, $database, $user, $password);
$db->selectdb($database);
When i run above code (by typing http://localhost:88/perl/ in the browser), I get the following error:
Can't locate Mysql.pm in #INC (#INC contains: C:/xampp/perl/site/lib/ C:/xampp/perl/lib C:/xampp/perl/site/lib C:/xampp/apache) at C:/xampp/htdocs/perl/index.pl line 2. BEGIN failed--compilation aborted at C:/xampp/htdocs/perl/index.pl line 2.
whereas browsing to http://localhost:88/php/ works.
index.php has:
<?php
$con = mysql_connect("localhost","root","");
if($con)
{
if(mysql_select_db("cdcol", $con))
{
$sql="SELECT Id From products";
if(mysql_query($sql))
{
$result = mysql_query($sql);
if ($result) ...

You should use DBI in conjunction with DBD::mysql.
You should use a standard CGI processing module such as CGI::Simple.
use strict; use warnings;
use CGI::Simple;
use DBI;
my $cgi = CGI::Simple->new;
my $dsn = sprintf(
'DBI:mysql:database=%s;host=%s',
'cdcol', 'localhost'
);
my $dbh = DBI->connect($dsn, root => '',
{ AutoCommit => 0, RaiseError => 0 }
);
my $status = $dbh ? 'Connected' : 'Failed to connect';
print $cgi->header, <<HTML;
<!DOCTYPE HTML>
<html>
<head><title>Test</title></head>
<body>
<h1>Perl CGI Script</h1>
<p>$status</p>
</body>
</html>
HTML

Related

DBI->connect working when executed in terminal but not when executed from browser

I am writing a CGI program that prints a database query result in the browser. The script looks like this
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
print "Content-type: text/html\n\n";
my $driver = "mysql";
my $database = "DBname";
my $ip = "127.0.0.1";
my $db = "DBI:$driver:DBNAME:$ip:database=$database";
my $username = "user";
my $password = "pass";
print "Connecting ...";
my $connection = DBI->connect($db, $username, $password)
or print "Couldn't connect to database: " . DBI->errstr . "\n\n";
print "Successful connection\n";
my $query = $connection->prepare("SELECT id FROM table");
$query->execute() or die $DBI::errstr;
while ( my #row = $query->fetchrow_array() ) {
my ($id) = #row;
print "ID = $id \n";
}
$query->finish();
Well, my problem is that when I run it from terminal using
perl test.cgi
it works fine, and I get the print results properly. The CGI script is located in /Library/Webserver/CGI-Executables/ and it is configured by default /cgi-bin/ in /etc/apache2/httpd.conf
If I execute it via the web browser, I just get the first print Connecting and nothing else, not even the or print from DBI->connect. I have been trying to realize what the error is, but I am unable to get a useful solution.
From your final comment it is as I suspected: the perl that the server is using simply doesn't have DBD::mysql installed, whereas your command-line perl does
Simply get that driver module installed on the server and all should be well
Note that is doesn't need to be "configured for Apache", it is simply that the copy of perl that is used by the CGI code doesn't have that module
By the way, the content type should be text/plain, not text/html: you're not generating HTML

Perl module to log in database and do a simple query?

I can't seem to figure out the issue with my .pm file and script. I am fairly new to Perl.
I have a database with name "project" and there is table with name "mailing".
mailing table has 7 entries, which I want to display using module.
So, I have this custom module to log in to database and do a query. This module is names as DB.pm
DB.pm is stored on my FEDORA 20 at /root/mysql/GUI/DB.pm.
DB.pm is defined as follows:
package GUI::DB;
use strict;
use DBI;
use vars qw(#ISA #EXPORT);
use Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(dbConnect query);
#
# dbConnect - connect to the database, get the database handle
#
sub dbConnect {
# Read database settings from config file:
print "Works";
my $dsn = "DBI:mysql:project";
my $dbh = DBI->connect( $dsn,
'root',
'mydatabasepassword',
{ RaiseError => 1 }
);
return $dbh;
}
#
# query - execute a query with parameters
# query($dbh, $sql, #bindValues)
#
sub query {
my $dbh = shift;
my $sql ="SELECT * FROM mailing";
my #bindValues = #_; # 0 or serveral parameters
my #returnData = ();
# issue query
my $sth = $dbh->prepare($sql); //**line number 39 that is giving** error
if ( #bindValues ) {
$sth->execute(#bindValues);
} else {
$sth->execute();
}
if ( $sql =~ m/^select/i ) {
while ( my $row = $sth->fetchrow_hashref ) {
push #returnData, $row;
}
}
# finish the sql statement
$sth->finish();
return #returnData;
}
1;
Now I want to use this module inside my per script. This is what I tried:
#!/usr/bin/perl
use warnings;
use strict;
use lib '/root/mysql/';
use GUI::DB qw(dbConnect query);
dbConnect();
query();
This is the error I'm getting -->
Can't call method "prepare" on an undefined value at /root/mysql/GUI/DB.pm line 39.
Please help me with this. I am not sure how to proceed. I am guessing it has something to do with argument passing. Nothing is wrong with database. It works fine from CLI.
Thanks :)
_x_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X__X_X_X_X_X__X
TILL HERE IT IS RESOLVED
_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X__X_X_X
FURTHER ISSUE is SQL command is not working.
In the mailing table of my database I have email id with different domains.
For example, some id's are xyz#gmail.com, 12343#gmail.com , bae#yahoo.com as so on and I am assuming new email ids will be added to mailing tables every day with different domains.
I am trying to write a scripts that updates another table which holds a daily count of email addresses by their domain name. This is what I tried:
#!/usr/bin/perl
use warnings;
use strict;
use lib '/root/mysql/';
use 5.016;
use Data::Dumper;
use GUI::DB qw(dbConnect query);
my $data = dbConnect();
my #domain = query($data, "SELECT substr(addr,locate('\#',addr)+1) as maildomain, count (*) as mailcount FROM mailing GROUP BY maildomain ORDER BY mailcount DESC");
for my $key (#domain){
say Dumper ($key);
}
But I am getting an error,
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '*) as mailcount FROM mailing GROUP BY maildomain ORDER BY mailcount DESC' at line 1 at /root/mysql/GUI/DB.pm line 44.
Same SQL statement works from CLI with no issues.
Any help would be appreciated. :)
1) Your error is saying that $dbh is undefined here:
sub query {
my $dbh = shift;
...
# issue query
my $sth = $dbh->prepare($sql); #<***LOOK HERE***
...which means $dbh must be undefined here:
sub query {
my $dbh = shift; #<***LOOK HERE***
...
# issue query
my $sth = $dbh->prepare($sql);
2) Let's see why. Your dbConnect() method returns $dbh:
sub dbConnect {
# Read database settings from config file:
print "Works";
my $dsn = "DBI:mysql:project";
my $dbh = DBI->connect(
$dsn,
'root',
'mydatabasepassword',
{ RaiseError => 1 }
);
return $dbh; #<***LOOK HERE*****
}
3) But, you call dbConnect() like this:
dbConnect();
Because you never save the return value anywhere, $dbh is discarded.
4) Furthermore, you call query() like this:
query();
Yet, you defined query() like this:
sub query {
my $dbh = shift;
The query() sub believes that the first argument will be the database handle--but you didn't call query() with any arguments.
You need to do this:
my $data_base_handle = dbConnect();
my #results = query($data_base_handle);
#do something with #results
Response to comment:
I printed #results, this is what I see HASH(0x1d05be8)
HASH(0x1d05ba0) HASH(0x1d05b58) HASH(0x1d05b10) HASH(0x1d05ac8)
HASH(0x1d05a80) HASH(0x1d05a38)
You wrote:
my $row = $sth->fetchrow_hashref;
...which asks DBI to return each row as a reference to a hash. Then you wrote:
push #returnData, $row;
...which pushed each hash reference into an array. So query() returns an array of hash references. The notation HASH(0x1d05be8) is what perl outputs when you print a hash reference.
If you want to see what's in those hashes, then do this:
use 5.016; #enable say()
use Data::Dumper;
...
...
for my $href (#results) {
say Dumper($href);
}
To access the data in a hash reference, you can do this:
use strict;
use warnings;
use 5.016;
use Data::Dumper;
my $href = {
c => 3,
a => 1,
b => 2,
};
my %hash = %{$href}; #dereference, {}, the reference into a hash, %
for my $key ( keys %hash ) {
say "$key $hash{$key}";
}
--output:--
c 3
a 1
b 2
Response to next comment:
(Answer posted in comments under op.)
By the way, perl is pretty good at text processing, so if you couldn't figure out the problem with your query, you could process the email addresses with perl:
use strict;
use warnings;
use 5.012;
use Data::Dumper;
use DBI;
use DBD::mysql;
# CONFIG VARIABLES
my $db_type = "mysql";
my $database = "my_db";
my $host = "localhost";
my $port = "3306";
my $user = "root";
my $pword = "";
# DATA SOURCE NAME
my $dsn = "dbi:$db_type:$database:$host:$port";
# PERL DBI CONNECT
my $dbh = DBI->connect($dsn, $user, $pword);
# PREPARE THE QUERY
my $tablename = "mailing";
my $select =<<"END_OF_SELECT";
select addr from $tablename
END_OF_SELECT
my $addr_aref = $dbh->selectcol_arrayref($select); #Returns a reference to a flat array containing all the email addresses
$dbh->disconnect;
my %count_for;
for my $addr (#{$addr_aref}) {
$addr =~ s/.*#//;
$count_for{$addr}++;
}
say Dumper(\%count_for);
--output:--
$VAR1 = {
'google.com' => 2,
'gorilla.com' => 1,
'yahoo.com' => 3
};

PERL::DBI Getting user databases in a list

I am trying to make a little script to extract databases/tables/columns from my database, but in the first step I couldn't move on, I am getting databases in strange list, please look:
#!/usr/bin/perl
use DBI;
$host = "localhost";
$user = "wnyclick_siteusr";
$pw = "Hank0402\$";
$dsn = "dbi:mysql:$database:localhost:3306";
$connect = DBI->connect($dsn, $user, $pw);
$databases = $connect->selectcol_arrayref('show databases');
use Data::Dumper;
print Dumper $databases;
executing this code giving me the following:
$VAR1 = [
'information_schema',
'wnyclick_sitedatawp'
];
How can I put this execution result in a list?
print #VAR1[0];
print #databases[0];
I just modified your code. Try the below code:
#!/usr/bin/perl -w
use DBI;
use DBD::mysql;
my $user = "wnyclick_siteusr";
my $pw = "Hank0402\$";
#Connecting Database
$dbh = DBI->connect( 'dbi:mysql:database=mysql;host=localhost;port=3306', '$user', '$pw' )
or die "Connection Error: $DBI::errstr\n";
$sql = "show databases";
$sth = $dbh->prepare($sql);
$sth->execute or die "SQL Error: $DBI::errstr\n";
while ( #row = $sth->fetchrow_array ) {
#print $row[1];
print "#row\n";
}

Deleting and updating data from database

I have created a code that connects to database and i want to delete data from database using a button the same for update. but i just can display data in a table and cant delete.
my $q= new CGI;
print $q->header;
print $q-> start_html(
-title => "",
);
# print $q->start_form;
## mysql user database name
my $db = "people";
## mysql database user name
my $user = "root";
## mysql database password
my $pass = "";
## user hostname : This should be "localhost" but it can be diffrent too
my $host="127.0.0.1";
## SQL query
my $query = "select ID,Name,Surname,Gender from person";
my $dbh = DBI->connect("DBI:mysql:$db:$host", $user, $pass);
my $sqlQuery = $dbh->prepare($query)
or die "Can't prepare $sqlQuery: $dbh->errstr\n";
my $rv = $sqlQuery->execute
or die "can't execute the query: $sqlQuery->errstr";
print start_form (-method => 'post', -action => "modify.pl" );
my #aRows;
while (my #data = $sqlQuery->fetchrow_array()) {
my $cRowId = hidden('ID', $data[0]);
my $bt1 = submit('action','delete');
my $bt2 = submit('action','update');
push #aRows, ($cRowId, $q->Tr($q->td([$data[1], $data[2], $data[3],$bt1,$bt2])));
}
print $q->table({-border =>'1', -align =>'center', -width => '100%'},
$q->Tr([$q->th([ 'Name', 'Surname', 'Gender', 'Delete', 'Update', ])]),
#aRows,
);
print $q->input({-type => 'button', -class => 'button', -onclick => "window.location.href='insert.pl';", -value => 'Shto'});
print $q->end_form;
print $q->end_html;
delete.pl
use CGI;
use CGI qw(standard);
use DBI;
use CGI::Carp qw(set_die_handler);
use CGI qw/:all/;
BEGIN {
sub handle_errors {
my $msg = shift;
print "content-type: text/html\n\n";
#proceed to send an email to a system administrator,
#write a detailed message to the browser and/or a log,
#etc....
}
set_die_handler(\&handle_errors);
}
my $q = CGI->new();
my $db = "people";
my $user = "root";
my $pass = "";
my $host="127.0.0.1";
my $dbh = DBI->connect("DBI:mysql:$db:$host", $user, $pass);
my $action = $q->param('action'){
given ($action){
when('delete'){
my $row_id = $q->param('ID');
my $sth = $dbh->prepare("DELETE FROM person WHERE ID = $row_id ") or die "Can't prepare $query: $dbh->errstr\n";
my $rv = $sth->execute() or die $DBI::errstr;
print "deleted";
my $sth->finish();
my $dbh->commit or die $DBI::errstr;
}
} }
I dont know where may be the problem
The vast majority of Perl CGI problems can be solved by:
Adding use strict and use warnings to your code
Fixing all of the errors that now appear in your error log
You assign a value to $row_id after you try to use that variable to create your query.
Additionally, using raw user input in SQL queries makes you vulnerable to XSS attacks. Rewrite your code to use parameterized queries
Do not use my if you do not want a new variable. Remove all my's from the method calls:
my $sth->finish();
my $dbh->commit or die $DBI::errstr;

How do I call MySQL stored procedures from Perl?

How do I call MySQL stored procedures from Perl? Stored procedure functionality is fairly new to MySQL and the MySQL modules for Perl don't seem to have caught up yet.
MySQL stored procedures that produce datasets need you to use Perl DBD::mysql 4.001 or later. (http://www.perlmonks.org/?node_id=609098)
Below is a test program that will work in the newer version:
mysql> delimiter //
mysql> create procedure Foo(x int)
-> begin
-> select x*2;
-> end
-> //
perl -e 'use DBI; DBI->connect("dbi:mysql:database=bonk", "root", "")->prepare("call Foo(?)")->execute(21)'
But if you have too old a version of DBD::mysql, you get results like this:
DBD::mysql::st execute failed: PROCEDURE bonk.Foo can't return a result set in the given context at -e line 1.
You can install the newest DBD using CPAN.
There's an example in the section on Multiple result sets in the DBD::mysql docs.
#!/usr/bin/perl
# Stored Proc - Multiple Values In, Multiple Out
use strict;
use Data::Dumper;
use DBI;
my $dbh = DBI->connect('DBI:mysql:RTPC;host=db.server.com',
'user','password',{ RaiseError => 1 }) || die "$!\n";
my $sth = $dbh->prepare('CALL storedProcedure(?,?,?,?,#a,#b);');
$sth->bind_param(1, 2);
$sth->bind_param(2, 1003);
$sth->bind_param(3, 5000);
$sth->bind_param(4, 100);
$sth->execute();
my $response = $sth->fetchrow_hashref();
print Dumper $response . "\n";
It took me a while to figure it out, but I was able to get what I needed with the above. if you need to get multiple return "lines" I'm guessing you just...
while(my $response = $sth->fetchrow_hashref()) {
print Dumper $response . "\n";
}
I hope it helps.
First of all you should be probably connect through the DBI library and then you should use bind variables. E.g. something like:
#!/usr/bin/perl
#
use strict;
use DBI qw(:sql_types);
my $dbh = DBI->connect(
$ConnStr,
$User,
$Password,
{RaiseError => 1, AutoCommit => 0}
) || die "Database connection not made: $DBI::errstr";
my $sql = qq {CALL someProcedure(1);} }
my $sth = $dbh->prepare($sql);
eval {
$sth->bind_param(1, $argument, SQL_VARCHAR);
};
if ($#) {
warn "Database error: $DBI::errstr\n";
$dbh->rollback(); #just die if rollback is failing
}
$dbh->commit();
Mind you i haven't tested this, you'll have to lookup the exact syntax on CPAN.
Hi, similar to above but using SQL exec. I could not get the CALL command to work. You will need to fill in anything that is within square brackets and remove the square brackets.
use DBI;
#START: SET UP DATABASE AND CONNECT
my $host = '*[server]*\\*[database]*';
my $database = '*[table]*';
my $user = '*[user]*';
my $auth = '*[password]*';
my $dsn = "dbi:ODBC:Driver={SQL Server};Server=$host;Database=$database";
my $dbh = DBI->connect($dsn, $user, $auth, { RaiseError => 1 });
#END : SET UP DATABASE AND CONNECT
$sql = "exec *[stored procedure name]* *[param1]*,*[param2]*,*[param3]*;";
$sth = $dbh->prepare($sql);
$sth->execute or die "SQL Error: $DBI::errstr\n";