Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Specialty database API.

by jkollar (Initiate)
on Mar 23, 2013 at 22:30 UTC ( #1025087=perlquestion: print w/replies, xml ) Need Help??
jkollar has asked for the wisdom of the Perl Monks concerning the following question:

I would like to create an API routine for accessing a proprietary database that has a SQL-like language syntax. For example, I would like to do something like the following:

my $value = ''; DBC ( '$value=DBrecord1,subrecord,field', '$x=DBrecord1,subrecord,field2', 'DBrecord1,subrecord,field3=55', 'DBrecord2,subrecord,field=$value' ); print "Copied $value from DBrecord1 to DBrecord2.\n"; print "Read $x from DBrecord1.\n"; print "Wrote 55 into DBrecord1.\n";

The essence of what I want to do is to have the DBC subroutine parse my specialty language into more primitive API routines that access the database. The issue I am having is in how to relate '$value' (notice that I have deliberately used single quotes to prevent variable interpolation into the string) to the corresponding Perl variable that is in the scope of the calling routine.

I have tried a less elegant syntax that uses references, but ultimately still encounter the problem of how to (I think) access the symbol table that is seen in the caller's scope. For example, I have tried the following:

DBC ( 'DBrecord1,subrecord,field' => \$value, 'DBrecord1,subrecord,field2' => \$x, 55 => 'DBrecord1,subrecord,field3', $value => 'DBrecord2,subrecord,field' );

This is a less intuitive syntax, and it does not quite satisfy my needs. If each command were to be submitted to the database and completed before the next command is started then this would work. However, for performance reasons I need to be able to submit the commands to the database at once (i.e. this is the reason that I am not just calling DBC four times with one command each time). What I really want to do in the example shown is to have DBC recognize that the same variable appears in both the 1st and 4th commands, and then to split the commands into two database submissions -- the first three commands in the first, and the 4th command in the second.

Given that I am willing to perform whatever complex parsing is required to make the original syntax work, is there a way that I can take a string such as '$value' and from it obtain a reference to the same-named variable in the callers variable scope?

An alternative way of doing this, such as the second syntax I described, would also be helpful. Or perhaps there is a way to use an eval or code-block trick (i.e. a "{}" block instead of the parameter list of a subroutine).

Any insights would be greatly appreciated.

Replies are listed 'Best First'.
Re: Specialty database API.
by rjt (Deacon) on Mar 23, 2013 at 23:33 UTC

    For the parsing of your language, Parse::RecDescent is usually my go-to for things like this. If your language is not that complex, you may be able to get by with regexes or somesuch, but if you think it's likely to get more complex in the future, the investment into a stronger parser might be worthwhile.

    As for accessing someone else's lexical variables in the way you describe, I'm not sure you can, at least not with pure Perl runtime. Have a look at perlguts for a little more information on what's going on behind the scenes. This can be a very dangerous road to go down that can open up many unforeseen consequences, such as what happens with tied variables, especially given the desired asynchronous behavior you've described.

    It won't exactly be trivial, but writing a Perl source filter will probably be the most straightforward way to accomplish what you want to do. If you've never worked with filters before, the link has some helpful examples, but the short version is that your custom filter would be given the text of the Perl source code you are running, upon which you can perform any text transformations you like, before Perl parses and compiles the source. So, you could conceivably detect and parse your "DBC" source from within the Perl source, and then convert it into those lower-level API calls you mentioned, before Perl sees it.

    Handling the asynchronous dependencies (such as $value being fetched on line 123, and needed again on line 126), will probably require you to maintain some sort of dependency tree. I predict debugging will be fun!

Re: Specialty database API.
by Anonymous Monk on Mar 23, 2013 at 23:12 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1025087]
Approved by davido
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2018-02-22 21:02 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (299 votes). Check out past polls.