http://www.perlmonks.org?node_id=744818


in reply to Re^3: Can DBI modify queries on the fly?
in thread Can DBI modify queries on the fly?

That's kind of the whole point, though, isn't it? The callback can't return any values. The only way to make any changes to what's going on is to modify the parameters directly. Or am I missing something?

As such, you have to worry about changing the application's data under its nose. You also have to watch out for the case where you're passed a read-only value.

  • Comment on Re^4: Can DBI modify queries on the fly?

Replies are listed 'Best First'.
Re^5: Can DBI modify queries on the fly?
by ikegami (Patriarch) on Feb 18, 2009 at 17:08 UTC

    What does modifying variables in the caller got to do with overriding a method? You haven't specified why you want to override the method, but I'm guessing "the point" is to change the values passed to your override then call the original method. How does modifying a variable that probably won't ever be used again help you?

      The callback functionality that perrin referred to does not override the method. Instead, I can insert a callback that is called before the real method. The callback is not allowed to return any value (doing so causes an exception).

      The only way to modify the behavior of the original method is to change the parameters that it gets. To do that, I have to change (the contents of) @_. The side effect is that the original method's caller has its data changed also. The other problem I see is that I won't be allowed to do this at all if the parameter I'm interested in (the query) is a read-only value as in:

      my ($count) = $dbh->selectrow_array( 'SELECT count(*) FROM table' );

      Both of those are serious enough to make me want to go back to looking at some DBD subclass with an overridden method instead of using the callback, but I'm not sure it will be worth the effort.

        Notice the call to ->connect in the callback, overriding Sybase's? The callback mechanism provides a means of (conditional) overriding.

        $sybase_drh->{Callbacks} = { selectrow_array => sub { # Protect against recursion when calling overriden method. return if $in_callback; local $in_callback = 1; my ($drh, $sql, $attrs, @bind_values) = @_; # Do something to $sql, $attrs and/or @bind_values here... # Tell DBI not to call original connect method undef $_; return $drh->selectrow_array($sql, $attrs, @bind_values); }, };

        Note that it would probably make more sense to override prepare and/or execute than convenience methods such as selectrow_array.

        Update: Added code.

        Both of those are serious enough to make me want to go back to looking at some DBD subclass with an overridden method instead of using the callback, but I'm not sure it will be worth the effort.

        Using a different DBD is what I recommended, and I still do. You'll probably want it to act as a wrapper to an existing DBD.

        If you absolutely refuse to change the DSN, you can make your Wrapper DBD transparent by using the callback mechanism. Just like the linked example switches Sybase for Gofer, your callback would switch the original handle for a wrapped handle.