How do I return a value if the prepare statement fails in the below code? - perl

sub loadFileRecon {
my $self = shift;
my $days = shift;
if($days eq '') {
$days = 1;
}
my $insert = $self->{rba}->rbdb->prepare(q{
insert into rba.filerecon (
filename,
records,
start_dtm,
file_type,
managed_file_id,
mf_dtm,
processed_tidemark,
mm_records,
mm_dropped,
mm_erred,
mm_duplicate,
file_source
)
select
i.filename,
i.records,
i.file_dtm start_dtm,
i.file_type,
mf.managed_file_id,
mf.created_dtm mf_dtm,
NULL,
i.orig_records,
i.dropped,
i.erred,
i.duplicate,
i.file_source
from rba.mmfilestats i, managedfile mf, filelog fl
where
i.filename = fl.file_name and
trunc(i.file_dtm) = trunc(sysdate - ?) and
mf.managed_file_id = fl.managed_file_id
}) or die $DBI::errstr;
$insert->execute($days);
$insert->finish;
$self->{rba}->rbdb->commit;
my $update = $self->{rba}->rbdb->prepare(q{
update rba.filerecon fr
set processed_tidemark = (
select processed_tidemark
from jobhasfile j
where j.managed_file_id = fr.managed_file_id
)
where
trunc(start_dtm) = trunc(sysdate - ?) and
processed_tidemark is null
});
$update->execute($days);
$insert->finish;
$self->{rba}->rbdb->commit;
}
If the prepare statement above fails due to table or view not existing, then it should return a value to perl module

you are telling your program to die if the prepare returns false:
}) or die $DBI::errstr;
replace that with what you're looking for:
}) or return $somevalue;
or remove the or entirely and check the value of your statement handle;
my $insert = $self->{rba}->rbdb->prepare(q{
...
});
return $somevalue if ( !$insert );

What you need to do is return the DBI::errstr. Do not die on error.
So do something like this (starting at your prepare and ending with your where but getting rid of the "or die"):
...prepare( ......
where
i.filename = fl.file_name and
trunc(i.file_dtm) = trunc(sysdate - ?) and
mf.managed_file_id = fl.managed_file_id
});
if ($DBI::errstr) {
# oops something is wrong
print $DBI::errstr;
call_error($DBI::errstr);
}
Good luck

Your post of the errorlog shows that your error is raised at point of execute not at the point of prepare.
So this what you do AFTER the execute:
#your execute statement first
$insert->execute($days);
#Now the check on the execute
if ($DBI::errstr) {
# oops something is wrong
return -1;
}
Please let me know if this works

Related

Returning an array using PDO

I'm trying to use PDO using the following code, I want to select the array of values for the context_list, but it returns one record, any ideas where I'm going wrong?
try {
$sql2 = "SELECT area_easting, area_northing, context_number FROM excavation.contexts";
$sth = $conn->prepare($sql2);
$sth->execute();
while ($row = $sth->fetch(PDO::FETCH_ASSOC))
{
$easting_list = $row['area_easting'];
$northing_list = $row['area_northing'];
$context_list = $row['context_number'];
}
}
catch(PDOException $e )
{
echo "Error: ".$e;
}
echo "context list: ";
echo $context_list;
A partial solution:
This worked:
$query = $conn->prepare("SELECT area_easting, area_northing, context_number FROM excavation.contexts");
$query->execute();
while($r = $query->fetch(PDO::FETCH_OBJ)){
echo $r->area_easting, '|';
echo $r->area_northing;
echo '<br/>';
}
But Now I need to make the $r->area_easting accessible to the session, but that's another question.
Your query may return several records (provided they actually exist in the table).
Your code loops through all the records (with the while loop) but the values ($easting_list, $northing_list and $context_list) are overwritten in the loop.
I suggest the following changes to your code:
$easting_list = array();
$northing_list = array();
$context_list = array();
try {
$sql2 = "SELECT area_easting, area_northing, context_number FROM excavation.contexts";
$sth = $conn->prepare($sql2);
$sth->execute();
while ($row = $sth->fetch(PDO::FETCH_ASSOC))
{
$easting_list[] = $row['area_easting'];
$northing_list[] = $row['area_northing'];
$context_list[] = $row['context_number'];
}
}
catch(PDOException $e )
{
echo "Error: ".$e;
}
echo "context list: ";
echo implode(', ', $context_list);
Now all the values are stored in 3 arrays. explode is used to print a comma-separated list of all values in $context_list array.

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?

Perl Hypertable mutator exception

I am using Hypertable::ThriftClient, and using mutator for mass insertion. Here is the code sample: $master, $port and $namespace are all defined.
Table:
show create table users; # Table schema is below
CREATE TABLE GROUP_COMMIT_INTERVAL "100" users (
'column_name_fake' MAX_VERSIONS 1,
ACCESS GROUP audience ('column_name_fake'),
)
:hypertable$ SELECT * FROM users limit 1; # displays
2342345 sf_following:1000234
2342346 sf_following:1234234
Code:
my $ht = new Hypertable::ThriftClient($master, $port);
my $ns = $ht->namespace_open($namespace);
my $users_mutator = $ht->mutator_open($ns, 'table_name', 2);
Subroutine:
sub batch_insert {
my ($ht, $mutator, $column_family, $row, $val) = #_;
my $keys;
my $cell;
try {
$keys = new Hypertable::ThriftGen::Key({
row => $row,
column_family => $column_family });
$cell = new Hypertable::ThriftGen::Cell({key => $keys, value => $val});
}
catch {
warn Dumper({ 'Error' => $_ });
};
$ht->mutator_set_cell($mutator, $cell);
$ht->mutator_flush($mutator);
return 1;
}
Function called:
for(.....) { # Just for example
batch_insert($ht, $users_mutator, '', $fs, "node:$node_u");
}
Here I get an exception,
Hypertable::ThriftGen::ClientException=HASH(0x54d7380)
Can anyone clarify, why?
Edit: I added table structure for more clarity?
The ClientException class is defined as follows:
exception ClientException {
1: i32 code
2: string message
}
Try catching the exception and printing out the code (in hex) and message. That should help pinpoint what's going on.
FIX: So, this exception is raised is a required parameter 'column_qualifier' was not
passed as per the table design. See below:
sub batch_insert {
my ($ht, $mutator, $cf, $cq, $row, $val) = #_;
my $keys = new Hypertable::ThriftGen::Key({
row => $row,
column_family => $cf,
column_qualifier => $cq });
my $cell = new Hypertable::ThriftGen::Cell({key => $keys, value => $val});
$ht->mutator_set_cell($mutator, $cell);
#$ht->mutator_flush($mutator);
}
Calling the above function:
--------------------------
batch_insert($ht, $users_mutator, 'column_family' , 'column_qualifier, 'row_key', '');
and it worked like a charm. If you are in similar types of issues, Let me know, I can help out. I spent quite a bit of time, reading about the Thrift api.

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';
}

insert_id mysqli

I'm trying to return the inserted id from a mysql INSERT query. Each time I run the function I get 0 as the result. Can someone please explain at what point I can retrieve the value because although the script below executes I cannot retireve the inserted id. Probably done something stupid.
<?php
public function execSQL($sql, $params, $close){
$mysqli = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$stmt = $mysqli->prepare($sql) or die ("Failed to prepared the statement!");
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($params));
$this->insert_id($this->connection);
$stmt->execute();
if($close){
$result = $mysqli->affected_rows;
} else {
$meta = $stmt->result_metadata();
while ( $field = $meta->fetch_field() ) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $this->refValues($parameters));
while ( $stmt->fetch() ) {
$x = array();
foreach( $row as $key => $val ) {
$x[$key] = $val;
}
$results[] = $x;
}
$result = $results;
}
$stmt->close();
$mysqli->close();
return $result;
}
?>
Check $mysqli->insert_id after executing insert query.