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


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

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?

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

Replies are listed 'Best First'.
Re^6: Can DBI modify queries on the fly?
by kyle (Abbot) on Feb 18, 2009 at 18:11 UTC

    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.

        Thank you!! I remember reading about the conditional override that you're using, but I somehow forgot it when I sat down to try to meet my goal. That works beautifully and saves me the trouble of trying to subclass a DBD. Thanks!

      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.

        Using a different DBD is what I recommended, and I still do.

        Why do that over this (easier) callback method? It acts a lot like a wrapper, but I don't have to cough up a separate package.