Code Comments
Programming Forum and web based access to our favorite programming groups.I'm reading the book Programming the Perl DBI to start work with
databases. The DBI portion I'm getting OK, but I find the reference
here to @$ confusing. (This code is based from the book.)
my $sth1 = $dbh->prepare("select 'SCM_ORDERS_OUT', message_index,
message_no, message_event, time_stamp, data from log");
$sth1->execute();
my @stash;
while ($array_ref = $sth1->fetchrow_arrayref) {
push @stash, [ @$array_ref ]; ##copy array contents
}
###dump stash contents
foreach $array_ref ( @stash ) {
print "Row: @$array_ref\n";
}
The rows print out fine, so it "works", but I don't understand how. I
need to be able to work with specific items in the output, such as the
column "data". How would I reference it, using this example?
Peter Link
Post Follow-up to this messageOn 8/17/07, petelink1@yahoo.com <petelink1@yahoo.com> wrote: > I'm reading the book Programming the Perl DBI to start work with > databases. The DBI portion I'm getting OK, but I find the reference > here to @$ confusing. (This code is based from the book.) snip It is funny that you use the word reference, because $array_ref is a reference to an array (hence its name). There are several ways to access the array referenced by $array_ref. If you want a specific element you can say $array_ref->[0] if you want access to the whole array you can say @$array_ref. You can read more about reverences in perldoc perlreftut (also available as http://perldoc.perl.org/perlreftut.html).
Post Follow-up to this messagepetelink1@yahoo.com wrote:
> I'm reading the book Programming the Perl DBI to start work with
> databases. The DBI portion I'm getting OK, but I find the reference
> here to @$ confusing. (This code is based from the book.)
>
> my $sth1 = $dbh->prepare("select 'SCM_ORDERS_OUT', message_index,
> message_no, message_event, time_stamp, data from log");
>
> $sth1->execute();
>
> my @stash;
>
> while ($array_ref = $sth1->fetchrow_arrayref) {
> push @stash, [ @$array_ref ]; ##copy array contents
> }
>
> ###dump stash contents
> foreach $array_ref ( @stash ) {
> print "Row: @$array_ref\n";
> }
>
> The rows print out fine, so it "works", but I don't understand how.
@stash is an "Array of Arrays", so to start with I think you should
study "perldoc perllol".
> I need to be able to work with specific items in the output, such as
> the column "data". How would I reference it, using this example?
foreach my $row ( @stash) {
print "Data: $row->[5]\n";
}
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
Post Follow-up to this messagepetelink1@yahoo.com wrote:
> I'm reading the book Programming the Perl DBI to start work with
> databases. The DBI portion I'm getting OK, but I find the reference
> here to @$ confusing. (This code is based from the book.)
>
> my $sth1 = $dbh->prepare("select 'SCM_ORDERS_OUT', message_index,
> message_no, message_event, time_stamp, data from log");
>
> $sth1->execute();
>
> my @stash;
>
> while ($array_ref = $sth1->fetchrow_arrayref) {
> push @stash, [ @$array_ref ]; ##copy array contents
> }
>
> ###dump stash contents
> foreach $array_ref ( @stash ) {
> print "Row: @$array_ref\n";
> }
>
> The rows print out fine, so it "works", but I don't understand how. I
> need to be able to work with specific items in the output, such as the
> column "data". How would I reference it, using this example?
The term '@$' is a de-reference of a reference.
To be exact, $array_ref holds a reference to an array. To access the array
you need to de-reference it. There are two ways to doing it. The following
are equivalent.
@$array_ref
@{ $array_ref }
You can use these anywhere you use an array:
push @$array_ref, $some_data;
if( grep { /$pattern/ } @{ $array_ref } ){
..
}
--
Just my 0.00000002 million dollars worth,
Shawn
"For the things we have to learn before we can do them, we learn by doing th
em."
Aristotle
Post Follow-up to this messageOn Aug 17, 5:07 pm, peteli...@yahoo.com wrote:
> I'm reading the book Programming the Perl DBI to start work with
> databases. The DBI portion I'm getting OK, but I find the reference
> here to @$ confusing. (This code is based from the book.)
>
> my $sth1 = $dbh->prepare("select 'SCM_ORDERS_OUT', message_index,
> message_no, message_event, time_stamp, data from log");
>
> $sth1->execute();
>
> my @stash;
>
> while ($array_ref = $sth1->fetchrow_arrayref) {
> push @stash, [ @$array_ref ]; ##copy array contents
Is that seriously from the book? UGH. Just declare $array_ref in the
proper scope, and there's no need to take a reference to a dereference
of the reference.
while (my $array_ref = $sth1->fetchrow_arrayref) {
push @stash, $array_ref;
}
>
> }
>
> ###dump stash contents
> foreach $array_ref ( @stash ) {
> print "Row: @$array_ref\n";
>
> }
>
> The rows print out fine, so it "works", but I don't understand how. I
> need to be able to work with specific items in the output, such as the
> column "data". How would I reference it, using this example?
In this specific example, "data" is the sixth column in the SELECT
query. You would therefore access it by $array_ref->[5].
I would generally recommend you use the fetchrrow_hashref method
rather than fetchrow_arrayref, so that you can refer to the column by
name. This will prevent bugs in your code if you later change the
query to add or remove columns. With fetchrow_hashref, the return
value is a reference to a hash rather than to an array:
while (my $hash_ref = $sth1->fetchrow_hashref()) {
print $hash_ref->{data} . "\n";
}
I agree with other posters - you should read:
perldoc perlref
perldoc perlreftut
perldoc perllol
perldoc perldsc
Paul Lalli
Post Follow-up to this message>>>>> "Paul" == Paul Lalli <mritty@gmail.com> writes:
Paul> Is that seriously from the book? UGH. Just declare $array_ref in the
Paul> proper scope, and there's no need to take a reference to a dereference
Paul> of the reference.
Yes there is.
Paul> while (my $array_ref = $sth1->fetchrow_arrayref) {
Paul> push @stash, $array_ref;
Paul> }
Your code breaks on older versions of DBI, for which the book was written.
In older versions of DBI, the value of $array_ref would have been
the same for each row returned. There was this clause in "perldoc DBI":
Note that the same array reference is returned for each fetch, so don't
store the reference and then use it after a later fetch. Also, the elements
of the array are also reused for each row, so take care if you want to take
a reference to an element.
Yes, DBI has matured since the book, but I wouldn't jump to conclusions abou
t
the validity of the code in the book. After all, Tim Bunce co-wrote the boo
k,
and there's nobody on the planet who knows more about DBI.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training
!
Post Follow-up to this messageOn Aug 18, 10:03 pm, mer...@stonehenge.com (Randal L. Schwartz) wrote:
>
> Paul> Is that seriously from the book? UGH. Just declare $array_ref in t
he
> Paul> proper scope, and there's no need to take a reference to a dereferen
ce
> Paul> of the reference.
>
> Yes there is.
>
> Paul> while (my $array_ref = $sth1->fetchrow_arrayref) {
> Paul> push @stash, $array_ref;
> Paul> }
>
> Your code breaks on older versions of DBI, for which the book was written.
> In older versions of DBI, the value of $array_ref would have been
> the same for each row returned. There was this clause in "perldoc DBI":
>
> Note that the same array reference is returned for each fetch, so don't
> store the reference and then use it after a later fetch. Also, the eleme
nts
> of the array are also reused for each row, so take care if you want to t
ake
> a reference to an element.
Yeesh. I guess I'm fortunate to have only dealt with newer versions
of DBI.pm. :-)
Thanks for the history lesson.
Paul Lalli
Post Follow-up to this messageOn Aug 18, 7:58 pm, mri...@gmail.com (Paul Lalli) wrote:
snip
>
> Is that seriously from the book? UGH. Just declare $array_ref in the
> proper scope, and there's no need to take a reference to a dereference
> of the reference.
>
> while (my $array_ref = $sth1->fetchrow_arrayref) {
> push @stash, $array_ref;
>
> }
Great - this worked fine.
>
> In this specific example, "data" is the sixth column in the SELECT
> query. You would therefore access it by $array_ref->[5].
>
No luck here, I could not retrieve anything (example code below).
> I would generally recommend you use the fetchrrow_hashref method
> rather than fetchrow_arrayref, so that you can refer to the column by
> name. This will prevent bugs in your code if you later change the
> query to add or remove columns. With fetchrow_hashref, the return
> value is a reference to a hash rather than to an array:
>
> while (my $hash_ref = $sth1->fetchrow_hashref()) {
> print $hash_ref->{data} . "\n";
>
> }
I was able to replicate this and also do a push to an array, but
again, I could not retrieve rows.
> I agree with other posters - you should read:
> perldoc perlref
> perldoc perlreftut
> perldoc perllol
> perldoc perldsc
>
> Paul Lalli
Thanks to all who suggested these perldocs - the perlreftut and
perllol were especially helpful.
I've learned more about references and also about scoping of variables
- now I'm doing "use strict" and it took a while to make it work
here.
A side question: why is it necessary to declare "our @variable" more
than once in a program?
The main problem is that I still can't retrieve data at will.
See below:
First, as an array - I tried commented-out options one at a time.
Msg is error message from Perl.
$sth1->execute();
while (my $array_ref = $sth1->fetchrow_arrayref) {
push ((our @stash), $array_ref); ##copy array contents
}
#use Data::Dumper 'Dumper';
# print Dumper our @stash ; #Msg: $VAR19586 = $VAR1;
###dump stash contents
foreach my $array_ref (our @stash ) {
# print "Row: $array_ref->[5]\n"; #Msg:Use of uninitialized value in
concatenation
# print $array_ref->[5]; #Msg: Use of uninitialized value in
concatenation
print "Row: @$array_ref\n"; #works, prints entire rows (from book)
}
foreach my $row (our @stash) {
# print "DATA: $row->[5]\n"; #Msg: Use of uninitialized value in
concatenation or string
# print "DATA: @$row->[5]\n"; #Msg: Use of uninitialized value in join
or string
#}
Now as a hash, which is what I would prefer, for the reasons stated by
Paul.
$sth1->execute();
while (my $hash_ref = $sth1->fetchrow_hashref()) {
#print $hash_ref->{data} . "\n"; # works, prints data
push our @stash, [ %$hash_ref ]; #works, copies hash contents
}
#use Data::Dumper 'Dumper';
# print Dumper our @stash; #showed good results (see below)
foreach my $hash_ref (our @stash ) {
#print "Row: %$hash_ref\n"; #Msg: Row: %ARRAY(0x13f88d44)
#print "Row: $hash_ref\n"; #Msg: Row: %ARRAY(0x13f88d44)
#print %$hash_ref . "\n"; #Msg: 'Can't coerce array into hash at'
}
from hash Data Dumper:
$VAR790 = [
'time_stamp',
'Mon Mar 05 2007 11:07:11',
'message_event',
'MESSAGE OUT',
'message_no',
'12101589',
'data',
' MSH|^~\\&|HUB|HOSP.MED.XXXX.EDU|PM3.0|HOSP.MED.XXXX.EDU|200
',A|AA|9}|MESSAGE ACCEPTED||
'message_index',
'36314470'
];
$VAR791 = [
'time_stamp',
'Mon Mar 05 2007 11:07:11',
etc.....
What am I doing wrong?
Thanks for all the help.
Peter Link
Post Follow-up to this messageOn 8/24/07, Paul Lalli <mritty@gmail.com> wrote: snip > 'our', like 'my', is lexically scoped. Its effects are terminated > when the innermost enclosing block ends. So if you're using the same > package variable in two different blocks, you have to use 'our' in > each of them: snip > Your syntax for 'our' is confusing at best. Just declare it once, at > the very top of your program. snip > Again. Stop using 'our' all over the place. Declare your variables > once, at the beginning of your program, if it's being used throughout > the program. snip I can't say that I agree with the advice to declare all of your our variables once at the top of your program. To my way of thinking this defeats the purpose of having the our function*. I have a once-per-function rule for our; if a function needs to use a global variable, then it has to request it. This means that when you come back to the code a year later, and are looking at just that one function, you can easily see that the variable is special (i.e. used by many functions). That said, the code you were referring to was definitely overusing our. It doesn't need to be attached to every reference to the variable. * yes, the variable is still visible to all packages in the same file without having to be fully qualified, but I consider that aspect of our a misfeature.
Post Follow-up to this messagePaul Lalli wrote:
> 'our', like 'my', is lexically scoped. Its effects are terminated
> when the innermost enclosing block ends. So if you're using the same
> package variable in two different blocks, you have to use 'our' in
> each of them:
'our' is not lexically scoped; it is package scoped. Once you declare a var
iable using 'our' you may use it anywhere in the package. Think of it as an
alias to the fully-qualified variable. A variable declare via 'our' in one
package is independent of
a variable of the same name in another package.
See `perldoc -f our` for more details.
#!/usr/bin/perl
use strict;
use warnings;
package Foo;
our $bar = 'Foo's bar'; # $bar is an alias to $Foo::bar
print "$bar\n";
sub bar {
print "Foo::bar sub: $bar\n";
}
package main;
our $bar = 'main's bar'; # $bar is an alias to $main::bar or $::bar;
print "$bar\n";
print "$Foo::bar\n";
print "$main::bar\n";
print "$::bar\n";
Foo::bar();
__END__
--
Just my 0.00000002 million dollars worth,
Shawn
"For the things we have to learn before we can do them, we learn by doing th
em."
Aristotle
"If you think Terrans are comprehensible, you don't understand them."
Great Fang Talphon
Post Follow-up to this message
Show a Printable Version
Email This Page to Someone!
Receive updates to this thread
Powered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.