DBD-SQLite-Amalgamation
view release on metacpan or search on metacpan
SV *errstr = DBIc_ERRSTR(imp_xxh);
sv_setiv(DBIc_ERR(imp_xxh), (IV)rc);
sv_setpv(errstr, what);
sv_catpvf(errstr, "(%d) at %s line %d", rc, file, line);
if (DBIS->debug >= 3) {
PerlIO_printf(DBILOGFP, "sqlite error %d recorded: %s at %s line %d\n",
rc, what, file, line);
}
}
static void
_sqlite_tracef(char *file, int line, int level, const char *fmt, ...)
{
dTHR;
va_list ap;
if (DBIS->debug >= level) {
char format[8192];
sqlite3_snprintf(8191, format, "sqlite trace: %s at %s line %d\n", fmt, file, line);
va_start(ap, fmt);
PerlIO_vprintf(DBILOGFP, format, ap);
va_end(ap);
}
}
static void
_sqlite_tracef_noline(int level, const char *fmt, ...)
{
dTHR;
va_list ap;
if (DBIS->debug >= level) {
char format[8192];
sqlite3_snprintf(8191, format, "sqlite trace: %s\n", fmt);
va_start(ap, fmt);
PerlIO_vprintf(DBILOGFP, format, ap);
va_end(ap);
}
}
int
sqlite_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pass)
{
dTHR;
int retval;
char *errmsg = NULL;
if (DBIS->debug >= 3) {
PerlIO_printf(DBILOGFP, " login '%s' (version %s)\n",
dbname, sqlite3_version);
}
if (sqlite3_open(dbname, &(imp_dbh->db)) != SQLITE_OK) {
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, 1, (char*)sqlite3_errmsg(imp_dbh->db));
return FALSE;
}
DBIc_IMPSET_on(imp_dbh);
imp_dbh->in_tran = FALSE;
imp_dbh->unicode = FALSE;
imp_dbh->functions = newAV();
imp_dbh->aggregates = newAV();
imp_dbh->timeout = SQL_TIMEOUT;
imp_dbh->handle_binary_nulls = FALSE;
sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT);
if ((retval = sqlite3_exec(imp_dbh->db, "PRAGMA empty_result_callbacks = ON",
NULL, NULL, &errmsg))
!= SQLITE_OK)
{
/* warn("failed to set pragma: %s\n", errmsg); */
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
return FALSE;
}
if ((retval = sqlite3_exec(imp_dbh->db, "PRAGMA show_datatypes = ON",
NULL, NULL, &errmsg))
!= SQLITE_OK)
{
/* warn("failed to set pragma: %s\n", errmsg); */
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
return FALSE;
}
DBIc_ACTIVE_on(imp_dbh);
return TRUE;
}
int
dbd_set_sqlite3_busy_timeout ( SV *dbh, int timeout )
{
D_imp_dbh(dbh);
if (timeout) {
imp_dbh->timeout = timeout;
sqlite3_busy_timeout(imp_dbh->db, timeout);
}
return imp_dbh->timeout;
}
int
sqlite_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh)
{
dTHR;
DBIc_ACTIVE_off(imp_dbh);
if (DBIc_is(imp_dbh, DBIcf_AutoCommit) == FALSE) {
sqlite_db_rollback(dbh, imp_dbh);
}
if (sqlite3_close(imp_dbh->db) == SQLITE_BUSY) {
/* active statements! */
warn("closing dbh with active statement handles");
}
imp_dbh->db = NULL;
av_undef(imp_dbh->functions);
imp_dbh->functions = (AV *)NULL;
{
AV *av;
D_imp_dbh_from_sth;
int numFields = DBIc_NUM_FIELDS(imp_sth);
int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks);
int i, retval;
sqlite_trace(6, "numFields == %d, nrow == %d\n", numFields, imp_sth->nrow);
if (!DBIc_ACTIVE(imp_sth)) {
return Nullav;
}
if (imp_sth->retval == SQLITE_DONE) {
sqlite_st_finish(sth, imp_sth);
return Nullav;
}
if (imp_sth->retval != SQLITE_ROW) {
/* error */
sqlite_st_finish(sth, imp_sth);
sqlite_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, (char*)sqlite3_errmsg(imp_dbh->db));
return Nullav;
}
imp_sth->nrow++;
av = DBIS->get_fbav(imp_sth);
for (i = 0; i < numFields; i++) {
int len;
char * val;
int col_type = sqlite3_column_type(imp_sth->stmt, i);
SV **sql_type = av_fetch(imp_sth->col_types, i, 0);
if (sql_type && SvOK(*sql_type)) {
if (SvIV(*sql_type)) {
col_type = SvIV(*sql_type);
}
}
switch(col_type) {
case SQLITE_INTEGER:
#if defined(USE_64_BIT_INT)
sv_setiv(AvARRAY(av)[i], sqlite3_column_int64(imp_sth->stmt, i));
#else
sv_setnv(AvARRAY(av)[i], (double)sqlite3_column_int64(imp_sth->stmt, i));
#endif
break;
case SQLITE_FLOAT:
sv_setnv(AvARRAY(av)[i], sqlite3_column_double(imp_sth->stmt, i));
break;
case SQLITE_TEXT:
val = (char*)sqlite3_column_text(imp_sth->stmt, i);
len = sqlite3_column_bytes(imp_sth->stmt, i);
if (chopBlanks) {
val = savepv(val);
while((len > 0) && (val[len-1] == ' ')) {
len--;
}
val[len] = '\0';
}
sv_setpvn(AvARRAY(av)[i], val, len);
if (imp_dbh->unicode) {
SvUTF8_on(AvARRAY(av)[i]);
} else {
SvUTF8_off(AvARRAY(av)[i]);
}
if (chopBlanks) Safefree(val);
break;
case SQLITE_BLOB:
len = sqlite3_column_bytes(imp_sth->stmt, i);
sv_setpvn(AvARRAY(av)[i], sqlite3_column_blob(imp_sth->stmt, i), len);
SvUTF8_off(AvARRAY(av)[i]);
break;
default:
sv_setsv(AvARRAY(av)[i], &PL_sv_undef);
SvUTF8_off(AvARRAY(av)[i]);
break;
}
SvSETMAGIC(AvARRAY(av)[i]);
}
imp_sth->retval = sqlite3_step(imp_sth->stmt);
return av;
}
int
sqlite_st_finish (SV *sth, imp_sth_t *imp_sth)
{
return sqlite_st_finish3(sth, imp_sth, 0);
}
int
sqlite_st_finish3 (SV *sth, imp_sth_t *imp_sth, int is_destroy)
{
D_imp_dbh_from_sth;
/* warn("finish statement\n"); */
if (!DBIc_ACTIVE(imp_sth))
return 1;
DBIc_ACTIVE_off(imp_sth);
av_clear(imp_sth->col_types);
if (!DBIc_ACTIVE(imp_dbh)) /* no longer connected */
return 1;
if (is_destroy) {
return TRUE;
}
if ((imp_sth->retval = sqlite3_reset(imp_sth->stmt)) != SQLITE_OK) {
char *errmsg = (char*)sqlite3_errmsg(imp_dbh->db);
/* warn("finalize failed! %s\n", errmsg); */
sqlite_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg);
return FALSE;
}
return TRUE;
}
void
sqlite_st_destroy (SV *sth, imp_sth_t *imp_sth)
{
/* warn("destroy statement: %s\n", imp_sth->statement); */
DBIc_ACTIVE_off(imp_sth);
sqlite3_finalize(imp_sth->stmt);
Safefree(imp_sth->statement);
SvREFCNT_dec((SV*)imp_sth->params);
SvREFCNT_dec((SV*)imp_sth->col_types);
DBIc_IMPSET_off(imp_sth);
}
int
sqlite_st_blob_read (SV *sth, imp_sth_t *imp_sth,
int field, long offset, long len, SV *destrv, long destoffset)
{
return 0;
}
int
sqlite_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
{
dTHR;
char *key = SvPV_nolen(keysv);
char *errmsg;
int retval;
if (strEQ(key, "AutoCommit")) {
if (SvTRUE(valuesv)) {
/* commit tran? */
if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (imp_dbh->in_tran) ) {
sqlite_trace(2, "COMMIT TRAN");
if ((retval = sqlite3_exec(imp_dbh->db, "COMMIT TRANSACTION",
NULL, NULL, &errmsg))
!= SQLITE_OK)
{
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
return TRUE;
}
imp_dbh->in_tran = FALSE;
}
}
DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv));
return TRUE;
}
if (strEQ(key, "unicode")) {
imp_dbh->unicode = !(! SvTRUE(valuesv));
return TRUE;
}
return FALSE;
}
SV *
sqlite_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
{
dTHR;
char *key = SvPV_nolen(keysv);
if (strEQ(key, "sqlite_version")) {
return newSVpv(sqlite3_version,0);
}
if (strEQ(key, "unicode")) {
return newSViv(imp_dbh->unicode ? 1 : 0);
}
return NULL;
}
int
sqlite_st_STORE_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)
{
char *key = SvPV_nolen(keysv);
return FALSE;
}
int
type_to_odbc_type (int type)
{
switch(type) {
case SQLITE_INTEGER: return SQL_INTEGER;
case SQLITE_FLOAT: return SQL_DOUBLE;
case SQLITE_TEXT: return SQL_VARCHAR;
case SQLITE_BLOB: return SQL_BLOB;
case SQLITE_NULL: return SQL_UNKNOWN_TYPE;
default: return SQL_UNKNOWN_TYPE;
}
}
SV *
sqlite_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv)
{
char *key = SvPV_nolen(keysv);
SV *retsv = NULL;
int i,n;
if (!DBIc_ACTIVE(imp_sth)) {
return NULL;
}
/* warn("fetch: %s\n", key); */
i = DBIc_NUM_FIELDS(imp_sth);
if (strEQ(key, "NAME")) {
AV *av = newAV();
/* warn("Fetch NAME fields: %d\n", i); */
av_extend(av, i);
retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
for (n = 0; n < i; n++) {
/* warn("Fetch col name %d\n", n); */
const char *fieldname = sqlite3_column_name(imp_sth->stmt, n);
if (fieldname) {
/* warn("Name [%d]: %s\n", n, fieldname); */
char *dot = instr(fieldname, ".");
if (dot) /* drop table name from field name */
fieldname = ++dot;
av_store(av, n, newSVpv(fieldname, 0));
}
}
}
else if (strEQ(key, "PRECISION")) {
AV *av = newAV();
retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
void *func, int len1, const void *string1,
int len2, const void *string2)
{
dSP;
int cmp;
int n_retval;
SV *sv1, *sv2;
ENTER;
SAVETMPS;
PUSHMARK(SP);
sv1 = newSVpvn( string1, len1);
SvUTF8_on(sv1);
sv2 = newSVpvn( string2, len2);
SvUTF8_on(sv2);
XPUSHs( sv_2mortal ( sv1 ) );
XPUSHs( sv_2mortal ( sv2 ) );
PUTBACK;
n_retval = call_sv((void*)func, G_SCALAR);
if (n_retval != 1) {
croak("collation function returned %d arguments", n_retval);
}
SPAGAIN;
cmp = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return cmp;
}
void
sqlite3_db_create_collation( SV *dbh, const char *name, SV *func )
{
D_imp_dbh(dbh);
int rv, rv2;
void *aa = "aa";
void *zz = "zz";
SV *func_sv = newSVsv(func);
/* Check that this is a proper collation function */
rv = sqlite_db_collation_dispatcher(func_sv, 2, aa, 2, aa);
if (rv != 0) {
warn("improper collation function: %s(aa, aa) returns %d!", name, rv);
}
rv = sqlite_db_collation_dispatcher(func_sv, 2, aa, 2, zz);
rv2 = sqlite_db_collation_dispatcher(func_sv, 2, zz, 2, aa);
if (rv2 != (rv * -1)) {
warn("improper collation function: '%s' is not symmetric", name);
}
/* Copy the func reference so that it can be deallocated at disconnect */
av_push( imp_dbh->functions, func_sv );
/* Register the func within sqlite3 */
rv = sqlite3_create_collation(
imp_dbh->db, name, SQLITE_UTF8,
func_sv,
imp_dbh->unicode ? sqlite_db_collation_dispatcher_utf8
: sqlite_db_collation_dispatcher
);
if ( rv != SQLITE_OK )
{
croak( "sqlite_create_collation failed with error %s",
sqlite3_errmsg(imp_dbh->db) );
}
}
int sqlite_db_progress_handler_dispatcher( void *handler )
{
dSP;
int n_retval;
int retval;
PUSHMARK(SP);
n_retval = call_sv( handler, G_SCALAR );
if ( n_retval != 1 ) {
croak( "progress_handler returned %d arguments", n_retval );
}
SPAGAIN;
retval = POPi;
PUTBACK;
return retval;
}
void
sqlite3_db_progress_handler( SV *dbh, int n_opcodes, SV *handler )
{
D_imp_dbh(dbh);
if (handler == &PL_sv_undef) {
/* remove previous handler */
sqlite3_progress_handler( imp_dbh->db, 0, NULL, NULL);
}
else {
int rv;
SV *handler_sv = newSVsv(handler);
/* Copy the handler ref so that it can be deallocated at disconnect */
av_push( imp_dbh->functions, handler_sv );
/* Register the func within sqlite3 */
sqlite3_progress_handler( imp_dbh->db, n_opcodes,
sqlite_db_progress_handler_dispatcher,
handler_sv );
}
}
/* end */
( run in 0.846 second using v1.01-cache-2.11-cpan-39bf76dae61 )