DBD-SQLite

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN


    return uv;
}

static inline dbd_sqlite_string_mode_t
_extract_sqlite_string_mode_from_sv( pTHX_ SV* input )
{
    if (SvOK(input)) {
        UV val = my_SvUV_strict(aTHX_ input, "sqlite_string_mode");

        if (val >= _DBD_SQLITE_STRING_MODE_COUNT) {
            _croak_invalid_value("sqlite_string_mode", SvPVbyte_nolen(input));
        }

        return val;
    }

    return DBD_SQLITE_STRING_MODE_PV;
}

int
sqlite_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pass, SV *attr)
{
    dTHX;
    int rc;
    HV *hv = NULL;
    SV **val;
    int extended = 0;
    int flag = 0;
    dbd_sqlite_string_mode_t string_mode = DBD_SQLITE_STRING_MODE_PV;

    sqlite_trace(dbh, imp_dbh, 3, form("login '%s' (version %s)", dbname, sqlite3_version));

    if (SvROK(attr)) {
        hv = (HV*)SvRV(attr);
        if (hv_exists(hv, "sqlite_extended_result_codes", 28)) {
            val = hv_fetch(hv, "sqlite_extended_result_codes", 28, 0);
            extended = (val && SvOK(*val)) ? !(!SvTRUE(*val)) : 0;
        }
        if (hv_exists(hv, "ReadOnly", 8)) {
            val = hv_fetch(hv, "ReadOnly", 8, 0);
            if ((val && SvOK(*val)) ? SvIV(*val) : 0) {
                flag |= SQLITE_OPEN_READONLY;
            }
        }
        if (hv_exists(hv, "sqlite_open_flags", 17)) {
            val = hv_fetch(hv, "sqlite_open_flags", 17, 0);
            flag |= (val && SvOK(*val)) ? SvIV(*val) : 0;
            if (flag & SQLITE_OPEN_READONLY) {
                hv_stores(hv, "ReadOnly", newSViv(1));
            }
        }

        /* sqlite_string_mode should be detected earlier, to register default functions correctly */

        SV** string_mode_svp = hv_fetchs(hv, "sqlite_string_mode", 0);
        if (string_mode_svp != NULL && SvOK(*string_mode_svp)) {
            string_mode = _extract_sqlite_string_mode_from_sv(aTHX_ *string_mode_svp);

        /* Legacy alternatives to sqlite_string_mode: */
        } else if (hv_exists(hv, "sqlite_unicode", 14)) {
            val = hv_fetch(hv, "sqlite_unicode", 14, 0);
            if ( (val && SvOK(*val)) ? SvIV(*val) : 0 ) {
                string_mode = DBD_SQLITE_STRING_MODE_UNICODE_NAIVE;
            }
        } else if (hv_exists(hv, "unicode", 7)) {
            val = hv_fetch(hv, "unicode", 7, 0);
            if ( (val && SvOK(*val)) ? SvIV(*val) : 0 ) {
                string_mode = DBD_SQLITE_STRING_MODE_UNICODE_NAIVE;
            }
        }
    }
    rc = sqlite_open2(dbname, &(imp_dbh->db), flag, extended);
    if ( rc != SQLITE_OK ) {
        return FALSE; /* -> undef in lib/DBD/SQLite.pm */
    }
    DBIc_IMPSET_on(imp_dbh);

    imp_dbh->string_mode               = string_mode;
    imp_dbh->functions                 = newAV();
    imp_dbh->aggregates                = newAV();
    imp_dbh->collation_needed_callback = newSVsv( &PL_sv_undef );
    imp_dbh->timeout                   = SQL_TIMEOUT;
    imp_dbh->handle_binary_nulls       = FALSE;
    imp_dbh->allow_multiple_statements = FALSE;
    imp_dbh->use_immediate_transaction = TRUE;
    imp_dbh->see_if_its_a_number       = FALSE;
    imp_dbh->extended_result_codes     = extended;
    imp_dbh->stmt_list                 = NULL;
    imp_dbh->began_transaction         = FALSE;
    imp_dbh->prefer_numeric_type       = FALSE;

    sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT);

    if (SvROK(attr)) {
        hv = (HV*)SvRV(attr);
        if (hv_exists(hv, "sqlite_defensive", 16)) {
            val = hv_fetch(hv, "sqlite_defensive", 16, 0);
            if (val && SvIOK(*val)) {
                sqlite3_db_config(imp_dbh->db, SQLITE_DBCONFIG_DEFENSIVE, (int)SvIV(*val), 0);
            }
        }
    }

#if 0
    /*
    ** As of 1.26_06 foreign keys support was enabled by default,
    ** but with further discussion, we agreed to follow what
    ** sqlite team does, i.e. wait until the team think it
    ** reasonable to enable the support by default, as they have
    ** larger users and will allocate enough time for people to
    ** get used to the foreign keys. However, we should say it loud
    ** that sometime in the (near?) future, this feature may break
    ** your applications (and it actually broke applications).
    ** Let everyone be prepared.
    */
    sqlite_exec(dbh, "PRAGMA foreign_keys = ON");
#endif

#if 0
    /*
    ** Enable this to see if you (wrongly) expect an implicit order
    ** of return values from a SELECT statement without ORDER BY.
    */
    sqlite_exec(dbh, "PRAGMA reverse_unordered_selects = ON");
#endif

dbdimp.c  view on Meta::CPAN


    if (strEQ(key, "AutoCommit")) {
        if (SvTRUE(valuesv)) {
            /* commit tran? */
            if ( DBIc_ACTIVE(imp_dbh) && (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (!sqlite3_get_autocommit(imp_dbh->db)) ) {
                sqlite_trace(dbh, imp_dbh, 3, "COMMIT TRAN");
                rc = sqlite_exec(dbh, "COMMIT TRANSACTION");
                if (rc != SQLITE_OK) {
                    return TRUE; /* XXX: is this correct? */
                }
            }
        }
        DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv));
        return TRUE;
    }
#if SQLITE_VERSION_NUMBER >= 3007011
    if (strEQ(key, "ReadOnly")) {
        if (SvTRUE(valuesv) && !sqlite3_db_readonly(imp_dbh->db, "main")) {
            sqlite_error(dbh, 0, "ReadOnly is set but it's only advisory");
        }
        return FALSE;
    }
#endif
    if (strEQ(key, "sqlite_allow_multiple_statements")) {
        imp_dbh->allow_multiple_statements = !(! SvTRUE(valuesv));
        return TRUE;
    }
    if (strEQ(key, "sqlite_use_immediate_transaction")) {
        imp_dbh->use_immediate_transaction = !(! SvTRUE(valuesv));
        return TRUE;
    }
    if (strEQ(key, "sqlite_see_if_its_a_number")) {
        imp_dbh->see_if_its_a_number = !(! SvTRUE(valuesv));
        return TRUE;
    }
    if (strEQ(key, "sqlite_extended_result_codes")) {
        imp_dbh->extended_result_codes = !(! SvTRUE(valuesv));
        sqlite3_extended_result_codes(imp_dbh->db, imp_dbh->extended_result_codes);
        return TRUE;
    }
    if (strEQ(key, "sqlite_prefer_numeric_type")) {
        imp_dbh->prefer_numeric_type = !(! SvTRUE(valuesv));
        return TRUE;
    }

    if (strEQ(key, "sqlite_string_mode")) {
        dbd_sqlite_string_mode_t string_mode = _extract_sqlite_string_mode_from_sv(aTHX_ valuesv);

#if PERL_UNICODE_DOES_NOT_WORK_WELL
        if (string_mode & DBD_SQLITE_STRING_MODE_UNICODE_ANY) {
            sqlite_trace(dbh, imp_dbh, 3, form("Unicode support is disabled for this version of perl."));
            string_mode = DBD_SQLITE_STRING_MODE_PV;
        }
#endif

        imp_dbh->string_mode = string_mode;

        return TRUE;
    }

    if (strEQ(key, "sqlite_unicode")) {
        /* it's too early to warn the deprecation of sqlite_unicode as it's widely used */
#if PERL_UNICODE_DOES_NOT_WORK_WELL
        sqlite_trace(dbh, imp_dbh, 3, form("Unicode support is disabled for this version of perl."));
        imp_dbh->string_mode = DBD_SQLITE_STRING_MODE_PV;
#else
        imp_dbh->string_mode = SvTRUE(valuesv) ? DBD_SQLITE_STRING_MODE_UNICODE_NAIVE : DBD_SQLITE_STRING_MODE_PV;
#endif
        return TRUE;
    }

    if (strEQ(key, "unicode")) {
        _warn_deprecated_if_possible(key, "sqlite_string_mode");
#if PERL_UNICODE_DOES_NOT_WORK_WELL
        sqlite_trace(dbh, imp_dbh, 3, form("Unicode support is disabled for this version of perl."));
        imp_dbh->string_mode = DBD_SQLITE_STRING_MODE_PV;
#else
        imp_dbh->string_mode = SvTRUE(valuesv) ? DBD_SQLITE_STRING_MODE_UNICODE_NAIVE : DBD_SQLITE_STRING_MODE_PV;
#endif
        return TRUE;
    }

    return FALSE;
}

SV *
sqlite_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
{
    dTHX;
    char *key = SvPV_nolen(keysv);

    if (strEQ(key, "sqlite_version")) {
        return sv_2mortal(newSVpv(sqlite3_version, 0));
    }
    if (strEQ(key, "sqlite_allow_multiple_statements")) {
        return sv_2mortal(newSViv(imp_dbh->allow_multiple_statements ? 1 : 0));
    }
   if (strEQ(key, "sqlite_use_immediate_transaction")) {
       return sv_2mortal(newSViv(imp_dbh->use_immediate_transaction ? 1 : 0));
   }
   if (strEQ(key, "sqlite_see_if_its_a_number")) {
       return sv_2mortal(newSViv(imp_dbh->see_if_its_a_number ? 1 : 0));
   }
   if (strEQ(key, "sqlite_extended_result_codes")) {
       return sv_2mortal(newSViv(imp_dbh->extended_result_codes ? 1 : 0));
   }
   if (strEQ(key, "sqlite_prefer_numeric_type")) {
       return sv_2mortal(newSViv(imp_dbh->prefer_numeric_type ? 1 : 0));
   }

   if (strEQ(key, "sqlite_string_mode")) {
       return sv_2mortal(newSVuv(imp_dbh->string_mode));
   }

   if (strEQ(key, "sqlite_unicode") || strEQ(key, "unicode")) {
        _warn_deprecated_if_possible(key, "sqlite_string_mode");
#if PERL_UNICODE_DOES_NOT_WORK_WELL
       sqlite_trace(dbh, imp_dbh, 3, "Unicode support is disabled for this version of perl.");
       return sv_2mortal(newSViv(0));
#else
       return sv_2mortal(newSViv(imp_dbh->string_mode == DBD_SQLITE_STRING_MODE_UNICODE_NAIVE ? 1 : 0));
#endif
   }

    return NULL;
}

SV *
sqlite_db_last_insert_id(SV *dbh, imp_dbh_t *imp_dbh, SV *catalog, SV *schema, SV *table, SV *field, SV *attr)
{
    dTHX;

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

    croak_if_db_is_null();

    return sv_2mortal(newSViv((IV)sqlite3_last_insert_rowid(imp_dbh->db)));
}

int
sqlite_st_prepare_sv(SV *sth, imp_sth_t *imp_sth, SV *sv_statement, SV *attribs)
{
    dTHX;
    dMY_CXT;
    int rc = 0;
    const char *extra;
    char *statement;
    stmt_list_s * new_stmt;
    D_imp_dbh_from_sth;

    MY_CXT.last_dbh_string_mode = imp_dbh->string_mode;

    if (!DBIc_ACTIVE(imp_dbh)) {
        sqlite_error(sth, -2, "attempt to prepare on inactive database handle");
        return FALSE; /* -> undef in lib/DBD/SQLite.pm */
    }

    /* sqlite3_prepare wants an utf8-encoded SQL statement */
    DBD_SQLITE_PREP_SV_FOR_SQLITE(sv_statement, imp_dbh->string_mode);

    statement = SvPV_nolen(sv_statement);

#if 0
    if (*statement == '\0') {
        sqlite_error(sth, -2, "attempt to prepare empty statement");
        return FALSE; /* -> undef in lib/DBD/SQLite.pm */
    }
#endif

    sqlite_trace(sth, imp_sth, 3, form("prepare statement: %s", statement));
    imp_sth->nrow      = -1;
    imp_sth->retval    = SQLITE_OK;

dbdimp.c  view on Meta::CPAN

    croak_if_db_is_null();

    if (timeout && SvIOK(timeout)) {
        imp_dbh->timeout = SvIV(timeout);
        if (!DBIc_ACTIVE(imp_dbh)) {
            sqlite_error(dbh, -2, "attempt to set busy timeout on inactive database handle");
            return -2;
        }
        sqlite3_busy_timeout(imp_dbh->db, imp_dbh->timeout);
    }
    return imp_dbh->timeout;
}

static void
sqlite_db_func_dispatcher(dbd_sqlite_string_mode_t string_mode, sqlite3_context *context, int argc, sqlite3_value **value)
{
    dTHX;
    dSP;
    int count;
    int i;
    SV *func;

    func      = sqlite3_user_data(context);

    ENTER;
    SAVETMPS;

    PUSHMARK(SP);
    for ( i=0; i < argc; i++ ) {
        XPUSHs(stacked_sv_from_sqlite3_value(aTHX_ value[i], string_mode));
    }
    PUTBACK;

    count = call_sv(func, G_SCALAR|G_EVAL);

    SPAGAIN;

    /* Check for an error */
    if (SvTRUE(ERRSV) ) {
        sqlite_set_result(aTHX_ context, ERRSV, 1);
        POPs;
    } else if ( count != 1 ) {
        SV *err = sv_2mortal(newSVpvf( "function should return 1 argument, got %d",
                                       count ));

        sqlite_set_result(aTHX_ context, err, 1);
        /* Clear the stack */
        for ( i=0; i < count; i++ ) {
            POPs;
        }
    } else {
        sqlite_set_result(aTHX_ context, POPs, 0 );
    }

    PUTBACK;
    FREETMPS;
    LEAVE;
}

static void
sqlite_db_func_dispatcher_unicode_naive(sqlite3_context *context, int argc, sqlite3_value **value)
{
    sqlite_db_func_dispatcher(DBD_SQLITE_STRING_MODE_UNICODE_NAIVE, context, argc, value);
}

static void
sqlite_db_func_dispatcher_unicode_fallback(sqlite3_context *context, int argc, sqlite3_value **value)
{
    sqlite_db_func_dispatcher(DBD_SQLITE_STRING_MODE_UNICODE_FALLBACK, context, argc, value);
}

static void
sqlite_db_func_dispatcher_unicode_strict(sqlite3_context *context, int argc, sqlite3_value **value)
{
    sqlite_db_func_dispatcher(DBD_SQLITE_STRING_MODE_UNICODE_STRICT, context, argc, value);
}

static void
sqlite_db_func_dispatcher_bytes(sqlite3_context *context, int argc, sqlite3_value **value)
{
    sqlite_db_func_dispatcher(DBD_SQLITE_STRING_MODE_BYTES, context, argc, value);
}

static void
sqlite_db_func_dispatcher_pv(sqlite3_context *context, int argc, sqlite3_value **value)
{
    sqlite_db_func_dispatcher(DBD_SQLITE_STRING_MODE_PV, context, argc, value);
}

typedef void (*dispatch_func_t)(sqlite3_context*, int, sqlite3_value**);

static dispatch_func_t _FUNC_DISPATCHER[_DBD_SQLITE_STRING_MODE_COUNT] = {
    sqlite_db_func_dispatcher_pv,
    sqlite_db_func_dispatcher_bytes,
    NULL, NULL,
    sqlite_db_func_dispatcher_unicode_naive,
    sqlite_db_func_dispatcher_unicode_fallback,
    sqlite_db_func_dispatcher_unicode_strict,
};

int
sqlite_db_create_function(pTHX_ SV *dbh, const char *name, int argc, SV *func, int flags)
{
    D_imp_dbh(dbh);
    int rc;
    SV *func_sv;

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

    /* Copy the function reference */
    if (SvOK(func)) {
        func_sv = newSVsv(func);
        av_push( imp_dbh->functions, func_sv );
    }

    croak_if_db_is_null();

    /* warn("create_function %s with %d args\n", name, argc); */
    if (SvOK(func)) {
        rc = sqlite3_create_function( imp_dbh->db, name, argc, SQLITE_UTF8|flags,
                                      func_sv, _FUNC_DISPATCHER[imp_dbh->string_mode], NULL, NULL );
    } else {
        rc = sqlite3_create_function( imp_dbh->db, name, argc, SQLITE_UTF8|flags, NULL, NULL, NULL, NULL );
    }
    if ( rc != SQLITE_OK ) {
        sqlite_error(dbh, rc, form("sqlite_create_function failed with error %s", sqlite3_errmsg(imp_dbh->db)));
        return FALSE;
    }
    return TRUE;
}

#ifndef SQLITE_OMIT_LOAD_EXTENSION

int
sqlite_db_enable_load_extension(pTHX_ SV *dbh, int onoff)
{
    D_imp_dbh(dbh);
    int rc;

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

    croak_if_db_is_null();

    /* COMPAT: sqlite3_enable_load_extension is only available for 3003006 or newer */
    rc = sqlite3_enable_load_extension( imp_dbh->db, onoff );
    if ( rc != SQLITE_OK ) {
        sqlite_error(dbh, rc, form("sqlite_enable_load_extension failed with error %s", sqlite3_errmsg(imp_dbh->db)));
        return FALSE;
    }
    return TRUE;
}



( run in 0.842 second using v1.01-cache-2.11-cpan-140bd7fdf52 )