How can I get output "Table created" with perl DBI - perl

There is a code I would like to get output with Perl DBI "Table created":
use DBI;
use DBD::Oracle qw(:ora_session_modes);
$dbh=DBI->connect( "dbi:Oracle:", "", "", { ora_session_mode =>
ORA_SYSDBA , RaiseError => 1, PrintError => 1 } );
$dbh->do(qq{ create table test ( customer_id number(10) NOT NULL ) } );
How can I get this output "Table created" from DBI?

I don't think you can get this answer directly from DBI. DBI does not really care about what it is executing, it just passes things to and fom the database. Only you (or the code you wrote) know that the statement you ran was a CREATE TABLE statement.
So if you want to print TABLE CREATED, or even TABLE test CREATED, you must check the return value as suggested by some other answers here and assemble the message yourself.

If the Query is not executed successfully print the error message.
$Local_Dbh->do($Query) or print " Unable to execute the query $Local_Dbh->errstr";
If the table is not created , It will return the undef or -1 otherwise return the value like
Result : 0E0

Related

Sybase Warning messages from perl DBI

I am connecting to sybase 12 from a perl script and calling storedprocs, I get the following warnings
DBD::Sybase::db prepare failed: Server message number=2401 severity=11 state=2 line=0 server=SERVER_NAME text=Character
set conversion is not available between client character set 'utf8' and server character set 'iso_1'.
Server message number=2411 severity=10 state=1 line=0 server=SERVER_NAME text=No conversions will be done.
at line 210.
Now, I understand these are only warnings, and my process works perfectly fine, but I am calling my stored proc in a loop and throughout the day and hence it creates a lot of warning message in my log files which causes the entire process to run a bit slower than expected. Can someone help me how can i suppress these please?
You can use a callback to handle the messages you want ignored. See the DBD::Sybase docs. The below is derived from the docs. You specify the message numbers you would like to ignore.
%blocked_msgs = map { $_ => 1 } ( 2401, 2411 );
sub err_handler {
my($err, $sev, $state, $line, $server, $proc, $msg, $sql, $err_type) = #_;
if ( exists $blocked_msgs{$err} ) { # it's a blocked message
return 0; # This is not an error
}
return 1;
}
This is how you might use it:
$dbh = DBI->connect('dbi:Sybase:server=troll', 'sa', '');
$dbh->{syb_err_handler} = \&err_handler;
$dbh->do("exec someproc");
$dbh->disconnect;

How to create trigger in DB with help of `DBIx::Class` using add_trigger method?

I want to add trigger into my database. I use DBIx::Class and follow these examples: 1, 2.
My code is:
package App::Schema;
use base qw/DBIx::Class::Schema/;
__PACKAGE__->load_namespaces();
sub sqlt_deploy_hook {
my ($self, $schema) = #_;
$schema->add_trigger( name => 'foo' );
}
1;
But I get this error:
Failed to translate to YAML: translate: Error with producer 'SQL::Translator::Producer::YAML': Can't call method "name" on an undefined value at /home/kes/work/projects/x/app/local/lib/perl5/SQL/Translator/Schema/Trigger.pm line 198
When run command with all environment variables as required by dbic-migration:
dbic-migration --force --schema_class App::Schema --database PostgreSQL -Ilib prepare
Which point me somewhere into SQL::Translator::Schema::Trigger
What did I miss? How to fix this error?
UPD
Even when I add all arguments I got error:
Failed to translate to YAML: translate: Error with parser 'SQL::Translator::Parser::DBIx::Class': Table named users doesn't exist at /home/kes/work/projects/x/app/local/lib/perl5/SQL/Translator/Schema/Trigger.pm line 54
Here the target line:
my $table = $args->{schema}->get_table($arg)
or die "Table named $arg doesn't exist";
Modified code:
sub sqlt_deploy_hook {
my ($self, $schema) = #_;
warn "TABLES: " ,$schema->get_tables ,"\n";
$schema->add_trigger(()
,name => 'foo'
,perform_action_when => 'after'
,database_events => 'insert'
,on_table => 'users'
,action => 'text'
,scope => 'row'
);
}
This code produce next warnings:
TABLES: users
TABLES: dbix_class_deploymenthandler_versions
But DB has only one table at the moment. I expect it at least should produce:
TABLES: users dbix_class_deploymenthandler_versions
How to create trigger in DB?
There maybe the problem with DBIx::Class::ResultSource::default_sqlt_deploy_hook:
which was originally designed to expect the Result class name and the $sqlt_table instance of the table being deployed
As work around add next line of code before add_trigger:
return unless grep $_ eq 'users', $schema->get_tables;
But the recommend way is to create deploy/upgrade/downgrade .sql files manually

Dancer::Tutorial connect to SQLite

I'm create database
sqlite3 database
create table if not exists entries (
id integer primary key autoincrement,
title string not null,
text string not null
);
^D
Where should i put this database ?
After
sub connect_db {
my $dbh = DBI->connect("dbi:SQLite:dbname=".setting('database')) or
die $DBI::errstr;
return $dbh;
}
sub init_db {
my $db = connect_db();
my $schema = read_file('./schema.sql');
$db->do($schema) or die $db->errstr;
}
get '/' => sub {
my $db = connect_db();
my $sql = 'select id, title, text from entries order by id desc';
my $sth = $db->prepare($sql) or die $db->errstr;
$sth->execute or die $sth->errstr;
template 'show_entries.tt', {
'msg' => get_flash(),
'add_entry_url' => uri_for('/add'),
'entries' => $sth->fetchall_hashref('id'),
};
};
Recieve an Error
Runtime Error
near "desk" : syntax error at /home/ultramozg/App/lib/App.pm line 40, line 16
What it's my mistake ?
I highly recommend you use Dancer::Plugin::Database instead of the connect_db routine you're proposing. The way you're doing it will probably create leftover open connections and therefore all sorts of problems. Dancer::Plugin::Database handles persistent connections for you. Doc for plugin:
https://metacpan.org/pod/Dancer::Plugin::Database
Once you install Dancer::Plugin::Database and configure it in config.yml, then whenever you need to a database handle, you just:
my $dbh => database('my_database_name');
and don't bother disconnecting when done.
If you're using ubuntu, just:
apt-get install libdancer-plugin-database-perl
Good luck on your project!
You have a ^D character for starters - last line in the first section. Please learn to read output. It tells you line 16.
Check where the word "desk" appears in your code as well.

Retrieve exception message from postgresql function

I have a trigger function on a table that runs on inserts which for certain circumstances will raise an exception.
I maintain an old Perl application running on Catalyst that creates a transaction and inserts rows on the table.
When the trigger function raises an exception, I'd like to be able to print out just the error message I throw and not any debugging information (database operation, context, perl file, etc).
So for example, if my function throws something like:
raise exception 'Item with id % cannot be shipped at this time.', new.id;
I would like to only see
Item with id 13 cannot be shipped at this time.
and not
DBIx::Class::Row::insert(): DBI Exception: DBD::Pg::st execute failed: ERROR: Item with id 13 cannot be shipped at this time. [for Statement "INSERT INTO ... at /home/../lib/Class/Controller/Inv.pm line 260
The perl code is currently something like
$c->model('Class')->schema->txn_do(sub {
...
eval {
$shipment->insert;
1;
} or do {
$error = $#;
last;
};
if ($error) {
$c->stash->{error} = $error;
}
);
Thank you.
Perhaps this substitution:
my $error = $#;
$error =~ s/^.*ERROR: (.*) \[for Statement.*$/$1/;
You could access the errstr() method of the database handle, which is what is what is passed to warn/die anyway
warn $c->model('Class')->schema->storage->dbh->errstr();

Unsure of Perl Datatype Referencing

I am trying to write a script using Net::IMAP::Client that outputs the body of a email, but so far every variable i try and output from the module shows up as something like: ARRAY(0x86f5524) or gives an error "Can't use an undefined value as a SCALAR reference."
The module documentation says that
# fetch full messages
my #msgs = $imap->get_rfc822_body([ #msg_ids ]);
print $$_ for (#msgs)
should contain references to a scalar. #msg_id should be an array of numbers for the email number in the inbox, but is also returned as an array reference.
I am unsure how to properly output this data so it is readable.
Here is the module reference: Net::IMAP::Client
and here is a snipit of my code:
use Net::IMAP::Client;
use Net::IMAP;
use Net::SMTP;
use strict;
use warnings;
my $imap = Net::IMAP::Client->new(
server => ,
user => , # i omitted this data for privacy
pass => ,
ssl => ,
port => ,
) or die "could not connect to IMAP server";
$imap->login or die('Login Failed: ' . $imap->last_error);
my $num_messages = $imap->select('[Gmail]/All Mail');
my #msg_id = $imap->search('ALL');
print #msg_id;
print "\n";
my #data = $imap->get_rfc822_body([#msg_id]);
print $$_ for (#data);
EDIT: I used Data::Dumper and got a big block of test containing the email and all the formatting tags. I also know that $imap-search should return something, as the inbox has 4 emails, 2 unread. But so since the variable #data IS holding the emails, i cant figure out the proper way to de-reference it in the output
$imap->search('ALL') returns an array reference not an array. So you need to change
my #msg_id = $imap->search('ALL');
to
my #msg_id = #{$imap->search('ALL')};
It would be better though to check whether the method returned a defined value before dereferencing, in case it fails.
Looking at the code, the proper usage is:
my $msgs = $imap->get_rfc822_body([ #msg_ids ]);
print $$_ for #$msgs;
The get the documented behaviour,
return $wants_many ? \#ret : $ret[0];
should be
return $wants_many ? (wantarray ? #ret : \#ret) : $ret[0];