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

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

I'm using DBD::Mock to simulate a MySQL connection. I'm running into an issue when trying to work with the mysql_insertid DBH attribute. Reading DBI::DBD, DBD/Mock.pm, and (what I can understand of) DBI.pm, I should be able to do the following:
use DBI; my $dbh = DBI->connect( 'dbi:Mock:', '', '' ) or die $DBI::errstr; $dbh->{mysql_insertid} = 10; print $dbh->{mysql_insertid}, $/; ----- 10

Except, mysql_insertid doesn't seem to be getting set, meaning that I am printing undef, not 10. Does anyone more knowledgable in this have any suggestions? (DBI 1.43, DBD::Mock 0.11, Perl 5.8.0, Solaris9)

------
We are the carpenters and bricklayers of the Information Age.

Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

I shouldn't have to say this, but any code, unless otherwise stated, is untested

Replies are listed 'Best First'.
Re: DBD::Mock and DBD-specific attributes
by stvn (Monsignor) on Aug 16, 2004 at 18:20 UTC

    You wont find that attribute in DBD::Mock since its specific to DBD::mysql. This is an interesting issue, and one that DBD::Mock should address. It actually seems like I might be taking over the maintance of this module from lachoy, so I will give some thought to how to address this. Any thoughts/suggestions on how you would like it to work are welcome.

    -stvn
      Regardless of how it works under the hood, if I set an attribute to $x, then ask for that attribute back, I should get $x, unless the docs indicate that the given attribute does something based on $x.

      Plus, in looking under the hood, DBD::Mock::db::STORE() calls to SUPER::STORE if it doesn't know about the attribute. From what I can discern (and from what I think DBI::DBD says), the attribute and value should be stored in the tied hash.

      Now, an interesting possibility to add to DBD::Mock would be an 'is_mocking' attribute in the connection parameters. So, I might want to say something like:

      my $dbh = DBI->connect( 'dbi:Mock:is_mocking=mysql', '', '' ) or die $ +DBI::errstr;

      And, there would be a DBD::Mock::mysql that would do the right thing with mysql_insertid (or DBD::Mock::Oracle with an ora_* attribute, etc.)

      ------
      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I shouldn't have to say this, but any code, unless otherwise stated, is untested

        If I am writing unit tests and I've misspelled the name of the attribute, I'd hope that my mistake would get caught.

        I'd suggest that any kind of 'is_mocking' attribute would know which attributes that module is supposed to support, and warn you about using unsupported attributes.

        After looking more closely at the source of DBD::Mock, I agree, it should work as you expect. After reading DBI::DBD I am convinced it should work as you expect. However, it does not. The really weird part of course is that it seems to works for other attributes like PrintError, RaiseError, etc. I am trying to figure it out right now, I will keep you updated.

        UPDATE
        Found this in the trace output:

        $h->{'mysql_insertid'}=10 ignored for invalid driver-specific attribut +e
        So it seems that DBI will skip over driver specific attributes. According to line 1554 of DBI.xs, only those attributes that start with 'private_', 'dbi_' or 'dbd_' are allowed, all others are ignored. However, this seems to contradict what it says in DBI::DBD
        The DBI will actually store and fetch driver-specific attributes (with all lowercase names) without warning or error, so there's actually no need to implement driver-specific any code in your FETCH and STORE methods unless you need extra logic/checks, beyond getting or setting the value.
        Hmmmm.

        -stvn
        Regardless of how it works under the hood, if I set an attribute to $x, then ask for that attribute back, I should get $x, unless the docs indicate that the given attribute does something based on $x.
        No, not with databse handle attributes AFAIK. DBI leaves the handling of all lower_cased handle attributes (method attributes are a different thing) to the drivers. If you set an attribute that the driver doesn't know about, the driver shouldn't be expected to give it back to you. In fact, the driver probably shouldn't allow you to set it. stvn you might consider adding code to ::db::STORE that dies if someone tries to set an unknown attribute.
Re: DBD::Mock and DBD-specific attributes
by stvn (Monsignor) on Aug 16, 2004 at 20:12 UTC
    dragonchild,

    I have made modifications to DBD::Mock to support the handling of arbitrary attributes that DBI does not seem to handle (it seems DBI handles anything with the following prefixes 'private_', 'dbi_' and 'dbd_'). Since I do not yet have official upload capabilities for DBD::Mock on CPAN yet, you will have to msg me and I can sent it to you.

    However, I am not sure that this is the best way to handle this though. I have a few ideas, and I would like to hear your opinion (and jZed's) of them.

    1. Leave it how it is, allowing arbitrary attributes to be stored and retrieved.
    2. When storing attributes like 'mysql_insert_id', you will be required to prefix it with 'mock_' ('mock_mysql_insert_id'). When you fetch them however, they can be called without the prefix ('mysql_insert_id').
    3. Allow the assignment of a callback function to handle such attributes. This would be called when either DBD::Mock of DBI could not handle it.
    And option 1 and 2 do not need to exclude option 3, they could likely co-exists together in some way. Personally I am leaning towards option 2 and maybe option 3 combined with it.

    Any thoughts?

    -stvn
      I would much prefer subclasses of DBD::Mock for specific DBD's that would work in addition to the base DBD::Mock. The idea I would like to see is DBD-specific attributes to be handled by a mock of the specific DBD. You wouldn't have to use them, but you could, if you wanted to.

      Ideally, these subclasses would be in the DBD-Mock distribution, but would be supported by people who are expert in the specific DBD. For example, ideally, tbunce would support DBD::Mock::Oracle (or someone with a similar level of knowledge).

      I would be willing to come up with a basic implementation for mysql and Oracle, as those are the RDBMSes that I work with.

      Thoughts?

      ------
      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: DBD::Mock and DBD-specific attributes
by jZed (Prior) on Aug 16, 2004 at 18:24 UTC
    It looks to me like DBD::Mock, like most DBDs only stores lower-cased attributes that start with the driver's prefix, in this case mock_. So try mock_mysql_insert_id if you just want to try setting something, though it won't behave as it would under MySQL, I think you need MySQL for that (but I'm no DBD::Mock maven, just guessing).