perl get info from database with selectrow_array - perl

I am working under perl. I am implementing a dynamic query and I have problems with this stuff , If you could give me a piece of advice during my searching.
Now, my static query:
my $envoi_numfact = $dbh->selectrow_array("SELECT envoi_numfact FROM user.envoi where envoi_reference='hapiness'");
print Dumper($envoi_numfact);
I have a nice result :
$VAR1 = '1611029546';
So I would like to transform it in dynamic query such as :
my $envoi_numfact = $dbh->selectrow_array("SELECT envoi_numfact FROM user.envoi where envoi_reference=?",undef,$hash_infos{ope_ref} );
Where $hash_infos{ope_ref} represents envoi_reference.
As a result, I have :
$VAR1 = undef;
Anyone couls help me ?

I am a winner ! I have just forgotten the closing bracket.
my $envoi_numfact = $dbh->selectrow_array("SELECT envoi_numfact FROM user.envoi where envoi_reference=?",undef,$hash_infos{ope_ref} );
becomes
my $envoi_numfact = $dbh->selectrow_array("SELECT envoi_numfact FROM user.envoi where envoi_reference = ?",undef,($hash_infos{ope_ref}));

Related

The if command is not performed as desire. Maybe due to non local variables?

I need to split two different types of records in a Perl program.
Every record comes with a distinct code (ZBKPF_W and ZBUS2081_W) so they have different processing depending on that.
The information comes from parsing the file name and at the end I should get the right command based on the right parsed fields.
However, the if command in Perl apparently does not obey it and in half of the cases, I get the wrong data.
Please allow me to show the process:
2 different types of documents to process that need to be split:
# get info from filename and process each file
# BO-CC-FY-DOCID-KOFAX#.PDF
# ZBKPF_W-DE10-2020-1900000001-00034113.PDF and
# ZBUS2081_W-DE10-2019-5106000000-00034114.PDF
( $fileindex, $filetype) = split( '\.', $dir[i] );
$fname = $dir[i];
$BO = "";
$CCode = "";
$FY = "";
$DocNo = "";
$KofaxNo = "";
$CCDocNoFY = "";
$CCFYDocNo = "";
# Get the index values from filename
( $BO, $CCode, $FY, $DocNo, $KofaxNo ) = split( '\-', $fileindex );
if ( $BO == "ZBKPF_W" ) {
$R3_SAP_OBJ = "ZBKPF_W";
$CCDocNoFY = $CCode.$DocNo.$FY;
$CCFYDocNo = $CCode.$FY.$DocNo;
}
else {
if ( $BO == "ZBUS2081_W" ) {
$R3_SAP_OBJ = "ZBUS2081_W";
$CCDocNoFY = $DocNo.$FY;
$CCFYDocNo = $FY.$DocNo;
}
}
So, at the end, all the records look like ZBUS2081_W
Results:
$R3_SAP_OBJ = "ZBBUS2081_W"
$CCDocNoFY = $DocNo.$FY
$CCFYDocNo = $FY.$DocNo
always provides the else of the if command.
The correct results should be:
For ZBKPF_W-DE10-2020-1900000001-00034113.PDF
$R3_SAP_OBJ = "ZBKPF_W"
$CCDocNoFY = "DE1019000000012020"
$CCFYDocNo = "DE1020201900000001"
For ZBUS2081_W-DE10-2019-5106000000-00034114.PDF
$R3_SAP_OBJ = "ZBUS2081_W"
$CCDocNoFY = "51060000002019"
$CCFYDocNo = "20195106000000"
I have tried to use nested IF, ELSEIF and also using local variables with MY
Same results... I don't usually prefer Perl, so I far from an expert but this is a requirement for ArchiveLink, so I need it to run smoothly.
Please, if you have an idea why could be the root cause of the issue, I will appreciate that.
== compares numbers in Perl. Use eq to compare strings.
When using a string starting with Z, it's coerced to number 0, so the first condition is always true.
See perlop for more details.

Can't call method "execute" on an undefined value

Whenever I'm executing the program below, I get the error message Can't call method "execute" on an undefined value from following line:
$sth->execute($agent_name,$service_id,$call_start_time,$call_end_time);
but in same program I'm able to execute the first SQL query indicated in the comments below:
#!/usr/bin/perl -w
use strict;
use DBI;
my $DSN = q/dbi:ODBC:SQLSERVER/;
my $uid = q/ivr/;
my $pwd = q/ivr/;
my $DRIVER = "Freetds";
my $dbh = DBI->connect($DSN,$uid,$pwd) or die "Coudn't Connect SQL";
my $servernumber = 2;
my $service_name = "JM";
my $agent_name= 'Balaji';
my $call_start_time='2013-07-01 15:46:50.865';
my $call_end_time='2013-07-15 15:46:50.789';
my $call_rec_file_name;
my $rows_fund = $dbh->selectrow_array("select count(service_name) from cti_services where service_name='$service_name'");
my $rows_agent = $dbh->selectrow_array("select count(agent_name) from cti_agents where agent_name='$agent_name'");
# This query successfully executes:
my $sql_fund = "select service_id from cti_services where service_name='$service_name'";
my $sth_fund = $dbh->prepare($sql_fund);
$sth_fund->execute() or die $DBI::errstr;
my $service_id = $sth_fund->fetchrow();
print $service_id,"\n";
if( $rows_fund == 1 && $rows_agent == 1 )
{
my $sql="select top(10) service_name,agent_name,call_rec_file_name,call_start_time,call_end_time from cti_agents join cti_call_master on (agent_name = call_agent_name) join cti_services on (call_service_id = service_id) where agent_name = ? and call_rec_file_name is not null and service_id=? and call_start_time between ? and ?";
my $sth = $dbh->prepare($sql);
# The problem is with this query. I'm getting the error "Can't call method "execute" on an undefined value".
$sth->execute($agent_name,$service_id,$call_start_time,$call_end_time);
print "Service Name","Agent Name","Call Start Time ","Call End Time","Sound File " ;
while (my #data = $sth->fetchrow_array())
{
my ($service_name,$agent_name,$call_rec_file_name,$call_start_time,$call_end_time ) = #data;
print "$service_name","$agent_name ","$call_start_time ","$call_end_time "," $call_rec_file_name ";
}
}
else
{
print "<em>","There is no data found","</em>";
}
$dbh->disconnect;
What could be causing the error message?
$sth is undefined because your call to $dbh->prepare is failing for some reason.
If you replace your DBI->connect() call with the following, you'll get the error from the prepare call rather than it failing silently and bombing out when you try to call execute:
my $dbh = DBI->connect($DSN,$uid,$pwd, { RaiseError => 1 });
You can read more about RaiseError and the other attributes available to DBI calls here: https://metacpan.org/module/DBI#RaiseError
I must admit I can't immediately see the error, my hunch is an SQL syntax issue, but I don't speak SQLServer.
Change the first two lines inside the if to this
my $sth = $dbh->prepare(<<__SQL__) or die $dbh->errstr;
SELECT TOP(10) service_name, agent_name, call_rec_file_name, call_start_time, call_end_time
FROM cti_agents
JOIN cti_call_master ON (agent_name = call_agent_name)
JOIN cti_services ON (call_service_id = service_id)
WHERE agent_name = ?
AND call_rec_file_name IS NOT NULL
AND service_id = ?
AND call_start_time BETWEEN ? AND ?
__SQL__
then you will see the reason for the error.
Note that there must be no spaces before or after __SQL__.
Put quotes inside the sql for the datetimes, it may be seeing the white space during parsing?

Passing variables into sqlplus query in perl

I'm having an issue here. I am trying to pass a variable into a sqlplus query, and it does not seem to be working.
my $connect = DBI->connect('DBI:Oracle:',$dbuser,$dbpasswd);
my $query = "select sum(transaction_amnt) from comm_to_cand natural join cmte_id_to_geo where cycle='?'", $cycle;
my $query_handle = $connect->prepare($query);
$query_handle->execute();
$cmte_money = $query_handle->fetchrow_array();
print 'Money: ';
print $cmte_money;
if($cmte_money > 0)
{
print 'HI';
}
else
{
print 'NOOOO';
}
I can get the query to work when I change the "cycles" variable from a variable to a constant, and the if statement checking will print hi, so the databases work I'm positive.
I've scoured the internet, and I can't seem to find an answer.
First, you mean to use a placeholder but you don't.
where cycle='?' -- This is a string
should be
where cycle=? -- This is a placeholder
And then there's problem that you don't actually pass a value for the placeholder.
$query_handle->execute();
should be
$query_handle->execute($cycle);
The replacements for placeholders get passed to execute, so:
my $query = "select sum(transaction_amnt) from comm_to_cand natural join cmte_id_to_geo where cycle=?";
my $query_handle = $connect->prepare($query);
$query_handle->execute($cycle);
The code you had would have triggered warnings if you had them enabled; make sure you do and that you figure out how to respond to any you get.
Here is an example:
use strict;
use DBI;
my $connect = DBI->connect('DBI:Oracle:', $dbuser, $dbpasswd);
my $query = "select sum(transaction_amnt) from comm_to_cand natural join cmte_id_to_geo where cycle = `$cycle`";
my $query_handle = $connect->prepare($query);
$query_handle->execute();
#cmte_money = $query_handle->fetchrow_array();
print 'Money: ';
print #cmte_money;
if($#cmte_money >= 0)
{
print 'HI';
}
else
{
print 'NOOOO';
}
I define a constant variable $cycle, I think like this.
my $connect = DBI->connect('DBI:Oracle:',$dbuser,$dbpasswd);
# Tell the DBI that the query uses bind variable with ? (question mark)
my $query = "select sum(transaction_amnt) from comm_to_cand natural join cmte_id_to_geo where cycle=?";
my $query_handle = $connect->prepare($query);
# Pass the value
$query_handle->execute($cycle); # assuming the variable is defined (otherwise it will pass as NULL into the query)
$cmte_money = $query_handle->fetchrow_array();
print 'Money: ';
print $cmte_money;
if($cmte_money > 0)
{
print 'HI';
}
else
{
print 'NOOOO';
}

Perl referencing and deferencing hash values when passing to subroutine?

I've been banging my head over this issue for about 5 hours now, I'm really frustrated and need some assistance.
I'm writing a Perl script that pulls jobs out of a MySQL table and then preforms various database admin tasks. The current task is "creating databases". The script successfully creates the database(s), but when I got to generating the config file for PHP developers it blows up.
I believe it is an issue with referencing and dereferencing variables, but I'm not quite sure what exactly is happening. I think after this function call, something happens to
$$result{'databaseName'}. This is how I get result: $result = $select->fetchrow_hashref()
Here is my function call, and the function implementation:
Function call (line 127):
generateConfig($$result{'databaseName'}, $newPassword, "php");
Function implementation:
sub generateConfig {
my($inName) = $_[0];
my($inPass) = $_[1];
my($inExt) = $_[2];
my($goodData) = 1;
my($select) = $dbh->prepare("SELECT id FROM $databasesTableName WHERE name = '$inName'");
my($path) = $documentRoot.$inName."_config.".$inExt;
$select->execute();
if ($select->rows < 1 ) {
$goodData = 0;
}
while ( $result = $select->fetchrow_hashref() )
{
my($insert) = $dbh->do("INSERT INTO $configTableName(databaseId, username, password, path)".
"VALUES('$$result{'id'}', '$inName', '$inPass', '$path')");
}
return 1;
}
Errors:
Use of uninitialized value in concatenation (.) or string at ./dbcreator.pl line 142.
Use of uninitialized value in concatenation (.) or string at ./dbcreator.pl line 154.
Line 142:
$update = $dbh->do("UPDATE ${tablename}
SET ${jobStatus}='${newStatus}'
WHERE id = '$$result{'id'}'");
Line 154:
print "Successfully created $$result{'databaseName'}\n";
The reason I think the problem comes from the function call is because if I comment out the function call, everything works great!
If anyone could help me understand what's going on, that would be great.
Thanks,
p.s. If you notice a security issue with the whole storing passwords as plain text in a database, that's going to be addressed after this is working correctly. =P
Dylan
You do not want to store a reference to the $result returned from fetchrow_hashref, as each subsequent call will overwrite that reference.
That's ok, you're not using the reference when you are calling generate_config, as you are passing data in by value.
Are you using the same $result variable in generate_config and in the calling function? You should be using your own 'my $result' in generate_config.
while ( my $result = $select->fetchrow_hashref() )
# ^^ #add my
That's all that can be said with the current snippets of code you've included.
Some cleanup:
When calling generate_config you are passing by value, not by reference. This is fine.
you are getting an undef warning, this means you are running with 'use strict;'. Good!
create lexical $result within the function, via my.
While $$hashr{key} is valid code, $hashr->{key} is preferred.
you're using dbh->prepare, might as well use placeholders.
sub generateConfig {
my($inName, inPass, $inExt) = #_;
my $goodData = 1;
my $select = $dbh->prepare("SELECT id FROM $databasesTableName WHERE name = ?");
my $insert = $dbh->prepare("
INSERT INTO $configTableName(
databaseID
,username
,password
,path)
VALUES( ?, ?, ?, ?)" );
my $path = $documentRoot . $inName . "_config." . $inExt;
$select->execute( $inName );
if ($select->rows < 1 ) {
$goodData = 0;
}
while ( my $result = $select->fetchrow_hashref() )
{
insert->execute( $result->{id}, $inName, $inPass, $path );
}
return 1;
}
EDIT: after reading your comment
I think that both errors have to do with your using $$result. If $result is the return value of fetchrow_hashref, like in:
$result = $select->fetchrow_hashref()
then the correct way to refer to its values should be:
print "Successfully created " . $result{'databaseName'} . "\n";
and:
$update = $dbh->do("UPDATE ${tablename}
SET ${jobStatus}='${newStatus}'
WHERE id = '$result{'id'}'");
OLD ANSWER:
In function generateConfig, you can pass a reference in using this syntax:
generateConfig(\$result{'databaseName'},$newPassword, "php");
($$ is used to dereference a reference to a string; \ gives you a reference to the object it is applied to).
Then, in the print statement itself, I would try:
print "Successfully created $result->{'databaseName'}->{columnName}\n";
indeed, fetchrow_hashref returns a hash (not a string).
This should fix one problem.
Furthermore, you are using the variable named $dbh but you don't show where it is set. Is it a global variable so that you can use it in generateConfig? Has it been initialized when generateConfig is executed?
This was driving me crazy when I was running hetchrow_hashref from Oracle result set.
Turened out the column names are always returned in upper case.
So once I started referencing the colum in upper case, problem went away:
insert->execute( $result->{ID}, $inName, $inPass, $path );

SeleniumRC/Perl dynamic XPath selector not working

This is more a question for XPath syntax than anything else.
I have multiple product pages on a site that have multiple products on each product pages. Each product has a unique ID for the add-to-cart button. I'm trying to return all of the unique ID's so that I can add a couple of the products to the bag. Searching with XPath seems to be the correct solution for this. I have the following code for querying the HTML with XPath and returning the unique ID's:
$XPATH_COUNT = $sel->get_xpath_count("//div[\#class='quick-info-link']/a");
#my_array;
$my_array[0] = $sel->get_attribute("//div[\#class='quick-info-link']/a/\#id");
print $my_array[0];
$count = 0;
while( $count < $XPATH_COUNT )
{
$arrayCount=0;
$a = "//";
foreach( #my_array )
{
$tmp = "a[\#id!='" . $my_array[$arrayCount] . "' and ";
$b .= $tmp;
$d .= "]";
$arrayCount++;
}
$c = "img[\#alt='Quick Shop']";
$e = $c . $d . "/\#id";
$xpath_query = $a . $b . $e;
$my_array[$count] = $sel->get_attribute($xpath_query);
$count++;
}
The output of the first run of this is an XPath query that looks like this:
//a[#id!='quickview-link-PROD7029' and img[#alt='Quick Shop']]/#id
Which correctly returns quickview-link-PROD6945. The second run produces this:
//a[#id!='quickview-link-PROD7029' and a[#id!='quickview-link-PROD6945' and img[#alt='Quick Shop']]]/#id
Which throws an error in my SeleniumRC terminal window of ERROR: Element [..xpath query..] not found on session.
I am aware of the possible use of indexes (i.e. adding an [i] to the end of the XPath query) to access elements on the page, however this isn't something that has worked for me in Selenium.
Any help would be great. Thanks for your time,
Steve
//a[#id!='quickview-link-PROD7029'
and a[#id!='quickview-link-PROD6945' and
img[#alt='Quick Shop']
]
]/#id
Which throws an error in my SeleniumRC
terminal window of ERROR: Element
[..xpath query..] not found on session
It would greatly help if you provide the XML document on which the XPath expression is applied and explain which node(s) you want to select.
Without this necessary information:
The most obvious reason for this problem is that the above expression is looking for a elements that have an a child with some property.
Usually an a element doesn't have any a children.
What you really want is something like:
//a[#id != 'quickview-link-PROD7029'
and
#id != 'quickview-link-PROD6945' and img[#alt='Quick Shop']
]/#id
This can be simplified a bit:
//a[img[#alt='Quick Shop']/#id
[not(. = 'quickview-link-PROD7029'
or
. = 'quickview-link-PROD6945'
)
]