FYI I've just added this info to the DBI::DBD docs:

=head4 The more_results method

If your driver doesn't support multiple result sets, then don't even implement 
this method.

Otherwise, this method needs to get the statement handle ready to fetch results
from the next result set, if there is one. Typically you'd start with:

    $sth->finish;

then you should delete all the attributes from the attribute cache that may no
longer be relevant for the new result set:

    delete $sth->{$_}
        for qw(NAME TYPE PRECISION SCALE ...);

for drivers written in C use:

    hv_delete((HV*)SvRV(sth), "NAME", 4, G_DISCARD);
    hv_delete((HV*)SvRV(sth), "NULLABLE", 8, G_DISCARD);
    hv_delete((HV*)SvRV(sth), "NUM_OF_FIELDS", 13, G_DISCARD);
    hv_delete((HV*)SvRV(sth), "PRECISION", 9, G_DISCARD);
    hv_delete((HV*)SvRV(sth), "SCALE", 5, G_DISCARD);
    hv_delete((HV*)SvRV(sth), "TYPE", 4, G_DISCARD);

Don't forget to also delete, or update, any driver-private attributes that may
not be correct for the next resultset.

The NUM_OF_FIELDS attribute is a special case. It should be set using STORE:

    $sth->STORE(NUM_OF_FIELDS => 0); /* for DBI <= 1.53 */
    $sth->STORE(NUM_OF_FIELDS => $new_value);

for drivers written in C use this incantation:

    /* Adjust NUM_OF_FIELDS - which also adjusts the row buffer size */
    DBIc_NUM_FIELDS(imp_sth) = 0; /* for DBI <= 1.53 */
    DBIS->set_attr_k(sth, sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0,
        sv_2mortal(newSViv(mysql_num_fields(imp_sth->result)))
    );

For DBI versions prior to 1.54 you'll also need to explicitly adjust the
number of elements in the row buffer array (C<DBIc_FIELDS_AV(imp_sth)>)
to match the new result set. Fill any new values with newSV(0) not &sv_undef.
Alternatively you could free DBIc_FIELDS_AV(imp_sth) and set it to null,
but that would mean bind_columns() woudn't work across result sets.

=cut

I've a patch for DBD::mysql.

Tim.

Reply via email to