How to use DBD::CSV to get column names row? - perl

I am using DBD::CSV to show csv data. The code I have is:
#! perl
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect("dbi:CSV:", undef, undef, {
f_dir => ".",
f_ext => ".txt/r",
f_lock => 2,
csv_eol => "\n",
csv_sep_char => "|",
csv_quote_char => '"',
csv_escape_char => '"',
csv_class => "Text::CSV_XS",
csv_null => 1,
csv_tables => {
info => {
file => "countries.txt"
}
},
FetchHashKeyName => "NAME_lc",
}) or die $DBI::errstr;
$dbh->{csv_tables}->{countries} = {
skip_first_row => 0,
col_names => ["a","b","c","d"],
raw_header => 1,
};
my $sth = $dbh->prepare ("select * from countries limit 1");
$sth->execute;
while (my #row = $sth->fetchrow_array) {
print join " ", #row;
print "\n"
}
The countries.txt file is like this:
ISO_COUNTRY|COUNTRY_NAME|REGION_CODE|REGION_NAME
AF|Afghanistan|A|Asia
AX|"Aland Islands"|E|Europe
AL|Albania|E|Europe
But when I ran this script, it returns
AF Afghanistan A Asia
I wanted it to return:
ISO_COUNTRY COUNTRY_NAME REGION_CODE REGION_NAME
Does any one know how to achieve this using DBD::CSV module?
Another question is why the col_names attribute setting didn't take effect?
How to make it return the following?
a b c d

$sth->{NAME}, $sth->{NAME_lc} and $sth->{NAME_uc} return a reference to an array containing the names.
my $sth = $dbh->prepare("select * from countries limit 1");
$sth->execute;
print "$_\n" for #{ $sth->{NAME} };

Related

Issue in Printing data from a hash table in perl

I am trying to process the data in a single file . i have to read the file and create a hash structure,get the value of fruitname append it to fruitCount and fruitValue and delete the line fruitName and write the entire output after the change is done.Given below is the content of file.
# this is a new file
{
date 14/07/2016
time 11:15
end 11:20
total 30
No "FRUITS"
Fruit_class
{
Name "fruit 1"
fruitName "apple.fru"
fruitId "0"
fruitCount 5
fruitValue 6
}
{
Name "fruit 2"
fruitName "orange.fru"
fruitId "1"
fruitCount 10
fruitValue 20
}
}
I tried with following code :
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %hash_table;
my $name;
my $file = '/tmp/fruitdir/fruit1.txt';
open my $fh, "<", $file or die "Can't open $file: $!";
while (<$fh>) {
chomp;
if (/^\s*fruitName/) {
($name) = /(\".+\")/;
next;
}
s/(fruitCount|fruitValue)/$name\.$1/;
my ($key, $value) = split /\s+/, $_, 2;
$hash_table{$key} = $value;
}
print Dumper(\%hash_table);
This is not working . I need to append the value of fruitname and print the the entire file content as output. Any help will be appreciated.Given below is the output that i got.
$VAR1 = {
'' => undef,
'time' => '11:15 ',
'date' => '14/07/2016',
'{' => undef,
'#' => 'this is a new file',
'total' => '30 ',
'end' => '11:20 ',
'No' => '"FRUITS"',
'Fruit_class' => undef,
'}' => undef
};
Expected hash as output:
$VAR1 = {
'Name' => '"fruit 1"',
'fruitId' => '"0" ',
'"apple_fru".fruitValue' => '6 ',
'"apple_fru".fruitCount' => '5'
'Name' => '"fruit 2"',
'fruitId' => '"0" ',
'"orange_fru".fruitValue' => '10 ',
'"orange_fru".fruitCount' => '20'
};
One word of advice before I continue:
Document your code
There are several logic errors in your code which I think you would have recognized if you wrote down what you thought each line was supposed to do. First, write down the algorithm that you would like to implement, then document how each step in the code implements a step in the algorithm. At the end you'll be able to see what you missed, or what part is not working.
Here are the errors that I see
You aren't ignoring lines that you shouldn't be parsing. For example, you're grabbing the '}' and '{' lines.
You aren't actually storing the name of the fruit. You grab it, but immediately start the next loop without storing it.
You're not keeping track of each structure. You need to start a new structure for each fruit.
Do you really want to keep the double quotes in the values?
Other things to worry about:
Are you guaranteed that the list of attributes is in that order? For example, can Name come last?
Here's some code which does what I think you want.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %hash_table;
my $name;
my #fruit;
my $file = '/tmp/fruitdir/fruit1.txt';
open my $fh, "<", $file or die "Can't open $file: $!";
while (<$fh>) {
chomp;
# save hash table if there's a close bracket, but
# only if it has been filled
if ( /^\s*}\s*$/ ) {
next unless keys %hash_table;
# save COPY of hash table
push #fruit, { %hash_table };
# clear it out for the next iteration
%hash_table = ();
}
# only parse lines that start with Name or fruit
next unless
my ( $key, $value ) =
/^
# skip any leading spaces
\s*
# parse a line beginning with Name or fruitXXXXX
(
Name
|
fruit[^\s]+
)
# need space between key and value
\s+
# everything that follows is a value. clean up
# double quotes in post processing
(.*)
/x;
# remove double quotes
$value =~ s/"//g;
if ( $key eq 'Name' ) {
$name = $value;
}
else {
$key = "${name}.${key}";
}
$hash_table{$key} = $value;
}
print Dumper \#fruit;
and here's the output:
$VAR1 = [
{
'fruit 1.fruitValue' => '6',
'fruit 1.fruitName' => 'apple.fru',
'Name' => 'fruit 1',
'fruit 1.fruitCount' => '5',
'fruit 1.fruitId' => '0'
},
{
'fruit 2.fruitName' => 'orange.fru',
'fruit 2.fruitId' => '1',
'fruit 2.fruitCount' => '10',
'fruit 2.fruitValue' => '20',
'Name' => 'fruit 2'
}
];

How to get "Var1" value of dumper in perl

When i use below code then it gives output, But i want "width", "file_media_type", "file_ext" values, But I am unable to get this value in individual. I am very new with Perl Please help me!
Code
use warnings ;
use strict;
use Image::Info qw[image_info];
use Data::Dumper;
my $file = 'd:\perl\test\a.jpg';
my $info = Dumper(image_info($file));
print $info;
Output
$VAR1 = {
'width' => 45,
'file_media_type' => 'image/png',
'file_ext' => 'png',
'PNG_Chunks' => [
'IHDR',
'gAMA',
'cHRM',
'IDAT',
'IEND'
],
'Chunk-cHRM' => ' z% Çâ ·  ÇF u0 O` :ù ?o',
'PNG_Filter' => 'Adaptive',
'color_type' => 'RGB',
'height' => 20,
'Gamma' => '0.45454',
'resolution' => '1/1',
'SampleFormat' => 'U8',
'Compression' => 'Deflate'
};
image_info($file) returns a hash reference. Looking at the dump you know the keys available (the keys are strings before =>)
$info = image_info($file);
foreach my $key ( qw/width file_media_type file_ext/ ){
print "$key:$info->{$key}\n";
}

dereferencing a multi-tiered hash in Perl

I cannot dereference the %spec_hash
Is it a multilevel hash?
#!/perl/bin/perl
use FOOConf; #custom module
use Data::Dumper ;
FOOConf::makeDBConnection(production);
use strict;
use warnings;
my $dbh=$EVTConf::dbh;
my $query = "select e_risk_symbol from gsd_etds where level_name='EXCH_CS' and e_exch_dest='XISX' and e_symbol_comment in ('Bin_6','Bin_56')";
if(!$dbh) {
print "Error connecting to DataBase; $DBI::errstr\n";
}
my $cur_msg = $dbh->prepare($query) or die "\n\nCould not prepare statement:".$dbh->errstr;
$cur_msg->execute();
while (my #row=$cur_msg->fetchrow_array) {
$spec_hash{'XISX'}{$row[0]}=1;
}
while(($key,$value) = each(%spech_hash)) {
print $key. "," .$value ;
}
I can see what is going into hash :
#!/perl/bin/perl
use strict;
use warnings ;
use FOOConf; # custom module we use for db access.
FOOConf::makeDBConnection(production); # amkes a database connection.
my $dbh=$EVTConf::dbh;
my $query = "select e_risk_symbol from gsd_etds where level_name='EXCH_CS' and e_exch_dest='XISX' and e_symbol_comment in ('Bin_6','Bin_56')";
if(!$dbh) {
print "Error connecting to DataBase; $DBI::errstr\n";
}
my $cur_msg = $dbh->prepare($query) or die "\n\nCould not prepare statement:".$dbh->errstr;
$cur_msg->execute();
while (my #row=$cur_msg->fetchrow_array) {
foreach $row(#row) {
print "$row ";
}
}
print "\n";
this is what i get ;
MTG GPS WM JBL ISIL MBI BA ILMN FCEL NDAQ CMS HOLX
INTC CYBX STLD MDT CTSH ASBC AMP KLAC LXK X MON
SYY HIG UNM AMGN STZ KMP SONC ECA BEBE EAT PLCE
SPN LAMR PDCO XLP GME CSGP EXC BHP
I can see what is getting loaded in to the $spec_hash by walking through the
#row array, and I can dump the %spec_hash
while (my #row=$cur_msg->fetchrow_array) {
$spec_hash{'XISX'}{$row[0]}=1;
}
print Dumper(%spec_hash)
In the dump is XISX the name of the hash and FCEL the key in hash XISX and the value of key FCEL is 1
foo#fooserver:/tmp/walt $ ./just_db.row.dumper
$VAR1 = 'XISX';
$VAR2 = {
'FCEL' => 1,
'GPS' => 1,
'MCO' => 1,
'DPZ' => 1,
'WM' => 1,
'SPLS' => 1,
'ILMN' => 1,
'BWLD' => 1,
'CTSH' => 1,
'EWU' => 1,
'MDVN' => 1,
'PDCO' => 1,
'AFAM' => 1,
'SHW' => 1,
I just can't dereference
"$spec_hash{'XISX'}{$row[0]}=1;"
there is somthing I don't understand about the way this hash is loaded.
Do this dump to see a better hash structure:
print Dumper(\%spec_hash);
To dereference you need:
while(my($key,$value) = each(%{$spech_hash{'XISX'}})) {

How to manually specify the column names using DBD::CSV?

I am using DBD::CSV to show csv data. Sometimes the file doesn't contain column names, so we have to manually define it. But after I followed the documentation, I got stuck with how to make the attribute skip_first_row work. The code I have is:
#! perl
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect("dbi:CSV:", undef, undef, {
f_dir => ".",
f_ext => ".txt/r",
f_lock => 2,
csv_eol => "\n",
csv_sep_char => "|",
csv_quote_char => '"',
csv_escape_char => '"',
csv_class => "Text::CSV_XS",
csv_null => 1,
csv_tables => {
info => {
file => "countries.txt"
}
},
FetchHashKeyName => "NAME_lc",
}) or die $DBI::errstr;
$dbh->{csv_tables}->{countries} = {
skip_first_row => 0,
col_names => ["a","b","c","d"],
};
my $sth = $dbh->prepare ("select * from countries limit 1");
$sth->execute;
while (my #row = $sth->fetchrow_array) {
print join " ", #row;
print "\n"
}
print join " ", #{$sth->{NAME}};
The countries.txt file is like this:
AF|Afghanistan|A|Asia
AX|"Aland Islands"|E|Europe
AL|Albania|E|Europe
But when I ran this script, it returns
AX Aland Islands E Europe
AF AFGHANISTAN A ASIA
I expected it to either return:
AF AFGHANISTAN A ASIA
a b c d
or
a b c d
a b c d
Does any know what's going on here?
For some reason, contrary to the documentation, it doesn't see the per-table settings unless you pass them to connect.
my $dbh = DBI->connect("dbi:CSV:", undef, undef, {
f_dir => ".",
f_ext => ".txt/r",
f_lock => 2,
csv_eol => "\n",
csv_sep_char => "|",
csv_quote_char => '"',
csv_escape_char => '"',
csv_class => "Text::CSV_XS",
csv_null => 1,
csv_tables => {
countries => {
col_names => [qw( a b c d )],
}
},
FetchHashKeyName => "NAME_lc",
}) or die $DBI::errstr;
Then it works fine:
my $sth = $dbh->prepare ("select * from countries limit 1");
$sth->execute;
print "#{ $sth->{NAME} }\n"; # a b c d
while (my $row = $sth->fetch) {
print "#$row\n"; # AF Afghanistan A Asia
}

How do I get schemas from Perl's DBI?

I am using Perl DBI. I know that $dbase->tables() will return all the tables in the corresponding database. Likewise, I want to know the schemas available in the database. Is there any function available for that?
What you're looking for is: DBI->table_info()
Call it like this:
my $sth = $dbh->table_info('', '%', '');
my $schemas = $dbh->selectcol_arrayref($sth, {Columns => [2]});
print "Schemas: ", join ', ', #$schemas;
This works.
Create a database:
echo 'create table foo (bar integer primary key, quux varchar(30));' | sqlite3 foobar.sqlite
Perl program to print schema:
use 5.010;
use Data::Dumper qw(Dumper);
use DBIx::Class::Schema::Loader qw();
DBIx::Class::Schema::Loader->naming('current');
DBIx::Class::Schema::Loader->use_namespaces(1);
my $dbi_dsn = 'dbi:SQLite:dbname=foobar.sqlite';
my ($dbi_user, $dbi_pass);
my $schema = DBIx::Class::Schema::Loader->connect(
$dbi_dsn, $dbi_user, $dbi_pass, {'AutoCommit' => 1, 'RaiseError' => 1,}
);
for my $source_name ($schema->sources) {
say "*** Source: $source_name";
my $result_source = $schema->source($source_name);
for my $column_name ($result_source->columns) {
say "Column: $column_name";
say Dumper $result_source->column_info($column_name);
}
}
Output:
*** Source: Foo
Column: bar
$VAR1 = {
'data_type' => 'integer',
'is_auto_increment' => 1,
'is_nullable' => 1
};
Column: quux
$VAR1 = {
'data_type' => 'varchar',
'is_nullable' => 1,
'size' => 30
};
Using ODBC to an Oracle database, I had to use this variation on Uncle Arnie's answer:
my $table_info = $dbh->table_info(undef, '%', undef);
my $schemas = $table_info->fetchall_arrayref([1]);
print "Schemas :\n",
join( "\n", map {$_->[0]} #$schemas ), "\n";
Otherwise, $schemas would be undefined when trying to use selectcol_arrayref($sth, ...).