I've looked a lots of ways to generate sql dynamically. I happen to like SQL::Interp quite a bit. You simply give it a list consisting of SQL and data structure references, and it generates SQL.

Pure SQL, I find very readable. Now, the problem with pure SQL is that it is not as easy to manipulate as a data structure.

So, the question is how to make sql manipulatable? Here's one approach: put any particular thing you might want to edit on a line by itself. In my case, all of my queries were the same except for the data range I was selecting.

The SQL::Interp data structure for today's data looks like this:

sub callbacks_for_today { my $username = shift or confess 'must supply username'; [" SELECT * FROM call_schedule INNER JOIN person ON (user_people_id=people.id) WHERE DATE_FORMAT( `callback_time` , '%Y-%m-%d' ) = DATE_FORMAT( NOW( ) , +'%Y-%m-%d' ) -- date_clause AND staff_people_id = users.people_id AND username =", \$username, " ORDER BY callback_time DESC "] }
Now, notice how one line is tagged with the SQL comment:  -- date_clause That is the primary way I wish to mod the SQL, so I cobbled up something to do it:
sub swap_sql { my ($sql_fragment, $sub_hint, $sub_expr) = @_; $sub_hint = "^.+-- $sub_hint"; # return data structures as is ref $sql_fragment and return $sql_fragment; $sql_fragment =~ s/$sub_hint/$sub_expr/m ; $sql_fragment; }
And then the code to gen sql for tomorrow just requests a line-oriented edit on today's SQL:
sub callbacks_for_tomorrow { my $username = shift or confess 'must supply username'; my $today_sql = callbacks_for_today($username); my $tomorrow_date_str = "DATE_FORMAT( `callback_time` , '%Y-%m-%d' + ) = DATE_FORMAT( DATE_ADD(NOW( ), INTERVAL 1 DAY) , '%Y-%m-%d' ) -- +date_clause"; my @tomorrow_sql = map (swap_sql($_, 'date_clause', $tomorrow_date +_str), @$today_sql); \@tomorrow_sql; }
It would be interesting to see how an ORM would allow for slicing, dicing and decorating a SQL query.

Replies are listed 'Best First'.
Re: line-oriented dynamic sql
by tilly (Archbishop) on Feb 13, 2009 at 16:23 UTC
    It looks like you are reinventing templates in a less readable and more complicated way. Just use one of the plethora of templating modules, and have a template for your SQL. Put whatever values you want in your template, and you're done.
      I appear guilty as charged... That's definitely something to think about...
Re: line-oriented dynamic sql
by zby (Vicar) on Feb 13, 2009 at 16:42 UTC
    Maybe you'll like Fey.
      I've looked closely at Fey as well as DBIx::Class and many others... SQL::Abstract, searchbuilder, CGI::Crud, etc, etc.

      They are not as close to pure SQL as I would like. There is a lot of object-oriented method calling which obscures my ability to think in SQL.