princepawn has asked for the wisdom of the Perl Monks concerning the following question:

I am very Unix-oriented. Part of my pipeline of creating and spitting SQL at a database consisted of this script:
#!/usr/bin/perl # whither strict? # use Text::Template? Template? HTML::Template? @in_data = qw(table id_field email_field state_field zip_field dob_fie +ld); sub USAGE { "Usage:\n\t$0 @in_data"; } @ARGV == @in_data or die USAGE; eval "\$$in_data[$i++] = '$_'" for @ARGV; print <<EOSQL SELECT $id_field, $email_field, $state_field, $zip_field, $dob_field FROM $table WHERE $zip_field like '336%' or $zip_field like '335%' or $zip_field like '346%' or $zip_field like '337%' or $zip_field like '342%' EOSQL

Now this was nice, but I did not want to cut and paste the top (the argument specs and the argument verification) into each and everyone of my SQL generator scripts.

So, here is my second incarnation

#!/usr/bin/perl # whither strict? # use Text::Template? Template? HTML::Template? use lib '/home/tbone/perl-modules/lib/perl5/site_perl/5.6.1'; use Text::Template::Script qw(table id_field email_field state_field zip_field dob_field); warn $table; __DATA__ SELECT $id_field, $email_field, $state_field, $zip_field, $dob_field FROM $table WHERE $zip_field like '336%' or $zip_field like '335%' or $zip_field like '346%' or $zip_field like '337%' or $zip_field like '342%'

And this is fine, but the DATAsection of the caller module is not getting passed

This node had a couple of solutions but neither worked. Presumably because the DATA filehandle is not open yet... is there anyway to get at the DATA section of a calling module in the import() section of another?

Carter's compass: I know I'm on the right track when by deleting something, I'm adding functionality

Replies are listed 'Best First'.
Re: Getting the DATA section of one module in the import() of another
by jand (Friar) on Aug 14, 2003 at 23:27 UTC
    Try using require instead of use. The DATA file handle is the same one that the Perl parser uses to read your script. By the time the use is executed, your script hasn't been completely compiled, so Perl didn't see the __DATA__ token and didn't create the connection yet. And if it did, then reading from DATA inside the used module would screw up the parsing of the rest of your script.

    The require however will execute at runtime, not compiletime, and DATA will be set up.

      Oops, sorry, that was incomplete.

      The require will of course not execute import(), so you will need to call it manually, which mean you should probably give it a different name.

      But either way, you won't be able to make this work from import() called by the use statement for the reasons given above.

Re: Getting the DATA section of one module in the import() of another
by antirice (Priest) on Aug 14, 2003 at 23:42 UTC

    I don't know how late you can get the information that you need, however if you don't need it before actual execution of code, this may do what you want.

    package SomethingOrAnother; BEGIN { my @incoming; my $otherdata; my $table; } INIT { local $/; $table = <$otherdata>; } sub import { my $self = shift; @incoming = @_; my ($caller) = caller; $otherdata = *{"$caller\::DATA"}; *{"$caller\::table"} = \${"$self\::table"}; } 1;

    Update: Noticed you used $table so made it into an export.

    Hope this helps.

    antirice    
    The first rule of Perl club is - use Perl
    The
    ith rule of Perl club is - follow rule i - 1 for i > 1

Re: Getting the DATA section of one module in the import() of another
by bart (Canon) on Aug 15, 2003 at 13:52 UTC
    Apparently you can't...

    Note: you didn't explicitely mention this, so I will: the DATA handle belongs to the package the end of the source file is in. For your script, that would be main::DATA. In case your proposed mechanism would have worked, it'd still have gotten broken if you had a package statement before the end of the script.

    Now, as for alternatives: you could add an explicit sub call that gets the data. It works, but doesn't look all that nice:

    # The module: package Foo; sub get { my($caller) = caller; no strict 'refs'; local $/; scalar readline "$caller\::DATA"; } 1; # The main script: use Foo; print Foo->get; __DATA__ Whatever you want...

    As an alternative idea, you can use a here-doc instead of a DATA section. That way you can do it while importing. Like this:

    package Foo; sub import { shift; my($caller) = caller; no strict 'refs'; ${"$caller\::foo"} = shift; } 1; # The main script: use Foo << '_*_'; This is my data over two lines! _*_ print "\$foo = '$foo'\n";
Re: Getting the DATA section of one module in the import() of another
by graff (Chancellor) on Aug 16, 2003 at 22:05 UTC
    So, the intent is to print out a well-formed sql statement by running a command with table and field names as command-line args, and your point is that you want this approach to work for a variety of distinct sql statements. And you think you need a different perl script (using a different inventory of args) for each distinct statement?

    I would think you could do everything with a single script, and a bunch of distinct sql templates stored as plain text files; you could put commentary in the templates so that when the arg inventory on the command line happens to be inappropriate for the given template file, the poor user can get a clue as to what the correct usage should be. Just add the template file name as the first arg in the command usage.

    This approach could save a lot of typing on the command line, since the sql template files can contain actual field names (things that don't change when the query is used repeatedly), and you only need args (and placeholders in the templates) for conditional values (things that are different just about every time the query is used).

    But having said that, I look at your example again and scratch my head -- I don't understand what you're really doing... The command line args are supposed to provide the table name and field names, and the conditional values ('336%', etc) are hard coded? That seems backwards.

    I wonder if this might explain why you have a (perhaps large) number of distinct "SQL generator" scripts -- the part that should be parameterized is scripted, and vice-versa.

    (And I wonder what this has to do with being unix-oriented.)