📄 driver.xst
字号:
# $Id: Driver.xst 9631 2007-06-07 12:56:24Z timbo $# Copyright (c) 1997-2002 Tim Bunce Ireland# Copyright (c) 2002 Jonathan Leffler## You may distribute under the terms of either the GNU General Public# License or the Artistic License, as specified in the Perl README file.#include "Driver_xst.h"MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~REQUIRE: 1.929PROTOTYPES: DISABLEBOOT: items = 0; /* avoid 'unused variable' warning */ DBISTATE_INIT; /* XXX this interface will change: */ DBI_IMP_SIZE("DBD::~DRIVER~::dr::imp_data_size", sizeof(imp_drh_t)); DBI_IMP_SIZE("DBD::~DRIVER~::db::imp_data_size", sizeof(imp_dbh_t)); DBI_IMP_SIZE("DBD::~DRIVER~::st::imp_data_size", sizeof(imp_sth_t)); dbd_init(DBIS);# ------------------------------------------------------------# driver level interface# ------------------------------------------------------------MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~::dr#ifdef dbd_discon_all# disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-(voiddiscon_all_(drh) SV * drh ALIAS: disconnect_all = 1 CODE: D_imp_drh(drh); if (0) ix = ix; /* avoid unused variable warning */ ST(0) = dbd_discon_all(drh, imp_drh) ? &sv_yes : &sv_no;#endif /* dbd_discon_all */#ifdef dbd_dr_data_sourcesvoiddata_sources(drh, attr = Nullsv) SV *drh SV *attr PPCODE: { D_imp_drh(drh); AV *av = dbd_dr_data_sources(drh, imp_drh, attr); if (av) { int i; int n = AvFILL(av)+1; EXTEND(sp, n); for (i = 0; i < n; ++i) { PUSHs(AvARRAY(av)[i]); } } }#endif# ------------------------------------------------------------# database level interface# ------------------------------------------------------------MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~::dbvoid_login(dbh, dbname, username, password, attribs=Nullsv) SV * dbh char * dbname SV * username SV * password SV * attribs CODE: { STRLEN lna; D_imp_dbh(dbh); char *u = (SvOK(username)) ? SvPV(username,lna) : ""; char *p = (SvOK(password)) ? SvPV(password,lna) : "";#ifdef dbd_db_login6 ST(0) = dbd_db_login6(dbh, imp_dbh, dbname, u, p, attribs) ? &sv_yes : &sv_no;#else ST(0) = dbd_db_login( dbh, imp_dbh, dbname, u, p) ? &sv_yes : &sv_no;#endif }voidselectall_arrayref(...) PREINIT: SV *sth; SV **maxrows_svp; SV **tmp_svp; SV *attr = &PL_sv_undef; imp_sth_t *imp_sth; CODE: if (items > 2) { attr = ST(2); if (SvROK(attr) && (DBD_ATTRIB_TRUE(attr,"Slice",5,tmp_svp) || DBD_ATTRIB_TRUE(attr,"Columns",7,tmp_svp)) ) { /* fallback to perl implementation */ ST(0) =dbixst_bounce_method("DBD::~DRIVER~::db::SUPER::selectall_arrayref", items); XSRETURN(1); } } /* --- prepare --- */ if (SvROK(ST(1))) { sth = ST(1); } else { sth = dbixst_bounce_method("prepare", 3); SPAGAIN; SP -= items; /* because stack might have been realloc'd */ if (!SvROK(sth)) XSRETURN_UNDEF; /* switch to inner handle */ sth = mg_find(SvRV(sth),'P')->mg_obj; } imp_sth = (imp_sth_t*)(DBIh_COM(sth)); /* --- bind_param --- */ if (items > 3) { /* need to bind params before execute */ if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { XSRETURN_UNDEF; } } /* --- execute --- */ DBIc_ROW_COUNT(imp_sth) = 0; if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ XSRETURN_UNDEF; } /* --- fetchall --- */ maxrows_svp = DBD_ATTRIB_GET_SVP(attr, "MaxRows", 7); ST(0) = dbdxst_fetchall_arrayref(sth, &PL_sv_undef, (maxrows_svp) ? *maxrows_svp : &PL_sv_undef);voidselectrow_arrayref(...) ALIAS: selectrow_array = 1 PREINIT: int is_selectrow_array = (ix == 1); imp_sth_t *imp_sth; SV *sth; AV *row_av; PPCODE: if (SvROK(ST(1))) { sth = ST(1); } else { /* --- prepare --- */ sth = dbixst_bounce_method("prepare", 3); SPAGAIN; SP -= items; /* because stack might have been realloc'd */ if (!SvROK(sth)) { if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } } /* switch to inner handle */ sth = mg_find(SvRV(sth),'P')->mg_obj; } imp_sth = (imp_sth_t*)(DBIh_COM(sth)); /* --- bind_param --- */ if (items > 3) { /* need to bind params before execute */ if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } } } /* --- execute --- */ DBIc_ROW_COUNT(imp_sth) = 0; if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } } /* --- fetchrow_arrayref --- */ row_av = dbd_st_fetch(sth, imp_sth); if (!row_av) { if (GIMME == G_SCALAR) PUSHs(&PL_sv_undef); } else if (is_selectrow_array) { int i; int num_fields = AvFILL(row_av)+1; if (GIMME == G_SCALAR) num_fields = 1; /* return just first field */ EXTEND(sp, num_fields); for(i=0; i < num_fields; ++i) { PUSHs(AvARRAY(row_av)[i]); } } else { PUSHs( sv_2mortal(newRV((SV *)row_av)) ); } /* --- finish --- */#ifdef dbd_st_finish3 dbd_st_finish3(sth, imp_sth, 0);#else dbd_st_finish(sth, imp_sth);#endif#ifdef dbd_db_do4 /* deebeedee-deebee-doo, deebee-doobee-dah? */voiddo(dbh, statement, params = Nullsv) SV * dbh char * statement SV * params CODE: { D_imp_dbh(dbh); IV retval; retval = dbd_db_do4(dbh, imp_dbh, statement, params); /* remember that dbd_db_do4 must return <= -2 for error */ if (retval == 0) /* ok with no rows affected */ XST_mPV(0, "0E0"); /* (true but zero) */ else if (retval < -1) /* -1 == unknown number of rows */ XST_mUNDEF(0); /* <= -2 means error */ else XST_mIV(0, retval); /* typically 1, rowcount or -1 */ }#endif#ifdef dbd_db_last_insert_idvoidlast_insert_id(dbh, catalog, schema, table, field, attr=Nullsv) SV * dbh SV * catalog SV * schema SV * table SV * field SV * attr CODE: { D_imp_dbh(dbh); ST(0) = dbd_db_last_insert_id(dbh, imp_dbh, catalog, schema, table, field, attr); }#endifvoidcommit(dbh) SV * dbh CODE: D_imp_dbh(dbh); if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) warn("commit ineffective with AutoCommit enabled"); ST(0) = dbd_db_commit(dbh, imp_dbh) ? &sv_yes : &sv_no;voidrollback(dbh) SV * dbh CODE: D_imp_dbh(dbh); if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) warn("rollback ineffective with AutoCommit enabled"); ST(0) = dbd_db_rollback(dbh, imp_dbh) ? &sv_yes : &sv_no;voiddisconnect(dbh) SV * dbh CODE: D_imp_dbh(dbh); if ( !DBIc_ACTIVE(imp_dbh) ) { XSRETURN_YES; } /* Check for disconnect() being called whilst refs to cursors */ /* still exists. This possibly needs some more thought. */ if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !dirty) { STRLEN lna; char *plural = (DBIc_ACTIVE_KIDS(imp_dbh)==1) ? "" : "s"; warn("%s->disconnect invalidates %d active statement handle%s %s", SvPV(dbh,lna), (int)DBIc_ACTIVE_KIDS(imp_dbh), plural, "(either destroy statement handles or call finish on them before disconnecting)"); } ST(0) = dbd_db_disconnect(dbh, imp_dbh) ? &sv_yes : &sv_no; DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */voidSTORE(dbh, keysv, valuesv) SV * dbh SV * keysv SV * valuesv CODE: D_imp_dbh(dbh); if (SvGMAGICAL(valuesv)) mg_get(valuesv); ST(0) = &sv_yes; if (!dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv)) if (!DBIc_DBISTATE(imp_dbh)->set_attr(dbh, keysv, valuesv)) ST(0) = &sv_no;voidFETCH(dbh, keysv) SV * dbh SV * keysv CODE: D_imp_dbh(dbh); SV *valuesv = dbd_db_FETCH_attrib(dbh, imp_dbh, keysv); if (!valuesv) valuesv = DBIc_DBISTATE(imp_dbh)->get_attr(dbh, keysv); ST(0) = valuesv; /* dbd_db_FETCH_attrib did sv_2mortal */voidDESTROY(dbh) SV * dbh PPCODE: /* keep in sync with default DESTROY in DBI.xs */ D_imp_dbh(dbh); ST(0) = &sv_yes; if (!DBIc_IMPSET(imp_dbh)) { /* was never fully set up */ STRLEN lna; if (DBIc_WARN(imp_dbh) && !dirty && DBIc_DBISTATE(imp_dbh)->debug >= 2) PerlIO_printf(DBIc_LOGPIO(imp_dbh), " DESTROY for %s ignored - handle not initialised\n", SvPV(dbh,lna)); } else { if (DBIc_IADESTROY(imp_dbh)) { /* want's ineffective destroy */ DBIc_ACTIVE_off(imp_dbh); if (DBIc_DBISTATE(imp_dbh)->debug) PerlIO_printf(DBIc_LOGPIO(imp_dbh), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(dbh)); } if (DBIc_ACTIVE(imp_dbh)) { if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) { /* Application is using transactions and hasn't explicitly disconnected. Some databases will automatically commit on graceful disconnect. Since we're about to gracefully disconnect as part of the DESTROY we want to be sure we're not about to implicitly commit changes that are incomplete and should be rolled back. (The DESTROY may be due to a RaiseError, for example.) So we rollback here. This will be harmless if the application has issued a commit, XXX Could add an attribute flag to indicate that the driver doesn't have this problem. Patches welcome. XXX or could just move the DBIc_is(imp_dbh, DBIcf_Executed) test to cover the rollback as well. That just needs sanity checking that DBIcf_Executed is set by any/all possible way to execute a statement that might start a transaction. */ if (DBIc_WARN(imp_dbh) && DBIc_is(imp_dbh, DBIcf_Executed) /* has not just called commit/rollback */ && (!dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3) ) warn("Issuing rollback() for database handle being DESTROY'd without explicit disconnect()"); dbd_db_rollback(dbh, imp_dbh); /* ROLLBACK! */ } dbd_db_disconnect(dbh, imp_dbh); DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ } dbd_db_destroy(dbh, imp_dbh); }#ifdef dbd_take_imp_datavoidtake_imp_data(h) SV * h CODE: D_imp_xxh(h);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -