Blame Driver.xst

Packit Service b125fd
#  $Id$
Packit Service b125fd
#  Copyright (c) 1997-2002  Tim Bunce  Ireland
Packit Service b125fd
#  Copyright (c) 2002       Jonathan Leffler
Packit Service b125fd
#
Packit Service b125fd
#  You may distribute under the terms of either the GNU General Public
Packit Service b125fd
#  License or the Artistic License, as specified in the Perl README file.
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#include "Driver_xst.h"
Packit Service b125fd
Packit Service b125fd
# Historically dbd_db_do4, dbd_st_execute, and dbd_st_rows returned an 'int' type.
Packit Service b125fd
# That's only 32 bits (31+sign) so isn't sufficient for very large row counts
Packit Service b125fd
# So now instead of defining those macros, drivers can define dbd_db_do4_iv,
Packit Service b125fd
# dbd_st_execute_iv, and dbd_st_rows_iv to be the names of functions that
Packit Service b125fd
# return an 'IV' type. They could also set DBIc_ROW_COUNT(imp_sth).
Packit Service b125fd
#
Packit Service b125fd
# To save a mess of #ifdef's we arrange for dbd_st_execute (etc) to work
Packit Service b125fd
# as dbd_st_execute_iv if that's defined
Packit Service b125fd
#
Packit Service b125fd
#if defined(dbd_st_execute_iv)
Packit Service b125fd
#undef dbd_st_execute
Packit Service b125fd
#define dbd_st_execute dbd_st_execute_iv
Packit Service b125fd
#endif
Packit Service b125fd
#if defined(dbd_st_rows_iv)
Packit Service b125fd
#undef dbd_st_rows
Packit Service b125fd
#define dbd_st_rows dbd_st_rows_iv
Packit Service b125fd
#endif
Packit Service b125fd
#if defined(dbd_db_do4_iv)
Packit Service b125fd
#undef dbd_db_do4
Packit Service b125fd
#define dbd_db_do4 dbd_db_do4_iv
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
MODULE = DBD::~DRIVER~  PACKAGE = DBD::~DRIVER~
Packit Service b125fd
Packit Service b125fd
REQUIRE:    1.929
Packit Service b125fd
PROTOTYPES: DISABLE
Packit Service b125fd
Packit Service b125fd
BOOT:
Packit Service b125fd
    PERL_UNUSED_VAR(items);
Packit Service b125fd
    DBISTATE_INIT;
Packit Service b125fd
    /* XXX this interface will change: */
Packit Service b125fd
    DBI_IMP_SIZE("DBD::~DRIVER~::dr::imp_data_size", sizeof(imp_drh_t));
Packit Service b125fd
    DBI_IMP_SIZE("DBD::~DRIVER~::db::imp_data_size", sizeof(imp_dbh_t));
Packit Service b125fd
    DBI_IMP_SIZE("DBD::~DRIVER~::st::imp_data_size", sizeof(imp_sth_t));
Packit Service b125fd
    dbd_init(DBIS);
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
# ------------------------------------------------------------
Packit Service b125fd
# driver level interface
Packit Service b125fd
# ------------------------------------------------------------
Packit Service b125fd
MODULE = DBD::~DRIVER~  PACKAGE = DBD::~DRIVER~::dr
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
dbixs_revision(...)
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    ST(0) = sv_2mortal(newSViv(DBIXS_REVISION));
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_discon_all
Packit Service b125fd
Packit Service b125fd
# disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-(
Packit Service b125fd
void
Packit Service b125fd
discon_all_(drh)
Packit Service b125fd
    SV *        drh
Packit Service b125fd
    ALIAS:
Packit Service b125fd
        disconnect_all = 1
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_drh(drh);
Packit Service b125fd
    PERL_UNUSED_VAR(ix);
Packit Service b125fd
    ST(0) = dbd_discon_all(drh, imp_drh) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
Packit Service b125fd
#endif /* dbd_discon_all */
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_dr_data_sources
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
data_sources(drh, attr = Nullsv)
Packit Service b125fd
    SV *drh
Packit Service b125fd
    SV *attr
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    {
Packit Service b125fd
        D_imp_drh(drh);
Packit Service b125fd
        AV *av = dbd_dr_data_sources(drh, imp_drh, attr);
Packit Service b125fd
        if (av) {
Packit Service b125fd
            int i;
Packit Service b125fd
            int n = AvFILL(av)+1;
Packit Service b125fd
            EXTEND(sp, n);
Packit Service b125fd
            for (i = 0; i < n; ++i) {
Packit Service b125fd
                PUSHs(AvARRAY(av)[i]);
Packit Service b125fd
            }
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
# ------------------------------------------------------------
Packit Service b125fd
# database level interface
Packit Service b125fd
# ------------------------------------------------------------
Packit Service b125fd
MODULE = DBD::~DRIVER~    PACKAGE = DBD::~DRIVER~::db
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
_login(dbh, dbname, username, password, attribs=Nullsv)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    SV *        dbname
Packit Service b125fd
    SV *        username
Packit Service b125fd
    SV *        password
Packit Service b125fd
    SV *        attribs
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
#if !defined(dbd_db_login6_sv)
Packit Service b125fd
    STRLEN lna;
Packit Service b125fd
    char *u = (SvOK(username)) ? SvPV(username,lna) : (char*)"";
Packit Service b125fd
    char *p = (SvOK(password)) ? SvPV(password,lna) : (char*)"";
Packit Service b125fd
#endif
Packit Service b125fd
#ifdef dbd_db_login6_sv
Packit Service b125fd
    ST(0) = dbd_db_login6_sv(dbh, imp_dbh, dbname, username, password, attribs) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#elif defined(dbd_db_login6)
Packit Service b125fd
    ST(0) = dbd_db_login6(dbh, imp_dbh, SvPV_nolen(dbname), u, p, attribs) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#else
Packit Service b125fd
    PERL_UNUSED_ARG(attribs);
Packit Service b125fd
    ST(0) = dbd_db_login( dbh, imp_dbh, SvPV_nolen(dbname), u, p) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#endif
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
selectall_arrayref(...)
Packit Service b125fd
    PREINIT:
Packit Service b125fd
    SV *sth;
Packit Service b125fd
    SV **maxrows_svp;
Packit Service b125fd
    SV **tmp_svp;
Packit Service b125fd
    SV *tmp_sv;
Packit Service b125fd
    SV *attr = &PL_sv_undef;
Packit Service b125fd
    imp_sth_t *imp_sth;
Packit Service b125fd
    CODE:
Packit Service b125fd
    if (items > 2) {
Packit Service b125fd
        attr = ST(2);
Packit Service b125fd
        if (SvROK(attr) &&
Packit Service b125fd
                (DBD_ATTRIB_TRUE(attr,"Slice",5,tmp_svp) || DBD_ATTRIB_TRUE(attr,"Columns",7,tmp_svp))
Packit Service b125fd
        ) {
Packit Service b125fd
            /* fallback to perl implementation */
Packit Service b125fd
            SV *tmp =dbixst_bounce_method("DBD::~DRIVER~::db::SUPER::selectall_arrayref", items);
Packit Service b125fd
            SPAGAIN;
Packit Service b125fd
            ST(0) = tmp;
Packit Service b125fd
            XSRETURN(1);
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    /* --- prepare --- */
Packit Service b125fd
    if (SvROK(ST(1))) {
Packit Service b125fd
        MAGIC *mg;
Packit Service b125fd
        sth = ST(1);
Packit Service b125fd
        /* switch to inner handle if not already */
Packit Service b125fd
        if ( (mg = mg_find(SvRV(sth),'P')) )
Packit Service b125fd
            sth = mg->mg_obj;
Packit Service b125fd
    }
Packit Service b125fd
    else {
Packit Service b125fd
        sth = dbixst_bounce_method("prepare", 3);
Packit Service b125fd
        SPAGAIN; SP -= items; /* because stack might have been realloc'd */
Packit Service b125fd
        if (!SvROK(sth))
Packit Service b125fd
            XSRETURN_UNDEF;
Packit Service b125fd
        /* switch to inner handle */
Packit Service b125fd
        sth = mg_find(SvRV(sth),'P')->mg_obj;
Packit Service b125fd
    }
Packit Service b125fd
    imp_sth = (imp_sth_t*)(DBIh_COM(sth));
Packit Service b125fd
    /* --- bind_param --- */
Packit Service b125fd
    if (items > 3) {    /* need to bind params before execute */
Packit Service b125fd
        if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) {
Packit Service b125fd
            XSRETURN_UNDEF;
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    /* --- execute --- */
Packit Service b125fd
    DBIc_ROW_COUNT(imp_sth) = 0;
Packit Service b125fd
    if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */
Packit Service b125fd
        XSRETURN_UNDEF;
Packit Service b125fd
    }
Packit Service b125fd
    /* --- fetchall --- */
Packit Service b125fd
    maxrows_svp = DBD_ATTRIB_GET_SVP(attr, "MaxRows", 7);
Packit Service b125fd
    tmp_sv = dbdxst_fetchall_arrayref(sth, &PL_sv_undef, (maxrows_svp) ? *maxrows_svp : &PL_sv_undef);
Packit Service b125fd
    SPAGAIN;
Packit Service b125fd
    ST(0) = tmp_sv;
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
selectrow_arrayref(...)
Packit Service b125fd
    ALIAS:
Packit Service b125fd
        selectrow_array = 1
Packit Service b125fd
    PREINIT:
Packit Service b125fd
    int is_selectrow_array = (ix == 1);
Packit Service b125fd
    imp_sth_t *imp_sth;
Packit Service b125fd
    SV *sth;
Packit Service b125fd
    AV *row_av;
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    if (SvROK(ST(1))) {
Packit Service b125fd
        MAGIC *mg;
Packit Service b125fd
        sth = ST(1);
Packit Service b125fd
        /* switch to inner handle if not already */
Packit Service b125fd
        if ( (mg = mg_find(SvRV(sth),'P')) )
Packit Service b125fd
            sth = mg->mg_obj;
Packit Service b125fd
    }
Packit Service b125fd
    else {
Packit Service b125fd
        /* --- prepare --- */
Packit Service b125fd
        sth = dbixst_bounce_method("prepare", 3);
Packit Service b125fd
        SPAGAIN; SP -= items; /* because stack might have been realloc'd */
Packit Service b125fd
        if (!SvROK(sth)) {
Packit Service b125fd
            if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; }
Packit Service b125fd
        }
Packit Service b125fd
        /* switch to inner handle */
Packit Service b125fd
        sth = mg_find(SvRV(sth),'P')->mg_obj;
Packit Service b125fd
    }
Packit Service b125fd
    imp_sth = (imp_sth_t*)(DBIh_COM(sth));
Packit Service b125fd
    /* --- bind_param --- */
Packit Service b125fd
    if (items > 3) {    /* need to bind params before execute */
Packit Service b125fd
        if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) {
Packit Service b125fd
            if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; }
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    /* --- execute --- */
Packit Service b125fd
    DBIc_ROW_COUNT(imp_sth) = 0;
Packit Service b125fd
    if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */
Packit Service b125fd
        if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; }
Packit Service b125fd
    }
Packit Service b125fd
    /* --- fetchrow_arrayref --- */
Packit Service b125fd
    row_av = dbd_st_fetch(sth, imp_sth);
Packit Service b125fd
    if (!row_av) {
Packit Service b125fd
        if (GIMME == G_SCALAR)
Packit Service b125fd
            PUSHs(&PL_sv_undef);
Packit Service b125fd
    }
Packit Service b125fd
    else if (is_selectrow_array) {
Packit Service b125fd
        int i;
Packit Service b125fd
        int num_fields = AvFILL(row_av)+1;
Packit Service b125fd
        if (GIMME == G_SCALAR)
Packit Service b125fd
            num_fields = 1; /* return just first field */
Packit Service b125fd
        EXTEND(sp, num_fields);
Packit Service b125fd
        for(i=0; i < num_fields; ++i) {
Packit Service b125fd
            PUSHs(AvARRAY(row_av)[i]);
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    else {
Packit Service b125fd
        PUSHs( sv_2mortal(newRV((SV *)row_av)) );
Packit Service b125fd
    }
Packit Service b125fd
    /* --- finish --- */
Packit Service b125fd
#ifdef dbd_st_finish3
Packit Service b125fd
    dbd_st_finish3(sth, imp_sth, 0);
Packit Service b125fd
#else
Packit Service b125fd
    dbd_st_finish(sth, imp_sth);
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_db_do4 /* deebeedee-deebee-doo, deebee-doobee-dah? */
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
do(dbh, statement, params = Nullsv)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    char *      statement
Packit Service b125fd
    SV *        params
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    IV retval;
Packit Service b125fd
    retval = dbd_db_do4(dbh, imp_dbh, statement, params); /* might be dbd_db_do4_iv via macro */
Packit Service b125fd
    /* remember that dbd_db_do4 must return <= -2 for error     */
Packit Service b125fd
    if (retval == 0)            /* ok with no rows affected     */
Packit Service b125fd
        XST_mPV(0, "0E0");      /* (true but zero)              */
Packit Service b125fd
    else if (retval < -1)       /* -1 == unknown number of rows */
Packit Service b125fd
        XST_mUNDEF(0);          /* <= -2 means error            */
Packit Service b125fd
    else
Packit Service b125fd
        XST_mIV(0, retval);     /* typically 1, rowcount or -1  */
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_db_last_insert_id
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
last_insert_id(dbh, catalog, schema, table, field, attr=Nullsv)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    SV *        catalog
Packit Service b125fd
    SV *        schema
Packit Service b125fd
    SV *        table
Packit Service b125fd
    SV *        field
Packit Service b125fd
    SV *        attr
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    ST(0) = dbd_db_last_insert_id(dbh, imp_dbh, catalog, schema, table, field, attr);
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
commit(dbh)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh))
Packit Service b125fd
        warn("commit ineffective with AutoCommit enabled");
Packit Service b125fd
    ST(0) = dbd_db_commit(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
rollback(dbh)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh))
Packit Service b125fd
        warn("rollback ineffective with AutoCommit enabled");
Packit Service b125fd
    ST(0) = dbd_db_rollback(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
disconnect(dbh)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    if ( !DBIc_ACTIVE(imp_dbh) ) {
Packit Service b125fd
        XSRETURN_YES;
Packit Service b125fd
    }
Packit Service b125fd
    /* Check for disconnect() being called whilst refs to cursors       */
Packit Service b125fd
    /* still exists. This possibly needs some more thought.             */
Packit Service b125fd
    if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !PL_dirty) {
Packit Service b125fd
        STRLEN lna;
Packit Service b125fd
        char *plural = (DBIc_ACTIVE_KIDS(imp_dbh)==1) ? (char*)"" : (char*)"s";
Packit Service b125fd
        warn("%s->disconnect invalidates %d active statement handle%s %s",
Packit Service b125fd
            SvPV(dbh,lna), (int)DBIc_ACTIVE_KIDS(imp_dbh), plural,
Packit Service b125fd
            "(either destroy statement handles or call finish on them before disconnecting)");
Packit Service b125fd
    }
Packit Service b125fd
    ST(0) = dbd_db_disconnect(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
    DBIc_ACTIVE_off(imp_dbh);   /* ensure it's off, regardless */
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
STORE(dbh, keysv, valuesv)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    SV *        keysv
Packit Service b125fd
    SV *        valuesv
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    if (SvGMAGICAL(valuesv))
Packit Service b125fd
        mg_get(valuesv);
Packit Service b125fd
    ST(0) = &PL_sv_yes;
Packit Service b125fd
    if (!dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv))
Packit Service b125fd
        if (!DBIc_DBISTATE(imp_dbh)->set_attr(dbh, keysv, valuesv))
Packit Service b125fd
            ST(0) = &PL_sv_no;
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
FETCH(dbh, keysv)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    SV *        keysv
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    SV *valuesv = dbd_db_FETCH_attrib(dbh, imp_dbh, keysv);
Packit Service b125fd
    if (!valuesv)
Packit Service b125fd
        valuesv = DBIc_DBISTATE(imp_dbh)->get_attr(dbh, keysv);
Packit Service b125fd
    ST(0) = valuesv;    /* dbd_db_FETCH_attrib did sv_2mortal   */
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
DESTROY(dbh)
Packit Service b125fd
    SV *        dbh
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    /* keep in sync with default DESTROY in DBI.xs */
Packit Service b125fd
    D_imp_dbh(dbh);
Packit Service b125fd
    ST(0) = &PL_sv_yes;
Packit Service b125fd
    if (!DBIc_IMPSET(imp_dbh)) {        /* was never fully set up       */
Packit Service b125fd
        STRLEN lna;
Packit Service b125fd
        if (DBIc_WARN(imp_dbh) && !PL_dirty && DBIc_DBISTATE(imp_dbh)->debug >= 2)
Packit Service b125fd
             PerlIO_printf(DBIc_LOGPIO(imp_dbh),
Packit Service b125fd
                "         DESTROY for %s ignored - handle not initialised\n",
Packit Service b125fd
                    SvPV(dbh,lna));
Packit Service b125fd
    }
Packit Service b125fd
    else {
Packit Service b125fd
        if (DBIc_IADESTROY(imp_dbh)) {            /* wants ineffective destroy */
Packit Service b125fd
            DBIc_ACTIVE_off(imp_dbh);
Packit Service b125fd
            if (DBIc_DBISTATE(imp_dbh)->debug)
Packit Service b125fd
                 PerlIO_printf(DBIc_LOGPIO(imp_dbh), "         DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(dbh));
Packit Service b125fd
        }
Packit Service b125fd
        if (DBIc_ACTIVE(imp_dbh)) {
Packit Service b125fd
            if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) {
Packit Service b125fd
                /* Application is using transactions and hasn't explicitly disconnected.
Packit Service b125fd
                    Some databases will automatically commit on graceful disconnect.
Packit Service b125fd
                    Since we're about to gracefully disconnect as part of the DESTROY
Packit Service b125fd
                    we want to be sure we're not about to implicitly commit changes
Packit Service b125fd
                    that are incomplete and should be rolled back. (The DESTROY may
Packit Service b125fd
                    be due to a RaiseError, for example.) So we rollback here.
Packit Service b125fd
                    This will be harmless if the application has issued a commit,
Packit Service b125fd
                    XXX Could add an attribute flag to indicate that the driver
Packit Service b125fd
                    doesn't have this problem. Patches welcome.
Packit Service b125fd
                */
Packit Service b125fd
                if (DBIc_WARN(imp_dbh) /* only warn if likely to be useful... */
Packit Service b125fd
                &&  DBIc_is(imp_dbh, DBIcf_Executed) /* has not just called commit/rollback */
Packit Service b125fd
            /*  && !DBIc_is(imp_dbh, DBIcf_ReadOnly) -- is not read only */
Packit Service b125fd
                && (!PL_dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3)
Packit Service b125fd
                ) {
Packit Service b125fd
                    warn("Issuing rollback() due to DESTROY without explicit disconnect() of %s handle %s",
Packit Service b125fd
                        SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "ImplementorClass", 16, 1)),
Packit Service b125fd
                        SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "Name", 4, 1))
Packit Service b125fd
                    );
Packit Service b125fd
                }
Packit Service b125fd
                dbd_db_rollback(dbh, imp_dbh);                  /* ROLLBACK! */
Packit Service b125fd
            }
Packit Service b125fd
            dbd_db_disconnect(dbh, imp_dbh);
Packit Service b125fd
            DBIc_ACTIVE_off(imp_dbh);   /* ensure it's off, regardless */
Packit Service b125fd
        }
Packit Service b125fd
        dbd_db_destroy(dbh, imp_dbh);
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_take_imp_data
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
take_imp_data(h)
Packit Service b125fd
    SV * h
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_xxh(h);
Packit Service b125fd
    /* dbd_take_imp_data() returns &sv_no (or other defined but false value)
Packit Service b125fd
     * to indicate "preparations complete, now call SUPER::take_imp_data" for me.
Packit Service b125fd
     * Anything else is returned to the caller via sv_2mortal(sv), typically that
Packit Service b125fd
     * would be &sv_undef for error or an SV holding the imp_data.
Packit Service b125fd
     */
Packit Service b125fd
    SV *sv = dbd_take_imp_data(h, imp_xxh, NULL);
Packit Service b125fd
    if (SvOK(sv) && !SvTRUE(sv)) {
Packit Service b125fd
        SV *tmp = dbixst_bounce_method("DBD::~DRIVER~::db::SUPER::take_imp_data", items);
Packit Service b125fd
        SPAGAIN;
Packit Service b125fd
        ST(0) = tmp;
Packit Service b125fd
    } else {
Packit Service b125fd
        ST(0) = sv_2mortal(sv);
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_db_data_sources
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
data_sources(dbh, attr = Nullsv)
Packit Service b125fd
    SV *dbh
Packit Service b125fd
    SV *attr
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    {
Packit Service b125fd
        D_imp_dbh(dbh);
Packit Service b125fd
        AV *av = dbd_db_data_sources(dbh, imp_dbh, attr);
Packit Service b125fd
        if (av) {
Packit Service b125fd
            int i;
Packit Service b125fd
            int n = AvFILL(av)+1;
Packit Service b125fd
            EXTEND(sp, n);
Packit Service b125fd
            for (i = 0; i < n; ++i) {
Packit Service b125fd
                PUSHs(AvARRAY(av)[i]);
Packit Service b125fd
            }
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
# -- end of DBD::~DRIVER~::db
Packit Service b125fd
Packit Service b125fd
# ------------------------------------------------------------
Packit Service b125fd
# statement interface
Packit Service b125fd
# ------------------------------------------------------------
Packit Service b125fd
MODULE = DBD::~DRIVER~    PACKAGE = DBD::~DRIVER~::st
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
_prepare(sth, statement, attribs=Nullsv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        statement
Packit Service b125fd
    SV *        attribs
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    DBD_ATTRIBS_CHECK("_prepare", sth, attribs);
Packit Service b125fd
#ifdef dbd_st_prepare_sv
Packit Service b125fd
    ST(0) = dbd_st_prepare_sv(sth, imp_sth, statement, attribs) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#else
Packit Service b125fd
    ST(0) = dbd_st_prepare(sth, imp_sth, SvPV_nolen(statement), attribs) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#endif
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_st_rows
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
rows(sth)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    XST_mIV(0, dbd_st_rows(sth, imp_sth));
Packit Service b125fd
Packit Service b125fd
#endif /* dbd_st_rows */
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_st_bind_col
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
bind_col(sth, col, ref, attribs=Nullsv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        col
Packit Service b125fd
    SV *        ref
Packit Service b125fd
    SV *        attribs
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    IV sql_type = 0;
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    if (SvGMAGICAL(ref))
Packit Service b125fd
        mg_get(ref);
Packit Service b125fd
    if (attribs) {
Packit Service b125fd
        if (SvNIOK(attribs)) {
Packit Service b125fd
            sql_type = SvIV(attribs);
Packit Service b125fd
            attribs = Nullsv;
Packit Service b125fd
        }
Packit Service b125fd
        else {
Packit Service b125fd
            SV **svp;
Packit Service b125fd
            DBD_ATTRIBS_CHECK("bind_col", sth, attribs);
Packit Service b125fd
            /* XXX we should perhaps complain if TYPE is not SvNIOK */
Packit Service b125fd
            DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type);
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    switch(dbd_st_bind_col(sth, imp_sth, col, ref, sql_type, attribs)) {
Packit Service b125fd
    case 2:     ST(0) = &PL_sv_yes;        /* job done completely */
Packit Service b125fd
                break;
Packit Service b125fd
    case 1:     /* fallback to DBI default */
Packit Service b125fd
                ST(0) = (DBIc_DBISTATE(imp_sth)->bind_col(sth, col, ref, attribs))
Packit Service b125fd
                    ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
                break;
Packit Service b125fd
    default:    ST(0) = &PL_sv_no;         /* dbd_st_bind_col has called set_err */
Packit Service b125fd
                break;
Packit Service b125fd
    }
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif /* dbd_st_bind_col */
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
bind_param(sth, param, value, attribs=Nullsv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        param
Packit Service b125fd
    SV *        value
Packit Service b125fd
    SV *        attribs
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    IV sql_type = 0;
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    if (SvGMAGICAL(value))
Packit Service b125fd
        mg_get(value);
Packit Service b125fd
    if (attribs) {
Packit Service b125fd
        if (SvNIOK(attribs)) {
Packit Service b125fd
            sql_type = SvIV(attribs);
Packit Service b125fd
            attribs = Nullsv;
Packit Service b125fd
        }
Packit Service b125fd
        else {
Packit Service b125fd
            SV **svp;
Packit Service b125fd
            DBD_ATTRIBS_CHECK("bind_param", sth, attribs);
Packit Service b125fd
            /* XXX we should perhaps complain if TYPE is not SvNIOK */
Packit Service b125fd
            DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type);
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, FALSE, 0)
Packit Service b125fd
                ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
bind_param_inout(sth, param, value_ref, maxlen, attribs=Nullsv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        param
Packit Service b125fd
    SV *        value_ref
Packit Service b125fd
    IV          maxlen
Packit Service b125fd
    SV *        attribs
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    IV sql_type = 0;
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    SV *value;
Packit Service b125fd
    if (!SvROK(value_ref) || SvTYPE(SvRV(value_ref)) > SVt_PVMG)
Packit Service b125fd
        croak("bind_param_inout needs a reference to a scalar value");
Packit Service b125fd
    value = SvRV(value_ref);
Packit Service b125fd
    if (SvREADONLY(value))
Packit Service b125fd
        croak("Modification of a read-only value attempted");
Packit Service b125fd
    if (SvGMAGICAL(value))
Packit Service b125fd
        mg_get(value);
Packit Service b125fd
    if (attribs) {
Packit Service b125fd
        if (SvNIOK(attribs)) {
Packit Service b125fd
            sql_type = SvIV(attribs);
Packit Service b125fd
            attribs = Nullsv;
Packit Service b125fd
        }
Packit Service b125fd
        else {
Packit Service b125fd
            SV **svp;
Packit Service b125fd
            DBD_ATTRIBS_CHECK("bind_param", sth, attribs);
Packit Service b125fd
            DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type);
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, TRUE, maxlen)
Packit Service b125fd
                ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
execute(sth, ...)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    IV retval;
Packit Service b125fd
    if (items > 1) {    /* need to bind params */
Packit Service b125fd
        if (!dbdxst_bind_params(sth, imp_sth, items, ax) ) {
Packit Service b125fd
            XSRETURN_UNDEF;
Packit Service b125fd
        }
Packit Service b125fd
    }
Packit Service b125fd
    /* XXX this code is duplicated in selectrow_arrayref above  */
Packit Service b125fd
    DBIc_ROW_COUNT(imp_sth) = 0;
Packit Service b125fd
    retval = dbd_st_execute(sth, imp_sth); /* might be dbd_st_execute_iv via macro */
Packit Service b125fd
    /* remember that dbd_st_execute must return <= -2 for error */
Packit Service b125fd
    if (retval == 0)            /* ok with no rows affected     */
Packit Service b125fd
        XST_mPV(0, "0E0");      /* (true but zero)              */
Packit Service b125fd
    else if (retval < -1)       /* -1 == unknown number of rows */
Packit Service b125fd
        XST_mUNDEF(0);          /* <= -2 means error            */
Packit Service b125fd
    else
Packit Service b125fd
        XST_mIV(0, retval);     /* typically 1, rowcount or -1  */
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
#ifdef dbd_st_execute_for_fetch
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
execute_for_fetch(sth, fetch_tuple_sub, tuple_status = Nullsv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        fetch_tuple_sub
Packit Service b125fd
    SV *        tuple_status
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    ST(0) = dbd_st_execute_for_fetch(sth, imp_sth, fetch_tuple_sub, tuple_status);
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
fetchrow_arrayref(sth)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    ALIAS:
Packit Service b125fd
        fetch = 1
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    AV *av;
Packit Service b125fd
    PERL_UNUSED_VAR(ix);
Packit Service b125fd
    av = dbd_st_fetch(sth, imp_sth);
Packit Service b125fd
    ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef;
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
fetchrow_array(sth)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    ALIAS:
Packit Service b125fd
        fetchrow = 1
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    AV *av;
Packit Service b125fd
    av = dbd_st_fetch(sth, imp_sth);
Packit Service b125fd
    if (av) {
Packit Service b125fd
        int i;
Packit Service b125fd
        int num_fields = AvFILL(av)+1;
Packit Service b125fd
        EXTEND(sp, num_fields);
Packit Service b125fd
        for(i=0; i < num_fields; ++i) {
Packit Service b125fd
            PUSHs(AvARRAY(av)[i]);
Packit Service b125fd
        }
Packit Service b125fd
        PERL_UNUSED_VAR(ix);
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
fetchall_arrayref(sth, slice=&PL_sv_undef, batch_row_count=&PL_sv_undef)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        slice
Packit Service b125fd
    SV *        batch_row_count
Packit Service b125fd
    CODE:
Packit Service b125fd
    if (SvOK(slice)) {  /* fallback to perl implementation */
Packit Service b125fd
        SV *tmp = dbixst_bounce_method("DBD::~DRIVER~::st::SUPER::fetchall_arrayref", 3);
Packit Service b125fd
        SPAGAIN;
Packit Service b125fd
        ST(0) = tmp;
Packit Service b125fd
    }
Packit Service b125fd
    else {
Packit Service b125fd
        SV *tmp = dbdxst_fetchall_arrayref(sth, slice, batch_row_count);
Packit Service b125fd
        SPAGAIN;
Packit Service b125fd
        ST(0) = tmp;
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
finish(sth)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    D_imp_dbh_from_sth;
Packit Service b125fd
    if (!DBIc_ACTIVE(imp_sth)) {
Packit Service b125fd
        /* No active statement to finish        */
Packit Service b125fd
        XSRETURN_YES;
Packit Service b125fd
    }
Packit Service b125fd
    if (!DBIc_ACTIVE(imp_dbh)) {
Packit Service b125fd
        /* Either an explicit disconnect() or global destruction        */
Packit Service b125fd
        /* has disconnected us from the database. Finish is meaningless */
Packit Service b125fd
        DBIc_ACTIVE_off(imp_sth);
Packit Service b125fd
        XSRETURN_YES;
Packit Service b125fd
    }
Packit Service b125fd
#ifdef dbd_st_finish3
Packit Service b125fd
    ST(0) = dbd_st_finish3(sth, imp_sth, 0) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#else
Packit Service b125fd
    ST(0) = dbd_st_finish(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no;
Packit Service b125fd
#endif
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
blob_read(sth, field, offset, len, destrv=Nullsv, destoffset=0)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    int field
Packit Service b125fd
    long        offset
Packit Service b125fd
    long        len
Packit Service b125fd
    SV *        destrv
Packit Service b125fd
    long        destoffset
Packit Service b125fd
    CODE:
Packit Service b125fd
    {
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    if (!destrv)
Packit Service b125fd
        destrv = sv_2mortal(newRV(sv_2mortal(newSV(0))));
Packit Service b125fd
    if (dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset))
Packit Service b125fd
         ST(0) = SvRV(destrv);
Packit Service b125fd
    else ST(0) = &PL_sv_undef;
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
STORE(sth, keysv, valuesv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        keysv
Packit Service b125fd
    SV *        valuesv
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    if (SvGMAGICAL(valuesv))
Packit Service b125fd
        mg_get(valuesv);
Packit Service b125fd
    ST(0) = &PL_sv_yes;
Packit Service b125fd
    if (!dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv))
Packit Service b125fd
        if (!DBIc_DBISTATE(imp_sth)->set_attr(sth, keysv, valuesv))
Packit Service b125fd
            ST(0) = &PL_sv_no;
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
# FETCH renamed and ALIAS'd to avoid case clash on VMS :-(
Packit Service b125fd
void
Packit Service b125fd
FETCH_attrib(sth, keysv)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    SV *        keysv
Packit Service b125fd
    ALIAS:
Packit Service b125fd
    FETCH = 1
Packit Service b125fd
    CODE:
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    SV *valuesv;
Packit Service b125fd
    PERL_UNUSED_VAR(ix);
Packit Service b125fd
    valuesv = dbd_st_FETCH_attrib(sth, imp_sth, keysv);
Packit Service b125fd
    if (!valuesv)
Packit Service b125fd
        valuesv = DBIc_DBISTATE(imp_sth)->get_attr(sth, keysv);
Packit Service b125fd
    ST(0) = valuesv;    /* dbd_st_FETCH_attrib did sv_2mortal   */
Packit Service b125fd
Packit Service b125fd
Packit Service b125fd
void
Packit Service b125fd
DESTROY(sth)
Packit Service b125fd
    SV *        sth
Packit Service b125fd
    PPCODE:
Packit Service b125fd
    /* keep in sync with default DESTROY in DBI.xs */
Packit Service b125fd
    D_imp_sth(sth);
Packit Service b125fd
    ST(0) = &PL_sv_yes;
Packit Service b125fd
    if (!DBIc_IMPSET(imp_sth)) {        /* was never fully set up       */
Packit Service b125fd
        STRLEN lna;
Packit Service b125fd
        if (DBIc_WARN(imp_sth) && !PL_dirty && DBIc_DBISTATE(imp_sth)->debug >= 2)
Packit Service b125fd
             PerlIO_printf(DBIc_LOGPIO(imp_sth),
Packit Service b125fd
                "         DESTROY for %s ignored - handle not initialised\n",
Packit Service b125fd
                    SvPV(sth,lna));
Packit Service b125fd
    }
Packit Service b125fd
    else {
Packit Service b125fd
        if (DBIc_IADESTROY(imp_sth)) {  /* wants ineffective destroy    */
Packit Service b125fd
            DBIc_ACTIVE_off(imp_sth);
Packit Service b125fd
            if (DBIc_DBISTATE(imp_sth)->debug)
Packit Service b125fd
                 PerlIO_printf(DBIc_LOGPIO(imp_sth), "         DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(sth));
Packit Service b125fd
        }
Packit Service b125fd
        if (DBIc_ACTIVE(imp_sth)) {
Packit Service b125fd
            D_imp_dbh_from_sth;
Packit Service b125fd
            if (!PL_dirty && DBIc_ACTIVE(imp_dbh)) {
Packit Service b125fd
#ifdef dbd_st_finish3
Packit Service b125fd
                dbd_st_finish3(sth, imp_sth, 1);
Packit Service b125fd
#else
Packit Service b125fd
                dbd_st_finish(sth, imp_sth);
Packit Service b125fd
#endif
Packit Service b125fd
            }
Packit Service b125fd
            else {
Packit Service b125fd
                DBIc_ACTIVE_off(imp_sth);
Packit Service b125fd
            }
Packit Service b125fd
        }
Packit Service b125fd
        dbd_st_destroy(sth, imp_sth);
Packit Service b125fd
    }
Packit Service b125fd
Packit Service b125fd
# end of ~DRIVER~.xst
Packit Service b125fd
# vim:ts=8:sw=4:et