DBD-SQLcipher

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

    XPUSHs( sv_2mortal( newSVpv( sql, 0 ) ) );
    /*
     * The profile callback time is in units of nanoseconds,
     * however the current implementation is only capable of
     * millisecond resolution so the six least significant digits
     * in the time are meaningless.
     * (http://sqlite.org/c3ref/profile.html)
     */
    XPUSHs( sv_2mortal( newSViv((IV)( elapsed / 1000000 )) ) );
    PUTBACK;

    n_retval = call_sv( callback, G_SCALAR );
    SPAGAIN;
    if ( n_retval != 1 ) {
        warn( "callback returned %d arguments", n_retval );
    }
    for(i = 0; i < n_retval; i++) {
        retval = POPi;
    }
    PUTBACK;
    FREETMPS;
    LEAVE;
}

int
sqlite_db_profile(pTHX_ SV *dbh, SV *func)
{
    D_imp_dbh(dbh);

    if (!DBIc_ACTIVE(imp_dbh)) {
        sqlite_error(dbh, -2, "attempt to profile on inactive database handle");
        return FALSE;
    }

    croak_if_db_is_null();

    if (!SvOK(func)) {
        /* remove previous callback */
        sqlite3_profile( imp_dbh->db, NULL, NULL );
    }
    else {
        SV *func_sv = newSVsv(func);

        /* Copy the func ref so that it can be deallocated at disconnect */
        av_push( imp_dbh->functions, func_sv );

        /* Register the func within sqlite3 */
        sqlite3_profile( imp_dbh->db,
                         sqlite_db_profile_dispatcher,
                         func_sv );
    }
    return TRUE;
}

/* Accesses the SQLcipher Online Backup API, and fills the currently loaded
 * database from the passed filename.
 * Usual usage of this would be when you're operating on the :memory:
 * special database connection and want to copy it in from a real db.
 */
int
sqlite_db_backup_from_file(pTHX_ SV *dbh, char *filename)
{
    D_imp_dbh(dbh);

#if SQLITE_VERSION_NUMBER >= 3006011
    int rc;
    sqlite3 *pFrom;
    sqlite3_backup *pBackup;

    if (!DBIc_ACTIVE(imp_dbh)) {
        sqlite_error(dbh, -2, "attempt to backup from file on inactive database handle");
        return FALSE;
    }

    croak_if_db_is_null();

    rc = sqlite_open(filename, &pFrom);
    if ( rc != SQLITE_OK ) {
        return FALSE;
    }

    /* COMPAT: sqlite3_backup_* are only available for 3006011 or newer */
    pBackup = sqlite3_backup_init(imp_dbh->db, "main", pFrom, "main");
    if (pBackup) {
        (void)sqlite3_backup_step(pBackup, -1);
        (void)sqlite3_backup_finish(pBackup);
    }
    rc = sqlite3_errcode(imp_dbh->db);
    (void)sqlite3_close(pFrom);

    if ( rc != SQLITE_OK ) {
        sqlite_error(dbh, rc, form("sqlite_backup_from_file failed with error %s", sqlite3_errmsg(imp_dbh->db)));
        return FALSE;
    }

    return TRUE;
#else
    sqlite_error(dbh, SQLITE_ERROR, form("backup feature requires SQLcipher 3.6.11 and newer"));
    return FALSE;
#endif
}

/* Accesses the SQLcipher Online Backup API, and copies the currently loaded
 * database into the passed filename.
 * Usual usage of this would be when you're operating on the :memory:
 * special database connection, and want to back it up to an on-disk file.
 */
int
sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename)
{
    D_imp_dbh(dbh);

#if SQLITE_VERSION_NUMBER >= 3006011
    int rc;
    sqlite3 *pTo;
    sqlite3_backup *pBackup;

    if (!DBIc_ACTIVE(imp_dbh)) {
        sqlite_error(dbh, -2, "attempt to backup to file on inactive database handle");
        return FALSE;
    }

    croak_if_db_is_null();

    rc = sqlite_open(filename, &pTo);
    if ( rc != SQLITE_OK ) {
        return FALSE;
    }

    /* COMPAT: sqlite3_backup_* are only available for 3006011 or newer */
    pBackup = sqlite3_backup_init(pTo, "main", imp_dbh->db, "main");
    if (pBackup) {
        (void)sqlite3_backup_step(pBackup, -1);
        (void)sqlite3_backup_finish(pBackup);
    }
    rc = sqlite3_errcode(pTo);
    (void)sqlite3_close(pTo);

    if ( rc != SQLITE_OK ) {
        sqlite_error(dbh, rc, form("sqlite_backup_to_file failed with error %s", sqlite3_errmsg(imp_dbh->db)));
        return FALSE;
    }

    return TRUE;
#else
    sqlite_error(dbh, SQLITE_ERROR, form("backup feature requires SQLcipher 3.6.11 and newer"));
    return FALSE;
#endif
}

typedef struct perl_tokenizer {
    sqlite3_tokenizer base;
    SV *coderef;                 /* the perl tokenizer is a coderef that takes
                                    a string and returns a cursor coderef */
} perl_tokenizer;

typedef struct perl_tokenizer_cursor {
    sqlite3_tokenizer_cursor base;
    SV *coderef;                 /* ref to the closure that returns terms */
    char *pToken;                /* storage for a copy of the last token */
    int nTokenAllocated;         /* space allocated to pToken buffer */

    /* members below are only used if the input string is in utf8 */
    const char *pInput;          /* input we are tokenizing */
    const char *lastByteOffset;  /* offset into pInput */
    int lastCharOffset;          /* char offset corresponding to lastByteOffset */
} perl_tokenizer_cursor;

/*
** Create a new tokenizer instance.
** Will be called whenever a FTS3 table is created with
**   CREATE .. USING fts3( ... , tokenize=perl qualified::function::name)
** where qualified::function::name is a fully qualified perl function
*/
static int perl_tokenizer_Create(
    int argc, const char * const *argv,
    sqlite3_tokenizer **ppTokenizer
){
    dTHX;
    dSP;
    int n_retval;
    SV *retval;
    perl_tokenizer *t;

    if (!argc) {
        return SQLITE_ERROR;
    }

    t = (perl_tokenizer *) sqlite3_malloc(sizeof(*t));
    if( t==NULL ) return SQLITE_NOMEM;
    memset(t, 0, sizeof(*t));

    ENTER;
    SAVETMPS;

    /* call the qualified::function::name */
    PUSHMARK(SP);
    PUTBACK;
    n_retval = call_pv(argv[0], G_SCALAR);
    SPAGAIN;

    /* store a copy of the returned coderef into the tokenizer structure */
    if (n_retval != 1) {
        warn("tokenizer_Create returned %d arguments", n_retval);
    }
    retval = POPs;



( run in 0.854 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )