1
0
Fork 0
mirror of https://github.com/DBD-SQLite/DBD-SQLite synced 2025-06-08 14:48:32 -04:00

DBD-SQLite: r6395 rewinds lots of things. reverted dbdimp.c

This commit is contained in:
Kenichi Ishigaki 2009-04-19 09:12:06 +00:00
parent f39688a7ab
commit 8f41000faf

382
dbdimp.c
View file

@ -1,4 +1,4 @@
/* $Id: dbdimp.c,v 1.64 2006/09/18 18:54:05 matt Exp $ */
#define PERL_NO_GET_CONTEXT
#include "SQLiteXS.h"
@ -18,9 +18,11 @@ DBISTATE_DECLARE;
#define call_sv(x,y) perl_call_sv(x,y)
#endif
#define sqlite_error(h,xxh,rc,what) _sqlite_error(__FILE__, __LINE__, h, xxh, rc, what)
#define sqlite_error(h,xxh,rc,what) _sqlite_error(aTHX_ __FILE__, __LINE__, h, xxh, rc, what)
/* XXX: is there any good way to use pTHX_/aTHX_ here like above? */
#if defined(__GNUC__) && (__GNUC__ > 2)
# define sqlite_trace(level,fmt...) _sqlite_tracef(__FILE__, __LINE__, level, fmt)
# define sqlite_trace(h,xxh,level,fmt...) _sqlite_tracef(__FILE__, __LINE__, h, xxh, level, fmt)
#else
# define sqlite_trace _sqlite_tracef_noline
#endif
@ -28,53 +30,52 @@ DBISTATE_DECLARE;
void
sqlite_init(dbistate_t *dbistate)
{
dTHR;
DBIS = dbistate;
dTHX;
DBISTATE_INIT; /* Initialize the DBI macros */
}
static void
_sqlite_error(char *file, int line, SV *h, imp_xxh_t *imp_xxh, int rc, char *what)
_sqlite_error(pTHX_ char *file, int line, SV *h, imp_xxh_t *imp_xxh, int rc, char *what)
{
dTHR;
DBIh_SET_ERR_CHAR(h, imp_xxh, Nullch, rc, what, Nullch, Nullch);
SV *errstr = DBIc_ERRSTR(imp_xxh);
sv_setiv(DBIc_ERR(imp_xxh), (IV)rc);
sv_setpv(errstr, what);
/* #7753: DBD::SQLite error shouldn't include extraneous info */
/* 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);
if ( DBIc_TRACE_LEVEL(imp_xxh) >= 3 ) {
PerlIO_printf(
DBIc_LOGPIO(imp_xxh),
"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, ...)
_sqlite_tracef(char *file, int line, SV *h, imp_xxh_t *imp_xxh, int level, const char *fmt, ...)
{
dTHR;
dTHX;
va_list ap;
if (DBIS->debug >= level) {
if ( DBIc_TRACE_LEVEL(imp_xxh) >= 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);
PerlIO_vprintf(DBIc_LOGPIO(imp_xxh), format, ap);
va_end(ap);
}
}
static void
_sqlite_tracef_noline(int level, const char *fmt, ...)
_sqlite_tracef_noline(SV *h, imp_xxh_t *imp_xxh, int level, const char *fmt, ...)
{
dTHR;
dTHX;
va_list ap;
if (DBIS->debug >= level) {
if ( DBIc_TRACE_LEVEL(imp_xxh) >= level ) {
char format[8192];
sqlite3_snprintf(8191, format, "sqlite trace: %s\n", fmt);
va_start(ap, fmt);
PerlIO_vprintf(DBILOGFP, format, ap);
PerlIO_vprintf(DBIc_LOGPIO(imp_xxh), format, ap);
va_end(ap);
}
}
@ -82,18 +83,18 @@ _sqlite_tracef_noline(int level, const char *fmt, ...)
int
sqlite_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pass)
{
dTHR;
dTHX;
int retval;
char *errmsg = NULL;
if (DBIS->debug >= 3) {
if ( DBIc_TRACE_LEVEL(imp_dbh) >= 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;
if ((retval = sqlite3_open(dbname, &(imp_dbh->db))) != SQLITE_OK ) {
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, (char*)sqlite3_errmsg(imp_dbh->db));
return FALSE; /* -> undef in lib/DBD/SQLite.pm */
}
DBIc_IMPSET_on(imp_dbh);
@ -102,7 +103,6 @@ sqlite_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pas
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);
@ -113,7 +113,7 @@ sqlite_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pas
{
/* warn("failed to set pragma: %s\n", errmsg); */
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
return FALSE;
return FALSE; /* -> undef in lib/DBD/SQLite.pm */
}
if ((retval = sqlite3_exec(imp_dbh->db, "PRAGMA show_datatypes = ON",
@ -122,16 +122,28 @@ sqlite_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pas
{
/* warn("failed to set pragma: %s\n", errmsg); */
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
return FALSE;
return FALSE; /* -> undef in lib/DBD/SQLite.pm */
}
DBIc_ACTIVE_on(imp_dbh);
/*
if ( DBIc_WARN(imp_dbh) ) {
warn("DBIc_WARN is on");
}
else {
warn("DBIc_WARN if off");
}
if ( DBIc_is(imp_dbh, DBIcf_PrintWarn) ) {
warn("DBIcf_PrintWarn is on");
}
*/
return TRUE;
}
int
dbd_set_sqlite3_busy_timeout ( SV *dbh, int timeout )
dbd_set_sqlite3_busy_timeout (pTHX_ SV *dbh, int timeout )
{
D_imp_dbh(dbh);
if (timeout) {
@ -144,7 +156,7 @@ dbd_set_sqlite3_busy_timeout ( SV *dbh, int timeout )
int
sqlite_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh)
{
dTHR;
dTHX;
sqlite3_stmt *pStmt;
DBIc_ACTIVE_off(imp_dbh);
@ -176,9 +188,14 @@ sqlite_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh)
void
sqlite_db_destroy (SV *dbh, imp_dbh_t *imp_dbh)
{
dTHR;
dTHX;
if (DBIc_ACTIVE(imp_dbh)) {
/* warn("DBIc_ACTIVE is on"); */
sqlite_db_disconnect(dbh, imp_dbh);
/*
} else {
warn("DBIc_ACTIVE is off");
*/
}
DBIc_IMPSET_off(imp_dbh);
}
@ -186,18 +203,18 @@ sqlite_db_destroy (SV *dbh, imp_dbh_t *imp_dbh)
int
sqlite_db_rollback(SV *dbh, imp_dbh_t *imp_dbh)
{
dTHR;
dTHX;
int retval;
char *errmsg;
if (imp_dbh->in_tran) {
sqlite_trace(2, "ROLLBACK TRAN");
sqlite_trace(dbh, (imp_xxh_t*)imp_dbh, 2, "ROLLBACK TRAN");
if ((retval = sqlite3_exec(imp_dbh->db, "ROLLBACK TRANSACTION",
NULL, NULL, &errmsg))
!= SQLITE_OK)
{
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
return FALSE;
return FALSE; /* -> &sv_no in SQLite.xsi */
}
imp_dbh->in_tran = FALSE;
}
@ -208,23 +225,23 @@ sqlite_db_rollback(SV *dbh, imp_dbh_t *imp_dbh)
int
sqlite_db_commit(SV *dbh, imp_dbh_t *imp_dbh)
{
dTHR;
dTHX;
int retval;
char *errmsg;
if (DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
warn("commit ineffective with AutoCommit");
/* We don't need to warn, because the DBI layer will do it for us */
return TRUE;
}
if (imp_dbh->in_tran) {
sqlite_trace(2, "COMMIT TRAN");
sqlite_trace(dbh, (imp_xxh_t*)imp_dbh, 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 FALSE;
return FALSE; /* -> &sv_no in SQLite.xsi */
}
imp_dbh->in_tran = FALSE;
}
@ -234,13 +251,14 @@ sqlite_db_commit(SV *dbh, imp_dbh_t *imp_dbh)
int
sqlite_discon_all(SV *drh, imp_drh_t *imp_drh)
{
dTHR;
dTHX;
return FALSE; /* no way to do this */
}
SV *
sqlite_db_last_insert_id(SV *dbh, imp_dbh_t *imp_dbh, SV *catalog, SV *schema, SV *table, SV *field, SV *attr)
{
dTHX;
return newSViv(sqlite3_last_insert_rowid(imp_dbh->db));
}
@ -248,22 +266,22 @@ int
sqlite_st_prepare (SV *sth, imp_sth_t *imp_sth,
char *statement, SV *attribs)
{
dTHR;
dTHX;
D_imp_dbh_from_sth;
const char *extra;
int retval = 0;
if (!DBIc_ACTIVE(imp_dbh)) {
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, "attempt to prepare on inactive database handle");
return FALSE;
sqlite_error(sth, (imp_xxh_t*)imp_sth, -2, "attempt to prepare on inactive database handle");
return FALSE; /* -> undef in lib/DBD/SQLite.pm */
}
if (strlen(statement) < 1) {
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, "attempt to prepare empty statement");
return FALSE;
sqlite_error(sth, (imp_xxh_t*)imp_sth, -2, "attempt to prepare empty statement");
return FALSE; /* -> undef in lib/DBD/SQLite.pm */
}
sqlite_trace(2, "prepare statement: %s", statement);
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 2, "prepare statement: %s", statement);
imp_sth->nrow = -1;
imp_sth->retval = SQLITE_OK;
imp_sth->params = newAV();
@ -277,7 +295,7 @@ sqlite_st_prepare (SV *sth, imp_sth_t *imp_sth,
sqlite3_finalize(imp_sth->stmt);
}
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, (char*)sqlite3_errmsg(imp_dbh->db));
return FALSE;
return FALSE; /* -> undef in lib/DBD/SQLite.pm */
}
/* store the query for later re-use if required */
@ -293,6 +311,7 @@ sqlite_st_prepare (SV *sth, imp_sth_t *imp_sth,
char *
sqlite_quote(imp_dbh_t *imp_dbh, SV *val)
{
dTHX;
STRLEN len;
char *cval = SvPV(val, len);
SV *ret = sv_2mortal(NEWSV(0, SvCUR(val) + 2));
@ -312,7 +331,7 @@ sqlite_quote(imp_dbh_t *imp_dbh, SV *val)
}
void
sqlite_st_reset (SV *sth)
sqlite_st_reset (pTHX_ SV *sth)
{
D_imp_sth(sth);
if (DBIc_IMPSET(imp_sth))
@ -322,41 +341,41 @@ sqlite_st_reset (SV *sth)
int
sqlite_st_execute (SV *sth, imp_sth_t *imp_sth)
{
dTHR;
dTHX;
D_imp_dbh_from_sth;
char *errmsg;
int num_params = DBIc_NUM_PARAMS(imp_sth);
int i;
int retval;
int retval = 0;
sqlite_trace(3, "execute");
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 3, "execute");
/* warn("execute\n"); */
if (!DBIc_ACTIVE(imp_dbh)) {
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, "attempt to execute on inactive database handle");
return FALSE;
sqlite_error(sth, (imp_xxh_t*)imp_sth, -2, "attempt to execute on inactive database handle");
return -2; /* -> undef in SQLite.xsi */
}
if (DBIc_ACTIVE(imp_sth)) {
sqlite_trace(3, "execute still active, reset");
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 3, "execute still active, reset");
if ((imp_sth->retval = sqlite3_reset(imp_sth->stmt)) != SQLITE_OK) {
char *errmsg = (char*)sqlite3_errmsg(imp_dbh->db);
sqlite_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg);
return FALSE;
return -2; /* -> undef in SQLite.xsi */
}
}
for (i = 0; i < num_params; i++) {
SV *value = av_shift(imp_sth->params);
SV *sql_type_sv = av_shift(imp_sth->params);
int sql_type = (int)SvIV(sql_type_sv);
int sql_type = SvIV(sql_type_sv);
sqlite_trace(4, "params left in 0x%p: %d", imp_sth->params, 1+av_len(imp_sth->params));
sqlite_trace(4, "bind %d type %d as %s", i, sql_type, SvPV_nolen_undef_ok(value));
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 4, "params left in 0x%p: %d", imp_sth->params, 1+av_len(imp_sth->params));
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 4, "bind %d type %d as %s", i, sql_type, SvPV_nolen_undef_ok(value));
if (!SvOK(value)) {
sqlite_trace(5, "binding null");
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 5, "binding null");
retval = sqlite3_bind_null(imp_sth->stmt, i+1);
}
else if (sql_type >= SQL_NUMERIC && sql_type <= SQL_SMALLINT) {
@ -372,12 +391,34 @@ sqlite_st_execute (SV *sth, imp_sth_t *imp_sth)
else if (sql_type == SQL_BLOB) {
STRLEN len;
char * data = SvPV(value, len);
retval = sqlite3_bind_blob(imp_sth->stmt, i+1, data, (int)len, SQLITE_TRANSIENT);
retval = sqlite3_bind_blob(imp_sth->stmt, i+1, data, len, SQLITE_TRANSIENT);
}
else {
#if 0
/* stop guessing until we figure out better way to do this */
const int numtype = looks_like_number(value);
if ((numtype & (IS_NUMBER_IN_UV|IS_NUMBER_NOT_INT)) == IS_NUMBER_IN_UV) {
#if defined(USE_64_BIT_INT)
retval = sqlite3_bind_int64(imp_sth->stmt, i+1, SvIV(value));
#else
retval = sqlite3_bind_int(imp_sth->stmt, i+1, SvIV(value));
#endif
}
else if ((numtype & (IS_NUMBER_NOT_INT|IS_NUMBER_INFINITY|IS_NUMBER_NAN)) == IS_NUMBER_NOT_INT) {
retval = sqlite3_bind_double(imp_sth->stmt, i+1, SvNV(value));
}
else {
#endif
STRLEN len;
char * data = SvPV(value, len);
retval = sqlite3_bind_text(imp_sth->stmt, i+1, data, (int)len, SQLITE_TRANSIENT);
char *data;
if (imp_dbh->unicode) {
sv_utf8_upgrade(value);
}
data = SvPV(value, len);
retval = sqlite3_bind_text(imp_sth->stmt, i+1, data, len, SQLITE_TRANSIENT);
#if 0
}
#endif
}
if (value) {
@ -386,25 +427,25 @@ sqlite_st_execute (SV *sth, imp_sth_t *imp_sth)
SvREFCNT_dec(sql_type_sv);
if (retval != SQLITE_OK) {
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, (char*)sqlite3_errmsg(imp_dbh->db));
return -4;
return -4; /* -> undef in SQLite.xsi */
}
}
if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (!imp_dbh->in_tran) ) {
sqlite_trace(2, "BEGIN TRAN");
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 2, "BEGIN TRAN");
if ((retval = sqlite3_exec(imp_dbh->db, "BEGIN TRANSACTION",
NULL, NULL, &errmsg))
!= SQLITE_OK)
{
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg);
return -2;
return -2; /* -> undef in SQLite.xsi */
}
imp_dbh->in_tran = TRUE;
}
imp_sth->nrow = 0;
sqlite_trace(3, "Execute returned %d cols\n", DBIc_NUM_FIELDS(imp_sth));
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 3, "Execute returned %d cols\n", DBIc_NUM_FIELDS(imp_sth));
if (DBIc_NUM_FIELDS(imp_sth) == 0) {
while ((imp_sth->retval = sqlite3_step(imp_sth->stmt)) != SQLITE_DONE) {
if (imp_sth->retval == SQLITE_ROW) {
@ -412,7 +453,7 @@ sqlite_st_execute (SV *sth, imp_sth_t *imp_sth)
}
sqlite3_reset(imp_sth->stmt);
sqlite_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, (char*)sqlite3_errmsg(imp_dbh->db));
return -5;
return -5; /* -> undef in SQLite.xsi */
}
/* warn("Finalize\n"); */
sqlite3_reset(imp_sth->stmt);
@ -427,12 +468,12 @@ sqlite_st_execute (SV *sth, imp_sth_t *imp_sth)
switch (imp_sth->retval) {
case SQLITE_ROW:
case SQLITE_DONE: DBIc_ACTIVE_on(imp_sth);
sqlite_trace(5, "exec ok - %d rows, %d cols\n", imp_sth->nrow, DBIc_NUM_FIELDS(imp_sth));
return 0;
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 5, "exec ok - %d rows, %d cols\n", imp_sth->nrow, DBIc_NUM_FIELDS(imp_sth));
return 0; /* -> '0E0' in SQLite.xsi */
default: sqlite3_reset(imp_sth->stmt);
imp_sth->stmt = NULL;
sqlite_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, (char*)sqlite3_errmsg(imp_dbh->db));
return -6;
return -6; /* -> undef in SQLite.xsi */
}
}
@ -452,6 +493,7 @@ sqlite_bind_ph (SV *sth, imp_sth_t *imp_sth,
SV *param, SV *value, IV sql_type, SV *attribs,
int is_inout, IV maxlen)
{
dTHX;
int pos;
if (!looks_like_number(param)) {
STRLEN len;
@ -459,21 +501,27 @@ sqlite_bind_ph (SV *sth, imp_sth_t *imp_sth,
paramstring = SvPV(param, len);
if(paramstring[len] == 0 && strlen(paramstring) == len) {
pos = sqlite3_bind_parameter_index(imp_sth->stmt, paramstring);
if (pos==0)
croak("Unknown named parameter: %s", paramstring);
if (pos==0) {
char errmsg[8192];
sqlite3_snprintf(8191, errmsg, "Unknown named parameter: %s", paramstring);
sqlite_error(sth, (imp_xxh_t*)imp_sth, -2, errmsg);
return FALSE; /* -> &sv_no in SQLite.xsi */
}
pos = 2 * (pos - 1);
}
else {
croak("<param> could not be coerced to a C string");
sqlite_error(sth, (imp_xxh_t*)imp_sth, -2, "<param> could not be coerced to a C string");
return FALSE; /* -> &sv_no in SQLite.xsi */
}
}
else {
if (is_inout) {
croak("InOut bind params not implemented");
sqlite_error(sth, (imp_xxh_t*)imp_sth, -2, "InOut bind params not implemented");
return FALSE; /* -> &sv_no in SQLite.xsi */
}
}
pos = (int)( 2 * (SvIV(param) - 1) );
sqlite_trace(3, "bind into 0x%p: %d => %s (%d) pos %d\n",
pos = 2 * (SvIV(param) - 1);
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 3, "bind into 0x%p: %d => %s (%d) pos %d\n",
imp_sth->params, SvIV(param), SvPV_nolen_undef_ok(value), sql_type, pos);
av_store(imp_sth->params, pos, SvREFCNT_inc(value));
av_store(imp_sth->params, pos+1, newSViv(sql_type));
@ -484,8 +532,10 @@ sqlite_bind_ph (SV *sth, imp_sth_t *imp_sth,
int
sqlite_bind_col(SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV sql_type, SV *attribs)
{
dTHX;
/* store the type */
av_store(imp_sth->col_types, (I32)SvIV(col)-1, newSViv(sql_type));
av_store(imp_sth->col_types, SvIV(col)-1, newSViv(sql_type));
/* Allow default implementation to continue */
return 1;
@ -494,13 +544,15 @@ sqlite_bind_col(SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV sql_type, SV *
AV *
sqlite_st_fetch (SV *sth, imp_sth_t *imp_sth)
{
dTHX;
AV *av;
D_imp_dbh_from_sth;
int numFields = DBIc_NUM_FIELDS(imp_sth);
int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks);
int i;
sqlite_trace(6, "numFields == %d, nrow == %d\n", numFields, imp_sth->nrow);
sqlite_trace(sth, (imp_xxh_t*)imp_sth, 6, "numFields == %d, nrow == %d\n", numFields, imp_sth->nrow);
if (!DBIc_ACTIVE(imp_sth)) {
return Nullav;
@ -515,12 +567,12 @@ sqlite_st_fetch (SV *sth, imp_sth_t *imp_sth)
/* 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;
return Nullav; /* -> undef in SQLite.xsi */
}
imp_sth->nrow++;
av = DBIS->get_fbav(imp_sth);
av = DBIc_DBISTATE((imp_xxh_t *)imp_sth)->get_fbav(imp_sth);
for (i = 0; i < numFields; i++) {
int len;
char * val;
@ -528,7 +580,7 @@ sqlite_st_fetch (SV *sth, imp_sth_t *imp_sth)
SV **sql_type = av_fetch(imp_sth->col_types, i, 0);
if (sql_type && SvOK(*sql_type)) {
if (SvIV(*sql_type)) {
col_type = (int)SvIV(*sql_type);
col_type = SvIV(*sql_type);
}
}
switch(col_type) {
@ -587,6 +639,8 @@ sqlite_st_finish (SV *sth, imp_sth_t *imp_sth)
int
sqlite_st_finish3 (SV *sth, imp_sth_t *imp_sth, int is_destroy)
{
dTHX;
D_imp_dbh_from_sth;
/* warn("finish statement\n"); */
@ -608,7 +662,7 @@ sqlite_st_finish3 (SV *sth, imp_sth_t *imp_sth, int is_destroy)
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 FALSE; /* -> &sv_no (or void) in SQLite.xsi */
}
return TRUE;
@ -617,6 +671,8 @@ sqlite_st_finish3 (SV *sth, imp_sth_t *imp_sth, int is_destroy)
void
sqlite_st_destroy (SV *sth, imp_sth_t *imp_sth)
{
dTHX;
D_imp_dbh_from_sth;
/* warn("destroy statement: %s\n", imp_sth->statement); */
DBIc_ACTIVE_off(imp_sth);
@ -640,7 +696,7 @@ sqlite_st_blob_read (SV *sth, imp_sth_t *imp_sth,
int
sqlite_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
{
dTHR;
dTHX;
char *key = SvPV_nolen(keysv);
char *errmsg;
int retval;
@ -649,13 +705,13 @@ sqlite_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
if (SvTRUE(valuesv)) {
/* commit tran? */
if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (imp_dbh->in_tran) ) {
sqlite_trace(2, "COMMIT TRAN");
sqlite_trace(dbh, (imp_xxh_t*)imp_dbh, 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;
return TRUE; /* XXX: is this correct? */
}
imp_dbh->in_tran = FALSE;
}
@ -664,7 +720,12 @@ sqlite_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
return TRUE;
}
if (strEQ(key, "unicode")) {
#if (PERL_REVISION <= 5) && ((PERL_VERSION < 8) || (PERL_VERSION == 8 && PERL_SUBVERSION < 5))
sqlite_trace(dbh, (imp_xxh_t*)imp_dbh, 2, "Unicode support is disabled for this version of perl.");
imp_dbh->unicode = 0;
#else
imp_dbh->unicode = !(! SvTRUE(valuesv));
#endif
return TRUE;
}
return FALSE;
@ -673,14 +734,19 @@ sqlite_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
SV *
sqlite_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
{
dTHR;
dTHX;
char *key = SvPV_nolen(keysv);
if (strEQ(key, "sqlite_version")) {
return newSVpv(sqlite3_version,0);
}
if (strEQ(key, "unicode")) {
#if (PERL_REVISION <= 5) && ((PERL_VERSION < 8) || (PERL_VERSION == 8 && PERL_SUBVERSION < 5))
sqlite_trace(dbh, (imp_xxh_t*)imp_dbh, 2, "Unicode support is disabled for this version of perl.");
return newSViv(0);
#else
return newSViv(imp_dbh->unicode ? 1 : 0);
#endif
}
return NULL;
@ -689,6 +755,7 @@ sqlite_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
int
sqlite_st_STORE_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)
{
dTHX;
char *key = SvPV_nolen(keysv);
return FALSE;
}
@ -709,6 +776,8 @@ type_to_odbc_type (int type)
SV *
sqlite_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv)
{
dTHX;
D_imp_dbh_from_sth;
char *key = SvPV_nolen(keysv);
SV *retsv = NULL;
int i,n;
@ -760,7 +829,26 @@ sqlite_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv)
}
else if (strEQ(key, "NULLABLE")) {
AV *av = newAV();
av_extend(av, i);
retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
#if defined(SQLITE_ENABLE_COLUMN_METADATA)
for (n = 0; n < i; n++) {
const char *database = sqlite3_column_database_name(imp_sth->stmt, n);
const char *tablename = sqlite3_column_table_name(imp_sth->stmt, n);
const char *fieldname = sqlite3_column_name(imp_sth->stmt, n);
const char *datatype, *collseq;
int notnull, primary, autoinc;
int retval = sqlite3_table_column_metadata(imp_dbh->db, database, tablename, fieldname, &datatype, &collseq, &notnull, &primary, &autoinc);
if (retval != SQLITE_OK) {
char *errmsg = (char*)sqlite3_errmsg(imp_dbh->db);
sqlite_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg);
av_store(av, n, newSViv(2)); /* SQL_NULLABLE_UNKNOWN */
}
else {
av_store(av, n, newSViv(!notnull));
}
}
#endif
}
else if (strEQ(key, "SCALE")) {
AV *av = newAV();
@ -774,14 +862,14 @@ sqlite_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv)
}
static void
sqlite_db_set_result(sqlite3_context *context, SV *result, int is_error )
sqlite_db_set_result(pTHX_ sqlite3_context *context, SV *result, int is_error )
{
STRLEN len;
char *s;
if ( is_error ) {
s = (char*)SvPV(result, len);
sqlite3_result_error( context, s, (int)len );
s = SvPV(result, len);
sqlite3_result_error( context, s, len );
return;
}
@ -790,21 +878,22 @@ sqlite_db_set_result(sqlite3_context *context, SV *result, int is_error )
sqlite3_result_null( context );
} else if( SvIOK_UV(result) ) {
s = SvPV(result, len);
sqlite3_result_text( context, s, (int)len, SQLITE_TRANSIENT );
sqlite3_result_text( context, s, len, SQLITE_TRANSIENT );
}
else if ( SvIOK(result) ) {
sqlite3_result_int( context, (int)SvIV(result));
sqlite3_result_int( context, SvIV(result));
} else if ( !is_error && SvIOK(result) ) {
sqlite3_result_double( context, SvNV(result));
} else {
s = SvPV(result, len);
sqlite3_result_text( context, s, (int)len, SQLITE_TRANSIENT );
sqlite3_result_text( context, s, len, SQLITE_TRANSIENT );
}
}
static void
sqlite_db_func_dispatcher(sqlite3_context *context, int argc, sqlite3_value **value)
sqlite_db_func_dispatcher(int is_unicode, sqlite3_context *context, int argc, sqlite3_value **value)
{
dTHX;
dSP;
int count;
int i;
@ -830,7 +919,11 @@ sqlite_db_func_dispatcher(sqlite3_context *context, int argc, sqlite3_value **va
arg = sv_2mortal(newSVnv(sqlite3_value_double(value[i])));
break;
case SQLITE_TEXT:
arg = sv_2mortal(newSVpvn((const char *)sqlite3_value_text(value[i]), len));
arg = newSVpvn((const char *)sqlite3_value_text(value[i]), len);
if (is_unicode) {
SvUTF8_on(arg);
}
arg = sv_2mortal(arg);
break;
case SQLITE_BLOB:
arg = sv_2mortal(newSVpvn(sqlite3_value_blob(value[i]), len));
@ -849,19 +942,19 @@ sqlite_db_func_dispatcher(sqlite3_context *context, int argc, sqlite3_value **va
/* Check for an error */
if (SvTRUE(ERRSV) ) {
sqlite_db_set_result( context, ERRSV, 1);
sqlite_db_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_db_set_result( context, err, 1);
sqlite_db_set_result(aTHX_ context, err, 1);
/* Clear the stack */
for ( i=0; i < count; i++ ) {
POPs;
}
} else {
sqlite_db_set_result( context, POPs, 0 );
sqlite_db_set_result(aTHX_ context, POPs, 0 );
}
PUTBACK;
@ -870,24 +963,55 @@ sqlite_db_func_dispatcher(sqlite3_context *context, int argc, sqlite3_value **va
LEAVE;
}
static void
sqlite_db_func_dispatcher_unicode(sqlite3_context *context, int argc, sqlite3_value **value)
{
sqlite_db_func_dispatcher(1, context, argc, value);
}
static void
sqlite_db_func_dispatcher_no_unicode(sqlite3_context *context, int argc, sqlite3_value **value)
{
sqlite_db_func_dispatcher(0, context, argc, value);
}
void
sqlite3_db_create_function( SV *dbh, const char *name, int argc, SV *func )
sqlite3_db_create_function(pTHX_ SV *dbh, const char *name, int argc, SV *func )
{
D_imp_dbh(dbh);
int rv;
int retval;
/* Copy the function reference */
SV *func_sv = newSVsv(func);
av_push( imp_dbh->functions, func_sv );
/* warn("create_function %s with %d args\n", name, argc); */
rv = sqlite3_create_function( imp_dbh->db, name, argc, SQLITE_UTF8,
retval = sqlite3_create_function( imp_dbh->db, name, argc, SQLITE_UTF8,
func_sv,
sqlite_db_func_dispatcher, NULL, NULL );
if ( rv != SQLITE_OK )
imp_dbh->unicode ? sqlite_db_func_dispatcher_unicode
: sqlite_db_func_dispatcher_no_unicode,
NULL, NULL );
if ( retval != SQLITE_OK )
{
croak( "sqlite_create_function failed with error %s",
sqlite3_errmsg(imp_dbh->db) );
char errmsg[8192];
sqlite3_snprintf(8191, errmsg, "sqlite_create_function failed with error %s", sqlite3_errmsg(imp_dbh->db));
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
}
}
void
sqlite3_db_enable_load_extension(pTHX_ SV *dbh, int onoff )
{
D_imp_dbh(dbh);
int retval;
retval = sqlite3_enable_load_extension( imp_dbh->db, onoff );
if ( retval != SQLITE_OK )
{
char errmsg[8192];
sqlite3_snprintf(8191, errmsg, "sqlite_enable_load_extension failed with error %s", sqlite3_errmsg(imp_dbh->db));
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
}
}
@ -899,7 +1023,7 @@ struct aggrInfo {
};
static void
sqlite_db_aggr_new_dispatcher( sqlite3_context *context, aggrInfo *aggr_info )
sqlite_db_aggr_new_dispatcher(pTHX_ sqlite3_context *context, aggrInfo *aggr_info )
{
dSP;
SV *pkg = NULL;
@ -958,6 +1082,7 @@ static void
sqlite_db_aggr_step_dispatcher (sqlite3_context *context,
int argc, sqlite3_value **value)
{
dTHX;
dSP;
int i;
aggrInfo *aggr;
@ -971,7 +1096,7 @@ sqlite_db_aggr_step_dispatcher (sqlite3_context *context,
/* initialize on first step */
if ( !aggr->inited ) {
sqlite_db_aggr_new_dispatcher( context, aggr );
sqlite_db_aggr_new_dispatcher(aTHX_ context, aggr );
}
if ( aggr->err || !aggr->aggr_inst )
@ -1022,6 +1147,7 @@ sqlite_db_aggr_step_dispatcher (sqlite3_context *context,
static void
sqlite_db_aggr_finalize_dispatcher( sqlite3_context *context )
{
dTHX;
dSP;
aggrInfo *aggr, myAggr;
int count = 0;
@ -1037,7 +1163,7 @@ sqlite_db_aggr_finalize_dispatcher( sqlite3_context *context )
aggr = &myAggr;
aggr->aggr_inst = NULL;
aggr->err = NULL;
sqlite_db_aggr_new_dispatcher (context, aggr);
sqlite_db_aggr_new_dispatcher(aTHX_ context, aggr);
}
if ( ! aggr->err && aggr->aggr_inst ) {
@ -1061,15 +1187,16 @@ sqlite_db_aggr_finalize_dispatcher( sqlite3_context *context )
POPs;
}
} else {
sqlite_db_set_result( context, POPs, 0 );
sqlite_db_set_result(aTHX_ context, POPs, 0 );
}
PUTBACK;
}
if ( aggr->err ) {
warn( "DBD::SQLite: error in aggregator cannot be reported to SQLite: %s", SvPV_nolen( aggr->err ) );
warn( "DBD::SQLite: error in aggregator cannot be reported to SQLite: %s",
SvPV_nolen( aggr->err ) );
/* sqlite_db_set_result( context, aggr->err, 1 ); */
/* sqlite_db_set_result(aTHX_ context, aggr->err, 1 ); */
SvREFCNT_dec( aggr->err );
aggr->err = NULL;
}
@ -1084,26 +1211,27 @@ sqlite_db_aggr_finalize_dispatcher( sqlite3_context *context )
}
void
sqlite3_db_create_aggregate( SV *dbh, const char *name, int argc, SV *aggr_pkg )
sqlite3_db_create_aggregate(pTHX_ SV *dbh, const char *name, int argc, SV *aggr_pkg )
{
D_imp_dbh(dbh);
int rv;
int retval;
/* Copy the aggregate reference */
SV *aggr_pkg_copy = newSVsv(aggr_pkg);
av_push( imp_dbh->aggregates, aggr_pkg_copy );
rv = sqlite3_create_function( imp_dbh->db, name, argc, SQLITE_UTF8,
retval = sqlite3_create_function( imp_dbh->db, name, argc, SQLITE_UTF8,
aggr_pkg_copy,
NULL,
sqlite_db_aggr_step_dispatcher,
sqlite_db_aggr_finalize_dispatcher
);
if ( rv != SQLITE_OK )
if ( retval != SQLITE_OK )
{
croak( "sqlite_create_aggregate failed with error %s",
sqlite3_errmsg(imp_dbh->db) );
char errmsg[8192];
sqlite3_snprintf(8191, errmsg, "sqlite_create_aggregate failed with error %s", sqlite3_errmsg(imp_dbh->db));
sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
}
}
@ -1111,6 +1239,7 @@ sqlite3_db_create_aggregate( SV *dbh, const char *name, int argc, SV *aggr_pkg )
int sqlite_db_collation_dispatcher(void *func, int len1, const void *string1,
int len2, const void *string2)
{
dTHX;
dSP;
int cmp;
int n_retval;
@ -1126,7 +1255,7 @@ int sqlite_db_collation_dispatcher(void *func, int len1, const void *string1,
croak("collation function returned %d arguments", n_retval);
}
SPAGAIN;
cmp = (int)POPi;
cmp = POPi;
PUTBACK;
FREETMPS;
LEAVE;
@ -1138,6 +1267,7 @@ int sqlite_db_collation_dispatcher_utf8(
void *func, int len1, const void *string1,
int len2, const void *string2)
{
dTHX;
dSP;
int cmp;
int n_retval;
@ -1158,7 +1288,7 @@ int sqlite_db_collation_dispatcher_utf8(
croak("collation function returned %d arguments", n_retval);
}
SPAGAIN;
cmp = (int)POPi;
cmp = POPi;
PUTBACK;
FREETMPS;
LEAVE;
@ -1168,7 +1298,7 @@ int sqlite_db_collation_dispatcher_utf8(
void
sqlite3_db_create_collation( SV *dbh, const char *name, SV *func )
sqlite3_db_create_collation(pTHX_ SV *dbh, const char *name, SV *func )
{
D_imp_dbh(dbh);
int rv, rv2;
@ -1201,14 +1331,15 @@ sqlite3_db_create_collation( SV *dbh, const char *name, SV *func )
if ( rv != SQLITE_OK )
{
croak( "sqlite_create_collation failed with error %s",
sqlite3_errmsg(imp_dbh->db) );
char errmsg[8192];
sqlite3_snprintf(8191, errmsg, "sqlite_create_collation failed with error %s", sqlite3_errmsg(imp_dbh->db));
}
}
int sqlite_db_progress_handler_dispatcher( void *handler )
{
dTHX;
dSP;
int n_retval;
int retval;
@ -1219,7 +1350,7 @@ int sqlite_db_progress_handler_dispatcher( void *handler )
croak( "progress_handler returned %d arguments", n_retval );
}
SPAGAIN;
retval = (int)POPi;
retval = POPi;
PUTBACK;
return retval;
@ -1228,7 +1359,7 @@ int sqlite_db_progress_handler_dispatcher( void *handler )
void
sqlite3_db_progress_handler( SV *dbh, int n_opcodes, SV *handler )
sqlite3_db_progress_handler(pTHX_ SV *dbh, int n_opcodes, SV *handler )
{
D_imp_dbh(dbh);
@ -1249,7 +1380,4 @@ sqlite3_db_progress_handler( SV *dbh, int n_opcodes, SV *handler )
}
}
/* end */
>>>>>>> 64bit-warnings:dbdimp.c