Perl script executing mysql commands? - mysql

I'm new to Perl and was attempting to write a script on a RHEL box that will auto-configure a vanilla DB for new sites we create on our host. I already have the connect statement working and I'm able to connect and create a DB from the script (Used $dbh->do( qq(CREATE DATABASE $dbcreate) ); Is this the best way???), but I have a couple that I haven't been able to figure out how to make them work.
These are the mysql commands which I'm having issues with. Any suggestions? Thanks!
$dbh = DBI->connect("DBI:mysql:$db:$host", $user, $pass);
$dbh->do( qq(CREATE DATABASE $dbcreate) );
$dbh->do(qq(GRANT SELECT , INSERT , UPDATE , DELETE , CREATE , DROP , INDEX , ALTER , CREATE TEMPORARY TABLES , CREATE VIEW , SHOW VIEW , CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON `$dbcreate` . * TO 'moodle'#'%'`) );
$dbh->do( qq(FLUSH PRIVILEGES) );
$dbh->do( qq($dbcreate < MySQL_pristine.sql) );
$dbh->do( qq(USE $dbcreate) );
$dbh->do( qq(UPDATE md1_label SET content = REPLACE( content, "pristine", "$dbcreate")) );
$dbh->do( qq(UPDATE md1_label SET contents = REPLACE( contents, "pristine", "$dbcreate")) );
$dbh->do( qq(UPDATE md1_label SET questiontext = REPLACE( questiontext, "pristine", "$dbcreate")) );
DBD::mysql::db do failed: 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 'GRANT SELECT , INSERT , UPDATE , DELETE , CREATE , DROP , INDEX ,�' at line 1 at create-auto-db.pl line 52.
DBD::mysql::db do failed: 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 'test3 < MySQL_pristine.sql' at line 1 at create-auto-db.pl line 54.
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 56.
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 57.
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 58.

The main issue you've encountered is interpolation of strings with containing an at-sign. If you have something like qq{Here is my email: test#hotmail.com} - this fails because it tries to put a list variable #hotmail, which doesn't exist. Either use a backslash to escape it (i.e., qq{Here is my email: test\#hotmail.com}), or if you don't need to interpolate any variables, use the non-interpolating quote q{...}.
Having said that, you need to be a little careful with some of these statements. You're putting variable values into these SQL statements, and that is a risk for SQL injection attacks. I'd use $dbh->quote($dbcreate) to get a string version, and $dbh->quote_identifier($dbcreate) to get an identifier version of the value of $dbcreate, and embed those values in. This is much safer, as it will avoid somebody doing a Bobby Tables on you and giving you a database name like: db'; DROP TABLE mysql.user; '; or similar. DBI provides both string and identifier quoting, so you can get the right kinds of quoting as needed. For example:
my $quoted_id_dbcreate = $dbh->quote_identifier($dbcreate);
$dbh->do( qq(USE $quoted_id_dbcreate) );
Placeholders are usually better, but some of these admin statements probably won't support them, so using proper quoting to inject the values is likely to be necessary.

Two things stand out to me.
$dbh->do(qq(GRANT SELECT , INSERT , (snip), EXECUTE ON '$dbcreate' . * TO 'moodle'#'%'`) );
...you've got a trailing backtick that you probably don't intend.
$dbcreate < MySQL_pristine.sql
...isn't quite what you want. I think you're trying to do is to read that file in Perl, and iterate over each contained SQL statement, calling "$dbh->do()" against it. If you're very lucky, you have one line per statement in that .sql file.

Related

mysql DB Import script issue on version 5.6

I have a production server that hosts mysql 5.0 database. From there I exported the db backup script using export feature provided in phpmyadmin.
Now I want to restore database script on new server that 5.6 mysql. But when I run the import script I get following error:
Error Description:
unexpected character. (near at position mysql
On further investigation I found that the query was getting break at following location, please see image given below:
I noticed that this scring variable has 102129 Characters I also verified that I put '' in starting or in between then it does not break, but after n character it breaks & quite visible in phpmyadmin editor.
I am aware of using \' escape specifier, but this option is not useful in my case as this script is really long I manually can't replace such occurrances.
Please suggest any really healping solution.
Info:
While I was writing this post, I tried to execute the DB Script for single Record only (i.e., removing all other script) then i executed successfully. Therefore I can't identify the real reason for this issue.
Please suggest any db migration technique that I can use in this scenario.
Thanks
EDIT:
Following is the query that is being throwing exception on production phpmyadmin, but working elsewhere:
INSERT INTO `wp_options` (`option_id`, `option_name`, `option_value`, `autoload`, `blog_id`) VALUES
(297, 'wpcs_options', 'a:40:{s:5:"width";s:3:"973";s:6:"height";s:3:"399";s:12:"border_width";s:1:"0";s:12:"border_color";s:7:"#ffffff";s:11:"font_family";s:39:"\\''Trebuchet MS\\'', Helvetica, sans-serif";s:9:"font_size";s:2:"12";s:5:"color";s:7:"#000000";s:12:"heading_font";s:2:"18";s:13:"heading_color";s:7:"#ffffff";s:16:"background_color";s:7:"#ffffff";s:6:"update";s:7:"UPDATED";s:16:"square_per_width";s:1:"7";s:17:"square_per_height";s:1:"5";s:5:"delay";s:4:"3000";s:6:"sDelay";s:2:"30";s:7:"opacity";s:3:"0.7";s:10:"titleSpeed";s:3:"500";s:6:"effect";s:6:"random";s:10:"hoverPause";s:4:"true";s:24:"navigation_next_previous";s:4:"true";s:18:"navigation_buttons";s:4:"true";s:16:"navigation_color";s:7:"#000000";s:12:"show_excerpt";s:5:"false";s:11:"char_length";s:3:"200";s:10:"new_window";s:5:"false";s:5:"order";s:5:"false";s:12:"custom_image";s:4:"true";s:13:"post_category";s:1:"0";s:15:"number_of_posts";s:1:"4";s:19:"no_of_custom_images";s:1:"5";s:12:"slide_image1";s:92:"http://mydemozone.com/signaturewellnessv2/wp-content/plugins/content-slide/images/image1.jpg";s:16:"slide_imagelink1";s:60:"http://www.snilesh.com/resources/jquery/jquery-image-slider/";s:12:"slide_image2";s:92:"http://mydemozone.com/signaturewellnessv2/wp-content/plugins/content-slide/images/image2.jpg";s:16:"slide_imagelink2";s:132:"http://www.snilesh.com/resources/wordpress/wordpress-tips-and-tricks/wordpress-show-title-and-excerpt-of-child-pages-on-parent-page/";s:12:"slide_image3";s:92:"http://mydemozone.com/signaturewellnessv2/wp-content/plugins/content-slide/images/image3.jpg";s:16:"slide_imagelink3";s:90:"http://www.snilesh.com/resources/wordpress/wordpress-plugins/wordpress-news-ticker-plugin/";s:12:"slide_image4";s:92:"http://mydemozone.com/signaturewellnessv2/wp-content/plugins/content-slide/images/image4.jpg";s:16:"slide_imagelink4";s:66:"http://www.snilesh.com/resources/jquery/jquery-image-sliders-2010/";s:12:"slide_image5";s:92:"http://mydemozone.com/signaturewellnessv2/wp-content/plugins/content-slide/images/image5.jpg";s:16:"slide_imagelink5";s:65:"http://www.snilesh.com/resources/jquery/jquery-dynamic-selectbox/";}', 'yes', 0);
The above query returns following error:
Error
Static analysis:
1 errors were found during analysis.
Ending quote ' was expected. (near "" at position 349)
SQL query:
INSERT INTO `wp_options` (`option_id`, `option_name`, `option_value`, `autoload`, `blog_id`) VALUES (297, 'wpcs_options', 'a:40:{s:5:"width";s:3:"973";s:6:"height";s:3:"399";s:12:"border_width";s:1:"0";s:12:"border_color";s:7:"#ffffff";s:11:"font_family";s:39:"\\''Trebuchet MS\\'', Helvetica, sans-serif";s:9:"font_size";s:2:"12";s:5:"color";s:7:"
MySQL said: Documentation
#1064 - 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 ''a:40:{s:5:"width";s:3:"973";s:6:"height";s:3:"399";s:12:"border_width";s:1:"0";' at line 2

Perl mysql mac address error

I have the below perl extract:
$query = "INSERT INTO test (`MACADDR`)
VALUES ($MACADDR)";
print $query,"\n";
$db->do($query);
I got the below error when trying to insert to mysql and my mac address is 000E38F4E9CC:
DBD::mysql::db do failed: 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 '0E38F4E9CC)' at line 2 at insertmac.pl line 156.
Is perl mysql dbi able to insert mac address?
My other records is able to be inserted correctly except mac addresses.
Any idea?
Thanks.
As your passing in a string as a value you need to quote it
$query = "INSERT INTO test (`MACADDR`)
VALUES ('$MACADDR')";
Alternatively you can prepare it and use parameters
$query = "INSERT INTO test (`MACADDR`)
VALUES (?)";
my $q = $db->prepare($query);
$q->execute($MACADDR);
which is a better idea as you can reuse it for speed and it also avoid SQL injection attacks

Insert SQL code into database in PHP/MySQL

I'm trying to write sql to insert a SQL code into one of the table's columns.
The table has these three columns: email, verification code, sql.
I try this code, and variations of it, playing around with the quotes and backslashing/escaping them, etc... but something's still wrong:
INSERT INTO pre_registration(email, verification_code, sql) VALUES('myemail#gmail.com', '8efb100a295c0c690931222ff4467bb8', '"INSERT INTO customer(title) VALUES(\'Mr.\')"')
It tells me there's an error in the SQL syntax:
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 'sql) VALUES('myemail#gmail.com', '89f0fd5c927d466d6ec9a21b9ac34ffa', "INSER' at line 1
How to do it? I'm using PHP/MySQL.
MySQL considers sql as a keyword. You have to quote it:
INSERT INTO pre_registration(email, verification_code, `sql`) VALUES('myemail#gmail.com', '8efb100a295c0c690931222ff4467bb8', '"INSERT INTO customer(title) VALUES(\'Mr.\')"')
By the way double the quotes to escape them instead of using bakslashes. This is more SQL friendly.
INSERT INTO pre_registration(email, verification_code, `sql`) VALUES('myemail#gmail.com', '8efb100a295c0c690931222ff4467bb8', '"INSERT INTO customer(title) VALUES(''Mr.'')"')
Some insight into the exact SQL error would help. At first glance I'd say you need to apply spaces between the table name and the open parentheses and between values and the open parentheses.
Also, the Single quotes around the double quotes for the SQL portion may be creating an error though I am not certain. Whatever is between the single quotes is interpreted literally which should make the escape characters actually be slashes inside the stored data.
Also, sql is a reserved word that must be quoted for use.
Finally, depending on your situation there may be a more secure method of data entry using prepare and bound parameters:
try
{
$conn = new PDO ( "sqlsrv:server = $serverstringname; Database = $logindatabase", "$loginusername", "$loginpassword");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch ( PDOException $e )
{
print( "Error connecting to SQL Server." );
die(print_r($e));
}
$email = 'myemail#gmail.com' //or some other way of setting the variable like $_POST
$verification_code = '#####' //or $_Post method
$sql = 'Put Query Here' //probably have to declare this explicitly
$sql_insert = "INSERT INTO pre_registration_info (email, verification_code, 'sql') VALUES (?,?,?)";
$stmt = $conn->prepare($sql_insert);
$stmt->bindValue(1, $email);
$stmt->bindValue(2, $verification_code);
$stmt->bindValue(3, $sql);
$stmt->execute();

Special Characters in Scriptella, jexl

I want to extract a text field from a database and insert it into some other database. So while extracting I used the REPLACE(message_text,'\'', '"') while selecting the test. I gave me an error. I changed that from my select statement and did it while initiating the global variable.
etl.globals['message_text'] = message_text;
still I'm getting an error at the insert statement
insert into lcs_al_user_likes(user_id,liked_user_id,post_content,loop_id) values('${etl.globals['posted_by']}','${etl.globals['liked_user_id']}','${etl.gl‌​obals['message_text']}',?batchLoopCounter);
saying
*You have an error in your SQL syntaxcheck the manual that corresponds to your MySQL server version for the right syntax to use near 'message_text']}')' at line 1*
I think it is not getting the global variable. That I say because when i print its value using log it just gives me
${etl.globals['message_text']}
as output. So please help me out here.
<query connection-id="lcsDBConnection">
SELECT forum_topic_post_id AS forum_topic_post_id, posted_by AS posted_by,message_text as message_text FROM lcs_tbl_forum_topic_post WHERE like_count>0 LIMIT ?batchSize OFFSET ?queryCounter ;
<script connection-id="jexl">
etl.globals['forum_topic_post_id'] = forum_topic_post_id;
etl.globals['posted_by'] = posted_by;
etl.globals['message_text'] = message_text.replace('\'', '"');
</script>
It looks like the problem is in INSERT statement, you should use prepared statement
parameters escaping:
INSERT INTO lcs_al_user_likes(user_id,liked_user_id,post_content,loop_id) values(?{etl.globals['posted_by']},?{etl.globals['liked_user_id']},?{etl.gl‌​obals['message_text']},?batchLoopCounter);
BTW As I understand, your original problem was quotes breaking the insert statement, so in this case with ?{parameter} syntax you don't need to use replace(...) function at all.

why mysql gives me a syntax error when there seems to be none?

The following code is runnable and works fine but if I change $dbh->do("set names utf8"); to $dbh->do("set names gbk");, I will receive a syntax error:
use strict;
use warnings;
use DBD::mysql;
my $dbh = DBI->connect("DBI:mysql:database=test;host=localhost","root","password");
$dbh->do("set names utf8");
open my $jpg, '<', 'test.jpg' or die "$!";
binmode $jpg;
my $image = do{local $/; <$jpg>};
close $jpg;
my $sql = "INSERT INTO student VALUES (?, ?)";
my $sth = $dbh->prepare($sql);
$sth->bind_param(1, 'Yang Liu');
$sth->bind_param(2, $image);
$sth->execute();
$sth->finish;
exit;
The syntax error reads as follows:
DBD::mysql::st execute failed: You have an error in your SQL syntax; check the m
anual that corresponds to your MySQL server version for the right syntax to use
near 'id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\' x
:xmptk' at line 1 at D:\sqltest.pl line 22.
DBD::mysql::st execute failed: You have an error in your SQL syntax; check the m
anual that corresponds to your MySQL server version for the right syntax to use
near 'id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\' x
:xmptk' at line 1 at D:\sqltest.pl line 22.
And the suspicious line that reads
'id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\'
is associated with the test.jpg image file which I'm trying to store to the longblob as I can find the same string if I open the image file using a text editor.
It's weird that code also works if I change $dbh->do("set names utf8"); to $dbh->do("set names gb2312"); Why the set names gbk statement gives me a syntax error? Is there something obvious that I'm doing wrong?
Thanks in advance:)
I'm running ActivePerl 5.10.1 and MySQL 5.5.
UPDATE
I've found the culprit!
This line local $/; is causing a MySQL syntax error. To fix the problem, simply comment out this line.
My Perl script is encoded in GBK and my database table encoding is also GBK, but I have to also add the set names to gbk to the DBI in perl, otherwise, GBK characters inserted into the table won't display properly in a GBK environment.
UPDATE2
I thought I had fixed the problem but the problem is actually still there. When I delete the local $/; line, there's no error message but the blob field contains a corrupted image file.
GBK is outdated, you must not use it anymore; and MySQL does not support the current standard GB 18030.
http://dev.mysql.com/doc/refman/5.5/en/faqs-cjk.html#qandaitem-B-11-1-1
http://www.gb18030.com/
http://zh.wikipedia.org/wiki/GB_18030
Work-around: do not set names, and deal with encoding of text in Perl only. Keep binary data such as images as octets.
use utf8;
use Encode qw(encode);
use Encode::HanExtra qw();
⋮
my $name = encode('GB18030', '刘阳', Encode::FB_CROAK | Encode::LEAVE_SRC);
$dbh->do(
'INSERT INTO student VALUES (?, ?)',
{},
$name, $image
);
(I have not tested this code.)
com/users/183467/mike ,
I solved this by using the function addslashes($img).
Without it the img var contain chars that need to be covered by a slash to allow them in database properly.. Otherwise, it seems such chars would blend with your sql code and get misread as syntax errors.
That's why even after you removed the appearance the error message the image was not stored the right way.