0

I was hoping that someone might be able to assist me. I'm new to Perl and generally getting some good results from some small scripts I've written, however, I'm stuck on a nested while loop of a new script I'm working on.

The script I've put together performs two mysql select statements, and then places the results into to separate arrays. I then want to check from the first element in the first array against all of the results in the second array. Then move to the second element in the first array and check for against all results in the seconds array and so on.

The goal of the script is to find an IP address in the first array and see which subnets it fits into in the second...

What I find is happening is that the script runs through on only the first element on the first array and all elements on the second array, then stops.

Here is the extract of the perl script below - if anyone could point me int the right direction I would really appreciate it.

my @ip_core_wan_field;

while ( @ip_core_wan_field = $wan_core_collection->fetchrow_array() ) {
    my $coreipAddr = @ip_core_wan_field[1];
    my @ip_wan_field;
    while ( @ip_wan_field = $wan_collection->fetchrow_array() ) {
        my $ipAddr  = @ip_wan_field[1];
        my $network = NetAddr::IP->new( @ip_wan_field[4], @ip_wan_field[5] );
        my $ip      = NetAddr::IP->new($coreipAddr);

        if ( $ip->within($network) && $ip ne $ipAddr ) {
            print "$ip IS IN THE SAME subnet as $network \n";
        }
        else {
            print "$coreipAddr is outside the subnet for $network\n\n";
        }
    }
}
2
  • 1
    Without seeing the actual query, nor DB contents, it would be difficult to tell. fetchrow_array will cause it to exit if that is the full content of the query. Also, this is kind of a terribly inefficient search method, with a response that will be of order nm (n being the number of core_wan_field that is returned from the query to m being the wan_collection number. You could improve this by taking the results as sorted lists (either during the db query or in perl) and get something more along the lines of nlog(n)+m*log(m) search time. Commented May 16, 2014 at 1:13
  • In this case it wouldn't have helped but, when you have a Perl problem, make sure you have use strict and use warnings in your script. (Actually, make sure you have them at all time.) I can see you don't have warnings enabled, because perl would have suggested that you don't use things like @ip_wan_field[1]. Commented May 16, 2014 at 12:39

1 Answer 1

4

Your sql queries are single pass operations. If you want to loop over the second collection more than once, you need to either cache the values and interate over the cache, or rerun the query.

I would of course advise that you go with the first option using fetchall_arrayref

my $wan_arrayref = $wan_collection->fetchall_arrayref;

while ( my @ip_core_wan_field = $wan_core_collection->fetchrow_array() ) {
    my $coreipAddr = @ip_core_wan_field[1];

    for my $ip_wan_field_ref (@$wan_arrayref) {
        my @ip_wan_field = @$ip_wan_field_ref;

There are of course other ways to make this operation more efficient, but that's the crux of your current problem.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks you for your help. I added the sql query into the loop and now it's doing exactly what it needs to do. I feel a bit silly now as I made the assumption that I only had to read it in once and it was stored in the array...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.