Cannot locate dynamically declared array

M

minjie

Hello,

I'm trying to do the following: to retrive all table names from a
database and display them on a web application, and when a user selects
one table, display all its fields and the corresponding values on the
web. I'm doing it in Perl (ver 5.8.0). I can get the table names and
field names from the database alright. But when I dynamically composed
the field names as elements of an array, such as the following:

my $var_declaration = "my @" . $tablename . " = (";
foreach $fieldname (@fieldnames)
{
$var_declaration .= "'" . $fieldname . "', ";
}
...... # some processing to get rid of the last comma and add the
enclosing ")"

and then I do the following:
eval $var_declaration;
print $var_declaration;

the print statement did print the array as follows:
my @USER = ('NAME', 'ADDRESS1', 'ADDRESS2', 'CITY', 'STATE',
'ZIPCODE');

I thought the eval will actually declare @USER array. But when I
actually tried to use @USER in the following code, Perl found no
elements at all. I did a size on @USER and I got a 1(one) in return.
Does that mean eval cannot be used to dynamically declare an array? Is
there another way to do it, or is it not doable at all?

Thanks for any help.
 
T

Tad McClellan

I'm trying to do the following: to retrive all table names from a
database and display them on a web application,


So you have taint checking enabled then?

But when I dynamically composed
the field names as elements of an array, such as the following:
[snip]

eval $var_declaration;


Ack!

eval EXPR is the tool of *last* resort, there is nearly always
a better way, often involving references and/or hashes.


I thought the eval will actually declare @USER array.


An array reference would be the Right Way.

my $aref;
foreach my $fieldname (@fieldnames)
{
push @$aref, $fieldname;
}


Or, if you have lots of tables, then a HoL would be the most
natural data structure:


my %dbinfo;
foreach my $table (@tablenames)
{
# load @fieldnames for this table here
foreach my $fieldname (@fieldnames)
{
push @{ $dbinfo{$table} }, $fieldname;
}
}
print Dumper \%dbinfo;



See:

perldoc perlreftut
perldoc perlref
perldoc perllol
perldoc perldsc
 
T

Tad McClellan

my $var_declaration = "my @" . $tablename . " = (";
foreach $fieldname (@fieldnames)
{
$var_declaration .= "'" . $fieldname . "', ";
}
..... # some processing to get rid of the last comma


You don't need to get rid of the last comma...
 
B

Bob Walton

I'm trying to do the following: to retrive all table names from a
database and display them on a web application, and when a user selects
one table, display all its fields and the corresponding values on the
web. I'm doing it in Perl (ver 5.8.0). I can get the table names and
field names from the database alright. But when I dynamically composed
the field names as elements of an array, such as the following:

my $var_declaration = "my @" . $tablename . " = (";
foreach $fieldname (@fieldnames)
{
$var_declaration .= "'" . $fieldname . "', ";
}
..... # some processing to get rid of the last comma and add the
enclosing ")"

It is not necessary to get rid of the last comma in Perl. A
construction like: @a=(1,2,3,); is fine.
and then I do the following:
eval $var_declaration;
print $var_declaration;

the print statement did print the array as follows:
my @USER = ('NAME', 'ADDRESS1', 'ADDRESS2', 'CITY', 'STATE',
'ZIPCODE');

I thought the eval will actually declare @USER array. But when I
actually tried to use @USER in the following code, Perl found no
elements at all. I did a size on @USER and I got a 1(one) in return.
Does that mean eval cannot be used to dynamically declare an array? Is
there another way to do it, or is it not doable at all?

The problem is that you are creating a lexical variable in an
eval(). The lexical variable thus created goes out of scope as
soon as eval() returns, and is destroyed. You could instead
create a package global variable my simply removing the "my" (and
also the use strict;). But you would be far better off to
dispense with the idea of storing this stuff in variables named
by the tables of your database, and simply store it in a hash (a
hash of arrays in this case). That's what hashes were made for.
If you called the hash "tables", then something on the order of:

use Data::Dumper;
use warnings;
use strict;
my @fieldnames=('f1','f2','f3');
chomp @fieldnames;
my $tablename='table1';
my %tables;
for my $fieldname(@fieldnames){
push @{$tables{$tablename}},$fieldname;
}
print Dumper(\%tables);

should work nicely. And without all the nastiness of building
strings containing Perl code, along with the worries about such
things as: What if a table name is the same as another variable
in the program? What if a table name contains a character that
is not legal in a Perl variable name? What if the table name
were set by a hacker to something like ';rm -rf ?

....
 
M

minjie

Tad said:
So you have taint checking enabled then?

No. Thanks for this info! I'm new to Perl and I did not know about this
taint checking. I'll definitely enable it then, since it's considered a
law for web application (I read something about it after reading your
message).
But when I dynamically composed
the field names as elements of an array, such as the following:
[snip]

eval $var_declaration;


Ack!

eval EXPR is the tool of *last* resort, there is nearly always
a better way, often involving references and/or hashes.


I thought the eval will actually declare @USER array.


An array reference would be the Right Way.

my $aref;
foreach my $fieldname (@fieldnames)
{
push @$aref, $fieldname;
}


Or, if you have lots of tables, then a HoL would be the most
natural data structure:


my %dbinfo;
foreach my $table (@tablenames)
{
# load @fieldnames for this table here
foreach my $fieldname (@fieldnames)
{
push @{ $dbinfo{$table} }, $fieldname;
}
}
print Dumper \%dbinfo;



See:

perldoc perlreftut
perldoc perlref
perldoc perllol
perldoc perldsc

Thank you so much for all the info (including the other message you
sent after this)! I used your method (HoL) and it worked beautifully,
and it's a much more elegant way to do it.
 
M

minjie

Hello Bob, thank you very much for all the info! I combined yours with
Tad's and made my application work. It's a much better solution than
using eval !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top