|
Packit |
723767 |
/***********************************************************************
|
|
Packit |
723767 |
** The set of routines that implement the perl "module"
|
|
Packit |
723767 |
** (i.e support for virtual tables written in Perl)
|
|
Packit |
723767 |
************************************************************************/
|
|
Packit |
723767 |
|
|
Packit |
723767 |
typedef struct perl_vtab {
|
|
Packit |
723767 |
sqlite3_vtab base;
|
|
Packit |
723767 |
SV *perl_vtab_obj;
|
|
Packit |
723767 |
HV *functions;
|
|
Packit |
723767 |
} perl_vtab;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
typedef struct perl_vtab_cursor {
|
|
Packit |
723767 |
sqlite3_vtab_cursor base;
|
|
Packit |
723767 |
SV *perl_cursor_obj;
|
|
Packit |
723767 |
} perl_vtab_cursor;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
typedef struct perl_vtab_init {
|
|
Packit |
723767 |
SV *dbh;
|
|
Packit |
723767 |
const char *perl_class;
|
|
Packit |
723767 |
} perl_vtab_init;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* auxiliary routine for generalized method calls. Arg "i" may be unused */
|
|
Packit |
723767 |
static int _call_perl_vtab_method(sqlite3_vtab *pVTab,
|
|
Packit |
723767 |
const char *method, int i) {
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab *) pVTab)->perl_vtab_obj);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSViv(i)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method (method, G_VOID);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_New(const char *method,
|
|
Packit |
723767 |
sqlite3 *db, void *pAux,
|
|
Packit |
723767 |
int argc, const char *const *argv,
|
|
Packit |
723767 |
sqlite3_vtab **ppVTab, char **pzErr){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
perl_vtab *vt;
|
|
Packit |
723767 |
perl_vtab_init *init_data = (perl_vtab_init *)pAux;
|
|
Packit |
723767 |
int count, i;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
SV *perl_vtab_obj;
|
|
Packit |
723767 |
SV *sql;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* allocate a perl_vtab structure */
|
|
Packit |
723767 |
vt = (perl_vtab *) sqlite3_malloc(sizeof(*vt));
|
|
Packit |
723767 |
if( vt==NULL ) return SQLITE_NOMEM;
|
|
Packit |
723767 |
memset(vt, 0, sizeof(*vt));
|
|
Packit |
723767 |
vt->functions = newHV();
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the ->CREATE/CONNECT() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(init_data->perl_class, 0)));
|
|
Packit |
723767 |
XPUSHs(init_data->dbh);
|
|
Packit |
723767 |
for(i = 0; i < argc; i++) {
|
|
Packit |
723767 |
XPUSHs(newSVpvn_flags(argv[i], strlen(argv[i]), SVs_TEMP|SVf_UTF8));
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method (method, G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* check the return value */
|
|
Packit |
723767 |
if ( count != 1 ) {
|
|
Packit |
723767 |
*pzErr = sqlite3_mprintf("vtab->%s() should return one value, got %d",
|
|
Packit |
723767 |
method, count );
|
|
Packit |
723767 |
SP -= count; /* Clear the stack */
|
|
Packit |
723767 |
goto cleanup;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* get the VirtualTable instance */
|
|
Packit |
723767 |
perl_vtab_obj = POPs;
|
|
Packit |
723767 |
if ( !sv_isobject(perl_vtab_obj) ) {
|
|
Packit |
723767 |
*pzErr = sqlite3_mprintf("vtab->%s() should return a blessed reference",
|
|
Packit |
723767 |
method);
|
|
Packit |
723767 |
goto cleanup;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the ->VTAB_TO_DECLARE() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(perl_vtab_obj);
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("VTAB_TO_DECLARE", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* check the return value */
|
|
Packit |
723767 |
if (count != 1 ) {
|
|
Packit |
723767 |
*pzErr = sqlite3_mprintf("vtab->VTAB_TO_DECLARE() should return one value, got %d",
|
|
Packit |
723767 |
count );
|
|
Packit |
723767 |
SP -= count; /* Clear the stack */
|
|
Packit |
723767 |
goto cleanup;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call sqlite3_declare_vtab with the sql returned from
|
|
Packit |
723767 |
method VTAB_TO_DECLARE(), converted to utf8 */
|
|
Packit |
723767 |
sql = POPs;
|
|
Packit |
723767 |
rc = sqlite3_declare_vtab(db, SvPVutf8_nolen(sql));
|
|
Packit |
723767 |
|
|
Packit |
723767 |
cleanup:
|
|
Packit |
723767 |
if (rc == SQLITE_OK) {
|
|
Packit |
723767 |
/* record the VirtualTable perl instance within the vtab structure */
|
|
Packit |
723767 |
vt->perl_vtab_obj = SvREFCNT_inc(perl_vtab_obj);
|
|
Packit |
723767 |
*ppVTab = &vt->base;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
sqlite3_free(vt);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return rc;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Create(sqlite3 *db, void *pAux,
|
|
Packit |
723767 |
int argc, const char *const *argv,
|
|
Packit |
723767 |
sqlite3_vtab **ppVTab, char **pzErr){
|
|
Packit |
723767 |
return perl_vt_New("CREATE", db, pAux, argc, argv, ppVTab, pzErr);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Connect(sqlite3 *db, void *pAux,
|
|
Packit |
723767 |
int argc, const char *const *argv,
|
|
Packit |
723767 |
sqlite3_vtab **ppVTab, char **pzErr){
|
|
Packit |
723767 |
return perl_vt_New("CONNECT", db, pAux, argc, argv, ppVTab, pzErr);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int _free_perl_vtab(perl_vtab *pVTab){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
SvREFCNT_dec(pVTab->perl_vtab_obj);
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* deallocate coderefs that were declared through FindFunction() */
|
|
Packit |
723767 |
hv_undef(pVTab->functions);
|
|
Packit |
723767 |
SvREFCNT_dec(pVTab->functions);
|
|
Packit |
723767 |
|
|
Packit |
723767 |
sqlite3_free(pVTab);
|
|
Packit |
723767 |
return SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Disconnect(sqlite3_vtab *pVTab){
|
|
Packit |
723767 |
_call_perl_vtab_method(pVTab, "DISCONNECT", 0);
|
|
Packit |
723767 |
return _free_perl_vtab((perl_vtab *)pVTab);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Drop(sqlite3_vtab *pVTab){
|
|
Packit |
723767 |
_call_perl_vtab_method(pVTab, "DROP", 0);
|
|
Packit |
723767 |
return _free_perl_vtab((perl_vtab *)pVTab);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static char *
|
|
Packit |
723767 |
_constraint_op_to_string(unsigned char op) {
|
|
Packit |
723767 |
switch (op) {
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_EQ:
|
|
Packit |
723767 |
return "=";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_GT:
|
|
Packit |
723767 |
return ">";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_GE:
|
|
Packit |
723767 |
return ">=";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_LT:
|
|
Packit |
723767 |
return "<";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_LE:
|
|
Packit |
723767 |
return "<=";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_MATCH:
|
|
Packit |
723767 |
return "MATCH";
|
|
Packit |
723767 |
#if SQLITE_VERSION_NUMBER >= 3010000
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_LIKE:
|
|
Packit |
723767 |
return "LIKE";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_GLOB:
|
|
Packit |
723767 |
return "GLOB";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_REGEXP:
|
|
Packit |
723767 |
return "REGEXP";
|
|
Packit |
723767 |
#endif
|
|
Packit |
723767 |
#if SQLITE_VERSION_NUMBER >= 3021000
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_NE:
|
|
Packit |
723767 |
return "NE";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_ISNOT:
|
|
Packit |
723767 |
return "ISNOT";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
|
|
Packit |
723767 |
return "ISNOTNULL";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_ISNULL:
|
|
Packit |
723767 |
return "ISNULL";
|
|
Packit |
723767 |
case SQLITE_INDEX_CONSTRAINT_IS:
|
|
Packit |
723767 |
return "IS";
|
|
Packit |
723767 |
#endif
|
|
Packit |
723767 |
default:
|
|
Packit |
723767 |
return "unknown";
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pIdxInfo){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int i, count;
|
|
Packit |
723767 |
int argvIndex;
|
|
Packit |
723767 |
AV *constraints;
|
|
Packit |
723767 |
AV *order_by;
|
|
Packit |
723767 |
SV *hashref;
|
|
Packit |
723767 |
SV **val;
|
|
Packit |
723767 |
HV *hv;
|
|
Packit |
723767 |
struct sqlite3_index_constraint_usage *pConsUsage;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* build the "where_constraints" datastructure */
|
|
Packit |
723767 |
constraints = newAV();
|
|
Packit |
723767 |
for (i=0; i<pIdxInfo->nConstraint; i++){
|
|
Packit |
723767 |
struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[i];
|
|
Packit |
723767 |
HV *constraint = newHV();
|
|
Packit |
723767 |
char *op_str = _constraint_op_to_string(pCons->op);
|
|
Packit |
723767 |
hv_stores(constraint, "col", newSViv(pCons->iColumn));
|
|
Packit |
723767 |
hv_stores(constraint, "op", newSVpv(op_str, 0));
|
|
Packit |
723767 |
hv_stores(constraint, "usable", pCons->usable ? &PL_sv_yes : &PL_sv_no);
|
|
Packit |
723767 |
av_push(constraints, newRV_noinc((SV*) constraint));
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* build the "order_by" datastructure */
|
|
Packit |
723767 |
order_by = newAV();
|
|
Packit |
723767 |
for (i=0; i<pIdxInfo->nOrderBy; i++){
|
|
Packit |
723767 |
struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[i];
|
|
Packit |
723767 |
HV *order = newHV();
|
|
Packit |
723767 |
hv_stores(order, "col", newSViv(pOrder->iColumn));
|
|
Packit |
723767 |
hv_stores(order, "desc", pOrder->desc ? &PL_sv_yes : &PL_sv_no);
|
|
Packit |
723767 |
av_push( order_by, newRV_noinc((SV*) order));
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the ->BEST_INDEX() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs( ((perl_vtab *) pVTab)->perl_vtab_obj);
|
|
Packit |
723767 |
XPUSHs( sv_2mortal( newRV_noinc((SV*) constraints)));
|
|
Packit |
723767 |
XPUSHs( sv_2mortal( newRV_noinc((SV*) order_by)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("BEST_INDEX", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* get values back from the returned hashref */
|
|
Packit |
723767 |
if (count != 1)
|
|
Packit |
723767 |
croak("BEST_INDEX() method returned %d vals instead of 1", count);
|
|
Packit |
723767 |
hashref = POPs;
|
|
Packit |
723767 |
if (!(hashref && SvROK(hashref) && SvTYPE(SvRV(hashref)) == SVt_PVHV))
|
|
Packit |
723767 |
croak("BEST_INDEX() method did not return a hashref");
|
|
Packit |
723767 |
hv = (HV*)SvRV(hashref);
|
|
Packit |
723767 |
val = hv_fetch(hv, "idxNum", 6, FALSE);
|
|
Packit |
723767 |
pIdxInfo->idxNum = (val && SvOK(*val)) ? SvIV(*val) : 0;
|
|
Packit |
723767 |
val = hv_fetch(hv, "idxStr", 6, FALSE);
|
|
Packit |
723767 |
if (val && SvOK(*val)) {
|
|
Packit |
723767 |
STRLEN len;
|
|
Packit |
723767 |
char *str = SvPVutf8(*val, len);
|
|
Packit |
723767 |
pIdxInfo->idxStr = sqlite3_malloc(len+1);
|
|
Packit |
723767 |
memcpy(pIdxInfo->idxStr, str, len);
|
|
Packit |
723767 |
pIdxInfo->idxStr[len] = 0;
|
|
Packit |
723767 |
pIdxInfo->needToFreeIdxStr = 1;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
val = hv_fetch(hv, "orderByConsumed", 15, FALSE);
|
|
Packit |
723767 |
pIdxInfo->orderByConsumed = (val && SvTRUE(*val)) ? 1 : 0;
|
|
Packit |
723767 |
val = hv_fetch(hv, "estimatedCost", 13, FALSE);
|
|
Packit |
723767 |
pIdxInfo->estimatedCost = (val && SvOK(*val)) ? SvNV(*val) : 0;
|
|
Packit |
723767 |
#if SQLITE_VERSION_NUMBER >= 3008002
|
|
Packit |
723767 |
val = hv_fetch(hv, "estimatedRows", 13, FALSE);
|
|
Packit |
723767 |
pIdxInfo->estimatedRows = (val && SvOK(*val)) ? SvIV(*val) : 0;
|
|
Packit |
723767 |
#endif
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* loop over constraints to get back the "argvIndex" and "omit" keys
|
|
Packit |
723767 |
that shoud have been added by the best_index() method call */
|
|
Packit |
723767 |
for (i=0; i<pIdxInfo->nConstraint; i++){
|
|
Packit |
723767 |
SV **rv = av_fetch(constraints, i, FALSE);
|
|
Packit |
723767 |
if (!(rv && SvROK(*rv) && SvTYPE(SvRV(*rv)) == SVt_PVHV))
|
|
Packit |
723767 |
croak("the call to BEST_INDEX() has corrupted constraint data");
|
|
Packit |
723767 |
hv = (HV*)SvRV(*rv);
|
|
Packit |
723767 |
val = hv_fetch(hv, "argvIndex", 9, FALSE);
|
|
Packit |
723767 |
argvIndex = (val && SvOK(*val)) ? SvIV(*val) + 1: 0;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
pConsUsage = &pIdxInfo->aConstraintUsage[i];
|
|
Packit |
723767 |
pConsUsage->argvIndex = argvIndex;
|
|
Packit |
723767 |
val = hv_fetch(hv, "omit", 4, FALSE);
|
|
Packit |
723767 |
pConsUsage->omit = (val && SvTRUE(*val)) ? 1 : 0;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
SV *perl_cursor;
|
|
Packit |
723767 |
perl_vtab_cursor *cursor;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* allocate a perl_vtab_cursor structure */
|
|
Packit |
723767 |
cursor = (perl_vtab_cursor *) sqlite3_malloc(sizeof(*cursor));
|
|
Packit |
723767 |
if( cursor==NULL ) return SQLITE_NOMEM;
|
|
Packit |
723767 |
memset(cursor, 0, sizeof(*cursor));
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the ->OPEN() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs( ((perl_vtab *) pVTab)->perl_vtab_obj);
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("OPEN", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("vtab->OPEN() method returned %d vals instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
goto cleanup;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
perl_cursor = POPs;
|
|
Packit |
723767 |
if ( !sv_isobject(perl_cursor) ) {
|
|
Packit |
723767 |
warn("vtab->OPEN() method did not return a blessed cursor");
|
|
Packit |
723767 |
goto cleanup;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* everything went OK */
|
|
Packit |
723767 |
rc = SQLITE_OK;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
cleanup:
|
|
Packit |
723767 |
|
|
Packit |
723767 |
if (rc == SQLITE_OK) {
|
|
Packit |
723767 |
cursor->perl_cursor_obj = SvREFCNT_inc(perl_cursor);
|
|
Packit |
723767 |
*ppCursor = &cursor->base;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
sqlite3_free(cursor);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return rc;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Close(sqlite3_vtab_cursor *pVtabCursor){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
perl_vtab_cursor *perl_pVTabCursor;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* Note : there is no explicit call to a CLOSE() method; if
|
|
Packit |
723767 |
needed, the Perl class can implement a DESTROY() method */
|
|
Packit |
723767 |
|
|
Packit |
723767 |
perl_pVTabCursor = (perl_vtab_cursor *) pVtabCursor;
|
|
Packit |
723767 |
SvREFCNT_dec(perl_pVTabCursor->perl_cursor_obj);
|
|
Packit |
723767 |
sqlite3_free(perl_pVTabCursor);
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Filter( sqlite3_vtab_cursor *pVtabCursor,
|
|
Packit |
723767 |
int idxNum, const char *idxStr,
|
|
Packit |
723767 |
int argc, sqlite3_value **argv ){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
dMY_CXT;
|
|
Packit |
723767 |
int i, count;
|
|
Packit |
723767 |
int is_unicode = MY_CXT.last_dbh_is_unicode;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the FILTER() method with ($idxNum, $idxStr, @args) */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab_cursor *) pVtabCursor)->perl_cursor_obj);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSViv(idxNum)));
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(idxStr, 0)));
|
|
Packit |
723767 |
for(i = 0; i < argc; i++) {
|
|
Packit |
723767 |
XPUSHs(stacked_sv_from_sqlite3_value(aTHX_ argv[i], is_unicode));
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method("FILTER", G_VOID);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Next(sqlite3_vtab_cursor *pVtabCursor){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the next() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab_cursor *) pVtabCursor)->perl_cursor_obj);
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("NEXT", G_VOID);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Eof(sqlite3_vtab_cursor *pVtabCursor){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count, eof;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the eof() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab_cursor *) pVtabCursor)->perl_cursor_obj);
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("EOF", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("cursor->EOF() method returned %d vals instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
SV *sv = POPs; /* need 2 lines, because this doesn't work : */
|
|
Packit |
723767 |
eof = SvTRUE(sv); /* eof = SvTRUE(POPs); # I don't understand why :-( */
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return eof;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Column(sqlite3_vtab_cursor *pVtabCursor,
|
|
Packit |
723767 |
sqlite3_context* context,
|
|
Packit |
723767 |
int col){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the column() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab_cursor *) pVtabCursor)->perl_cursor_obj);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSViv(col)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("COLUMN", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("cursor->COLUMN() method returned %d vals instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
sqlite3_result_error(context, "column error", 12);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
SV *result = POPs;
|
|
Packit |
723767 |
sqlite_set_result(aTHX_ context, result, 0 );
|
|
Packit |
723767 |
rc = SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return rc;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Rowid( sqlite3_vtab_cursor *pVtabCursor,
|
|
Packit |
723767 |
sqlite3_int64 *pRowid ){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the rowid() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab_cursor *) pVtabCursor)->perl_cursor_obj);
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("ROWID", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("cursor->ROWID() returned %d vals instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
*pRowid =POPi;
|
|
Packit |
723767 |
rc = SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return rc;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Update( sqlite3_vtab *pVTab,
|
|
Packit |
723767 |
int argc, sqlite3_value **argv,
|
|
Packit |
723767 |
sqlite3_int64 *pRowid ){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
dMY_CXT;
|
|
Packit |
723767 |
int count, i;
|
|
Packit |
723767 |
int is_unicode = MY_CXT.last_dbh_is_unicode;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
SV *rowidsv;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the _SQLITE_UPDATE() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab *) pVTab)->perl_vtab_obj);
|
|
Packit |
723767 |
for(i = 0; i < argc; i++) {
|
|
Packit |
723767 |
XPUSHs(stacked_sv_from_sqlite3_value(aTHX_ argv[i], is_unicode));
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("_SQLITE_UPDATE", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("cursor->_SQLITE_UPDATE() returned %d vals instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
if (argc > 1 && sqlite3_value_type(argv[0]) == SQLITE_NULL
|
|
Packit |
723767 |
&& sqlite3_value_type(argv[1]) == SQLITE_NULL) {
|
|
Packit |
723767 |
/* this was an insert without any given rowid, so the result of
|
|
Packit |
723767 |
the method call must be passed in *pRowid*/
|
|
Packit |
723767 |
rowidsv = POPs;
|
|
Packit |
723767 |
if (!SvOK(rowidsv))
|
|
Packit |
723767 |
*pRowid = 0;
|
|
Packit |
723767 |
else if (SvUOK(rowidsv))
|
|
Packit |
723767 |
*pRowid = SvUV(rowidsv);
|
|
Packit |
723767 |
else if (SvIOK(rowidsv))
|
|
Packit |
723767 |
*pRowid = SvIV(rowidsv);
|
|
Packit |
723767 |
else
|
|
Packit |
723767 |
*pRowid = (sqlite3_int64)SvNV(rowidsv);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
rc = SQLITE_OK;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return rc;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Begin(sqlite3_vtab *pVTab){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "BEGIN_TRANSACTION", 0);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Sync(sqlite3_vtab *pVTab){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "SYNC_TRANSACTION", 0);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Commit(sqlite3_vtab *pVTab){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "COMMIT_TRANSACTION", 0);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Rollback(sqlite3_vtab *pVTab){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "ROLLBACK_TRANSACTION", 0);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_FindFunction(sqlite3_vtab *pVTab,
|
|
Packit |
723767 |
int nArg, const char *zName,
|
|
Packit |
723767 |
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
Packit |
723767 |
void **ppArg){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
dMY_CXT;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
int is_overloaded = 0;
|
|
Packit |
723767 |
char *func_name = sqlite3_mprintf("%s\t%d", zName, nArg);
|
|
Packit |
723767 |
STRLEN len = strlen(func_name);
|
|
Packit |
723767 |
HV *functions = ((perl_vtab *) pVTab)->functions;
|
|
Packit |
723767 |
SV* coderef = NULL;
|
|
Packit |
723767 |
SV** val;
|
|
Packit |
723767 |
SV *result;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* check if that function was already in cache */
|
|
Packit |
723767 |
if (hv_exists(functions, func_name, len)) {
|
|
Packit |
723767 |
val = hv_fetch(functions, func_name, len, FALSE);
|
|
Packit |
723767 |
if (val && SvOK(*val)) {
|
|
Packit |
723767 |
coderef = *val;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
/* call the FIND_FUNCTION() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab *) pVTab)->perl_vtab_obj);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSViv(nArg)));
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(zName, 0)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method ("FIND_FUNCTION", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("vtab->FIND_FUNCTION() method returned %d vals instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
goto cleanup;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
result = POPs;
|
|
Packit |
723767 |
if (SvTRUE(result)) {
|
|
Packit |
723767 |
/* the coderef must be valid for the lifetime of pVTab, so
|
|
Packit |
723767 |
make a copy */
|
|
Packit |
723767 |
coderef = newSVsv(result);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* store result in cache */
|
|
Packit |
723767 |
hv_store(functions, func_name, len, coderef ? coderef : &PL_sv_undef, 0);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* return function information for sqlite3 within *pxFunc and *ppArg */
|
|
Packit |
723767 |
is_overloaded = coderef && SvTRUE(coderef);
|
|
Packit |
723767 |
if (is_overloaded) {
|
|
Packit |
723767 |
*pxFunc = MY_CXT.last_dbh_is_unicode ? sqlite_db_func_dispatcher_unicode
|
|
Packit |
723767 |
: sqlite_db_func_dispatcher_no_unicode;
|
|
Packit |
723767 |
*ppArg = coderef;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
cleanup:
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
sqlite3_free(func_name);
|
|
Packit |
723767 |
return is_overloaded;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Rename(sqlite3_vtab *pVTab, const char *zNew){
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(((perl_vtab *) pVTab)->perl_vtab_obj);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(zNew, 0)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method("RENAME", G_SCALAR);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
if (count != 1) {
|
|
Packit |
723767 |
warn("vtab->RENAME() returned %d args instead of 1", count);
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
else {
|
|
Packit |
723767 |
rc = POPi;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return rc;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Savepoint(sqlite3_vtab *pVTab, int point){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "SAVEPOINT", point);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_Release(sqlite3_vtab *pVTab, int point){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "RELEASE", point);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static int perl_vt_RollbackTo(sqlite3_vtab *pVTab, int point){
|
|
Packit |
723767 |
return _call_perl_vtab_method(pVTab, "ROLLBACK_TO", point);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
static sqlite3_module perl_vt_Module = {
|
|
Packit |
723767 |
1, /* iVersion */
|
|
Packit |
723767 |
perl_vt_Create, /* xCreate */
|
|
Packit |
723767 |
perl_vt_Connect, /* xConnect */
|
|
Packit |
723767 |
perl_vt_BestIndex, /* xBestIndex */
|
|
Packit |
723767 |
perl_vt_Disconnect, /* xDisconnect */
|
|
Packit |
723767 |
perl_vt_Drop, /* xDestroy */
|
|
Packit |
723767 |
perl_vt_Open, /* xOpen - open a cursor */
|
|
Packit |
723767 |
perl_vt_Close, /* xClose - close a cursor */
|
|
Packit |
723767 |
perl_vt_Filter, /* xFilter - configure scan constraints */
|
|
Packit |
723767 |
perl_vt_Next, /* xNext - advance a cursor */
|
|
Packit |
723767 |
perl_vt_Eof, /* xEof - check for end of scan */
|
|
Packit |
723767 |
perl_vt_Column, /* xColumn - read data */
|
|
Packit |
723767 |
perl_vt_Rowid, /* xRowid - read data */
|
|
Packit |
723767 |
perl_vt_Update, /* xUpdate (optional) */
|
|
Packit |
723767 |
perl_vt_Begin, /* xBegin (optional) */
|
|
Packit |
723767 |
perl_vt_Sync, /* xSync (optional) */
|
|
Packit |
723767 |
perl_vt_Commit, /* xCommit (optional) */
|
|
Packit |
723767 |
perl_vt_Rollback, /* xRollback (optional) */
|
|
Packit |
723767 |
perl_vt_FindFunction, /* xFindFunction (optional) */
|
|
Packit |
723767 |
perl_vt_Rename, /* xRename */
|
|
Packit |
723767 |
#if SQLITE_VERSION_NUMBER >= 3007007
|
|
Packit |
723767 |
perl_vt_Savepoint, /* xSavepoint (optional) */
|
|
Packit |
723767 |
perl_vt_Release, /* xRelease (optional) */
|
|
Packit |
723767 |
perl_vt_RollbackTo /* xRollbackTo (optional) */
|
|
Packit |
723767 |
#endif
|
|
Packit |
723767 |
};
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
void
|
|
Packit |
723767 |
sqlite_db_destroy_module_data(void *pAux)
|
|
Packit |
723767 |
{
|
|
Packit |
723767 |
dTHX;
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
int count;
|
|
Packit |
723767 |
int rc = SQLITE_ERROR;
|
|
Packit |
723767 |
perl_vtab_init *init_data;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
init_data = (perl_vtab_init *)pAux;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the DESTROY_MODULE() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(init_data->perl_class, 0)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method("DESTROY_MODULE", G_VOID);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* free module memory */
|
|
Packit |
723767 |
SvREFCNT_dec(init_data->dbh);
|
|
Packit |
723767 |
sqlite3_free((char *)init_data->perl_class);
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
int
|
|
Packit |
723767 |
sqlite_db_create_module(pTHX_ SV *dbh, const char *name, const char *perl_class)
|
|
Packit |
723767 |
{
|
|
Packit |
723767 |
dSP;
|
|
Packit |
723767 |
D_imp_dbh(dbh);
|
|
Packit |
723767 |
int count, rc, retval = TRUE;
|
|
Packit |
723767 |
char *module_ISA;
|
|
Packit |
723767 |
char *loading_code;
|
|
Packit |
723767 |
perl_vtab_init *init_data;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
ENTER;
|
|
Packit |
723767 |
SAVETMPS;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
if (!DBIc_ACTIVE(imp_dbh)) {
|
|
Packit |
723767 |
sqlite_error(dbh, -2, "attempt to create module on inactive database handle");
|
|
Packit |
723767 |
return FALSE;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* load the module if needed */
|
|
Packit |
723767 |
module_ISA = sqlite3_mprintf("%s::ISA", perl_class);
|
|
Packit |
723767 |
if (!get_av(module_ISA, 0)) {
|
|
Packit |
723767 |
loading_code = sqlite3_mprintf("use %s", perl_class);
|
|
Packit |
723767 |
eval_pv(loading_code, TRUE);
|
|
Packit |
723767 |
sqlite3_free(loading_code);
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
sqlite3_free(module_ISA);
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* build the init datastructure that will be passed to perl_vt_New() */
|
|
Packit |
723767 |
init_data = sqlite3_malloc(sizeof(*init_data));
|
|
Packit |
723767 |
init_data->dbh = newRV(dbh);
|
|
Packit |
723767 |
sv_rvweaken(init_data->dbh);
|
|
Packit |
723767 |
init_data->perl_class = sqlite3_mprintf(perl_class);
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* register within sqlite */
|
|
Packit |
723767 |
rc = sqlite3_create_module_v2( imp_dbh->db,
|
|
Packit |
723767 |
name,
|
|
Packit |
723767 |
&perl_vt_Module,
|
|
Packit |
723767 |
init_data,
|
|
Packit |
723767 |
sqlite_db_destroy_module_data
|
|
Packit |
723767 |
);
|
|
Packit |
723767 |
if ( rc != SQLITE_OK ) {
|
|
Packit |
723767 |
sqlite_error(dbh, rc, form("sqlite_create_module failed with error %s",
|
|
Packit |
723767 |
sqlite3_errmsg(imp_dbh->db)));
|
|
Packit |
723767 |
retval = FALSE;
|
|
Packit |
723767 |
}
|
|
Packit |
723767 |
|
|
Packit |
723767 |
|
|
Packit |
723767 |
/* call the CREATE_MODULE() method */
|
|
Packit |
723767 |
PUSHMARK(SP);
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(perl_class, 0)));
|
|
Packit |
723767 |
XPUSHs(sv_2mortal(newSVpv(name, 0)));
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
count = call_method("CREATE_MODULE", G_VOID);
|
|
Packit |
723767 |
SPAGAIN;
|
|
Packit |
723767 |
SP -= count;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
PUTBACK;
|
|
Packit |
723767 |
FREETMPS;
|
|
Packit |
723767 |
LEAVE;
|
|
Packit |
723767 |
|
|
Packit |
723767 |
return retval;
|
|
Packit |
723767 |
}
|