bool QSQLiteResultPrivate::fetchNext(QtSqlCachedResult::RowCache* row) { // may be caching. const char **fvals; const char **cnames; int colNum; int res; int i; if (skipRow) { // already fetched if (row) *row = *skipRow; delete skipRow; skipRow = 0; return skippedStatus; } if (!currentMachine) return FALSE; // keep trying while busy, wish I could implement this better. while ((res = sqlite_step(currentMachine, &colNum, &fvals, &cnames)) == SQLITE_BUSY) { // sleep instead requesting result again immidiately. #if defined Q_WS_WIN32 Sleep(1000); #else sleep(1); #endif } switch(res) { case SQLITE_ROW: // check to see if should fill out columns if (rInf.isEmpty()) // must be first call. init(cnames, colNum, &row); if (!fvals) return FALSE; if (!row) return TRUE; for (i = 0; i < colNum; ++i) (*row)[i] = utf8 ? QString::fromUtf8(fvals[i]) : QString(fvals[i]); return TRUE; case SQLITE_DONE: if (rInf.isEmpty()) // must be first call. init(cnames, colNum); q->setAt(QSql::AfterLast); return FALSE; case SQLITE_ERROR: case SQLITE_MISUSE: default: // something wrong, don't get col info, but still return false finalize(); // finalize to get the error message. q->setAt(QSql::AfterLast); return FALSE; } return FALSE; }
struct _ds_storage_record * _ds_get_nexttoken (DSPAM_CTX * CTX) { struct _sqlite_drv_storage *s = (struct _sqlite_drv_storage *) CTX->storage; struct _ds_storage_record *st; char query[128]; char *err=NULL; const char **row, *query_tail=NULL; int ncolumn, x; if (s->dbh == NULL) { LOGDEBUG ("_ds_get_nexttoken: invalid database handle (NULL)"); return NULL; } st = calloc (1, sizeof (struct _ds_storage_record)); if (st == NULL) { LOG (LOG_CRIT, ERR_MEM_ALLOC); return NULL; } if (s->iter_token == NULL) { snprintf (query, sizeof (query), "select token, spam_hits, innocent_hits, strftime('%%s', " "last_hit) from dspam_token_data"); if ((sqlite_compile(s->dbh, query, &query_tail, &s->iter_token, &err)) !=SQLITE_OK) { _sqlite_drv_query_error (err, query); free(st); return NULL; } } if ((x = sqlite_step(s->iter_token, &ncolumn, &row, NULL)) !=SQLITE_ROW) { if (x != SQLITE_DONE) { _sqlite_drv_query_error (err, query); s->iter_token = NULL; free(st); return NULL; } sqlite_finalize((struct sqlite_vm *) s->iter_token, &err); s->iter_token = NULL; free(st); return NULL; } st->token = strtoull (row[0], NULL, 0); st->spam_hits = strtol (row[1], NULL, 0); st->innocent_hits = strtol (row[2], NULL, 0); st->last_hit = (time_t) strtol (row[3], NULL, 0); return st; }
/* ** Get another row of the given cursor. */ static int cur_fetch (lua_State *L) { cur_data *cur = getcursor(L); sqlite_vm *vm = cur->sql_vm; const char **row = NULL; int res; if (vm == NULL) return 0; res = sqlite_step(vm, NULL, &row, NULL); /* no more results? */ if (res == SQLITE_DONE) return finalize(L, cur); if (res != SQLITE_ROW) return finalize(L, cur); if (lua_istable (L, 2)) { int i; const char *opts = luaL_optstring(L, 3, "n"); if (strchr(opts, 'n') != NULL) { /* Copy values to numerical indices */ for (i = 0; i < cur->numcols;) { lua_pushstring(L, row[i]); lua_rawseti(L, 2, ++i); } } if (strchr(opts, 'a') != NULL) { /* Copy values to alphanumerical indices */ lua_rawgeti(L, LUA_REGISTRYINDEX, cur->colnames); for (i = 0; i < cur->numcols; i++) { lua_rawgeti(L, -1, i+1); lua_pushstring(L, row[i]); lua_rawset (L, 2); } } lua_pushvalue(L, 2); return 1; /* return table */ } else { int i; luaL_checkstack (L, cur->numcols, LUASQL_PREFIX"too many columns"); for (i = 0; i < cur->numcols; ++i) lua_pushstring(L, row[i]); return cur->numcols; /* return #numcols values */ } }
/* ** Usage: sqlite_step VM ?NVAR? ?VALUEVAR? ?COLNAMEVAR? ** ** Step a virtual machine. Return a the result code as a string. ** Column results are written into three variables. */ static int test_step( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite_vm *vm; int rc, i; const char **azValue = 0; const char **azColName = 0; int N = 0; char *zRc; char zBuf[50]; if( argc<2 || argc>5 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " VM NVAR VALUEVAR COLNAMEVAR", 0); return TCL_ERROR; } if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; rc = sqlite_step(vm, argc>=3?&N:0, argc>=4?&azValue:0, argc==5?&azColName:0); if( argc>=3 ){ sprintf(zBuf, "%d", N); Tcl_SetVar(interp, argv[2], zBuf, 0); } if( argc>=4 ){ Tcl_SetVar(interp, argv[3], "", 0); if( azValue ){ for(i=0; i<N; i++){ Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "", TCL_APPEND_VALUE | TCL_LIST_ELEMENT); } } } if( argc==5 ){ Tcl_SetVar(interp, argv[4], "", 0); if( azColName ){ for(i=0; i<N*2; i++){ Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "", TCL_APPEND_VALUE | TCL_LIST_ELEMENT); } } } switch( rc ){ case SQLITE_DONE: zRc = "SQLITE_DONE"; break; case SQLITE_BUSY: zRc = "SQLITE_BUSY"; break; case SQLITE_ROW: zRc = "SQLITE_ROW"; break; case SQLITE_ERROR: zRc = "SQLITE_ERROR"; break; case SQLITE_MISUSE: zRc = "SQLITE_MISUSE"; break; default: zRc = "unknown"; break; } Tcl_AppendResult(interp, zRc, 0); return TCL_OK; }
/* ** Execute an SQL statement. ** Return a Cursor object if the statement is a query, otherwise ** return the number of tuples affected by the statement. */ static int conn_execute(lua_State *L) { conn_data *conn = getconnection(L); const char *statement = luaL_checkstring(L, 2); int res; sqlite_vm *vm; char *errmsg; int numcols; const char **col_info; res = sqlite_compile(conn->sql_conn, statement, NULL, &vm, &errmsg); if (res != SQLITE_OK) { lua_pushnil(L); lua_pushliteral(L, LUASQL_PREFIX); lua_pushstring(L, errmsg); sqlite_freemem(errmsg); lua_concat(L, 2); return 2; } /* process first result to retrive query information and type */ res = sqlite_step(vm, &numcols, NULL, &col_info); /* real query? if empty, must have numcols!=0 */ if ((res == SQLITE_ROW) || ((res == SQLITE_DONE) && numcols)) { sqlite_reset(vm, NULL); return create_cursor(L, 1, conn, vm, numcols, col_info); } if (res == SQLITE_DONE) /* and numcols==0, INSERT,UPDATE,DELETE statement */ { sqlite_finalize(vm, NULL); /* return number of columns changed */ lua_pushnumber(L, sqlite_changes(conn->sql_conn)); return 1; } /* error */ sqlite_finalize(vm, &errmsg); lua_pushnil(L); lua_pushliteral(L, LUASQL_PREFIX); lua_pushstring(L, errmsg); sqlite_freemem(errmsg); lua_concat(L, 2); return 2; }
// Fetchs a new row, returns false if there is no new row bool cDBResult::fetchrow() { if ( !_result ) return false; if ( mysql_type ) { #ifdef MYSQL_DRIVER _row = mysql_fetch_row( ( st_mysql_res * ) _result ); return ( _row != 0 ); #endif } else { int count; const char** columns; return ( sqlite_step( ( sqlite_vm * ) _result, &count, ( const char * ** ) &_row, &columns ) == SQLITE_ROW ); } return false; }
static dfsch_object_t* result_next(sqlite_result_t* res){ char* err; int ret; char**values; pthread_mutex_lock(res->mutex); ret = sqlite_step(res->vm, &res->n_columns, &values, &res->names); if (ret == SQLITE_ROW){ res->last_res = get_row_as_vector(res->n_columns, values); pthread_mutex_unlock(res->mutex); return res; } else { pthread_mutex_unlock(res->mutex); if (ret == SQLITE_BUSY) { dfsch_error("Database is busy", (dfsch_object_t*)res->db); } else if (ret == SQLITE_ERROR){ finalize_result(res); return NULL; } else { return NULL; } } }
bool QSQLite2ResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch) { // may be caching. const char **fvals; const char **cnames; int colNum; int res; int i; if (skipRow) { // already fetched Q_ASSERT(!initialFetch); skipRow = false; for(int i=0;i<firstRow.count(); i++) values[i] = firstRow[i]; return skippedStatus; } skipRow = initialFetch; if (!currentMachine) return false; // keep trying while busy, wish I could implement this better. while ((res = sqlite_step(currentMachine, &colNum, &fvals, &cnames)) == SQLITE_BUSY) { // sleep instead requesting result again immidiately. #if defined Q_WS_WIN32 Sleep(1000); #else sleep(1); #endif } if(initialFetch) { firstRow.clear(); firstRow.resize(colNum); } switch(res) { case SQLITE_ROW: // check to see if should fill out columns if (rInf.isEmpty()) // must be first call. init(cnames, colNum); if (!fvals) return false; if (idx < 0 && !initialFetch) return true; for (i = 0; i < colNum; ++i) values[i + idx] = utf8 ? QString::fromUtf8(fvals[i]) : QString::fromAscii(fvals[i]); return true; case SQLITE_DONE: if (rInf.isEmpty()) // must be first call. init(cnames, colNum); q->setAt(QSql::AfterLastRow); return false; case SQLITE_ERROR: case SQLITE_MISUSE: default: // something wrong, don't get col info, but still return false finalize(); // finalize to get the error message. q->setAt(QSql::AfterLastRow); return false; } return false; }
static int smb_nic_hlist_dbget(smb_hosts_t *hlist) { smb_hostifs_t *iflist; sqlite *db; sqlite_vm *vm; int err = SMB_NIC_SUCCESS; const char **values; char *sql; char *errmsg = NULL; int ncol, rc; sql = sqlite_mprintf("SELECT * FROM hosts"); if (sql == NULL) return (SMB_NIC_NO_MEMORY); db = smb_nic_dbopen(SMB_NIC_DB_ORD); if (db == NULL) { sqlite_freemem(sql); return (SMB_NIC_DBOPEN_FAILED); } rc = sqlite_compile(db, sql, NULL, &vm, &errmsg); sqlite_freemem(sql); if (rc != SQLITE_OK) { smb_nic_dbclose(db); syslog(LOG_ERR, "Failed to query hosts info from host " \ "database. Unable to create virtual machine (%s).", NULL_MSGCHK(errmsg)); return (SMB_NIC_DB_ERROR); } do { rc = sqlite_step(vm, &ncol, &values, NULL); if (rc == SQLITE_ROW) { if (ncol != SMB_NIC_HTBL_NCOL) { err = SMB_NIC_DB_ERROR; break; } if ((iflist = smb_nic_iflist_decode(values, &err)) == NULL) { break; } list_insert_tail(&hlist->h_list, iflist); hlist->h_num++; hlist->h_ifnum += iflist->if_num; } } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE && err == SMB_NIC_SUCCESS) { /* set this error if no previous error */ err = SMB_LGRP_DBEXEC_FAILED; } rc = sqlite_finalize(vm, &errmsg); if (rc != SQLITE_OK) { syslog(LOG_ERR, "Failed to query hosts info from host " \ "database. Unable to destroy virtual machine (%s).", NULL_MSGCHK(errmsg)); if (err == SMB_NIC_SUCCESS) { /* set this error if no previous error */ err = SMB_NIC_DB_ERROR; } } smb_nic_dbclose(db); return (err); }
static array_t *SQLite2_fetch (dbconn_t * c, int row) { int last_row, length, i, l, r; char *p_end; const char *tail; double d; array_t *v; if (!c->SQLite2.vm) { /* We don't have a vm yet because the sql has not been compiled. * This is down to db_exec using sqlite_get_table to execute the sql in the * first instance. This is the reason we saved the sql into the SQLite * structure, compile it now and create a vm. We return a null array only * if the compile fails. */ r = sqlite_compile(c->SQLite2.handle, c->SQLite2.sql, NULL, &c->SQLite2.vm, &c->SQLite2.errormsg); if (r != SQLITE_OK || !c->SQLite2.vm) return &the_null_array; } if (c->SQLite2.step_res && c->SQLite2.step_res != SQLITE_ROW) { return &the_null_array; } if (row < 0 || row > c->SQLite2.nrows) { return &the_null_array; } if (c->SQLite2.ncolumns < 1) { return &the_null_array; } /* If the fetch is for row 0 then we don't return a row containing data values * instead we return the column names. This has proven quite useful in a number * of circumstances when they are unknown ahead of the query. Unlike SQLite3 we * have no means of obtaining them without stepping the virtual machine so we * have no choice. We will have to check the last_row and step_rc later to make * sure we use the values here before we step again. */ if (row == 0) { c->SQLite2.step_res = sqlite_step(c->SQLite2.vm, NULL, &c->SQLite2.values, &c->SQLite2.col_names); if (c->SQLite2.step_res == SQLITE_ROW || c->SQLite2.step_res == SQLITE_DONE) { v = allocate_empty_array(c->SQLite2.ncolumns); for (i = 0; i < c->SQLite2.ncolumns; i++) { v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)c->SQLite2.col_names[i], "SQLite2_fetch"); } return v; } return &the_null_array; } /* There is no quick entry to a row in the prepared statement. Thus we have * too loop through until we reach the desired row, but only if the last row * that we fetched is not the previous row... confused? join the club. */ last_row = c->SQLite2.last_row; /* If the requested row is before the last row that was accessed then we need * to re-compile the sql and recreate the virtual machine. SQLite3 provides a * facility to reset a vm however SQLite2 does not. This is a downfall of * SQLite in general though, we need to restart everything and walk through * all of the results again until we get to the row we want... sigh */ if (row < last_row) { free(c->SQLite2.errormsg); sqlite_finalize(c->SQLite2.vm, NULL); if (sqlite_compile(c->SQLite2.handle, c->SQLite2.sql, &tail, &c->SQLite2.vm, &c->SQLite2.errormsg) != SQLITE_OK) return 0; c->SQLite2.last_row = 0; c->SQLite2.step_res = 0; last_row = 0; } /* If the requested row is the same as the last one, ie: it's been requested * again! we do not need to step forward, so we miss the row location loop * and get straight to the nitty gritty of building the result array. If not * we loop through from the last_row requested to the one requested this time * using sqlite_step(). As long as the result is SQLITE_ROW we move on, if * not then either an error occured or there are no more rows so we return a * null array. The result is stored in the SQLite structure for later checks * so if fetch is called again on a completed or errornous statement we can * fail out sooner saving time. */ if ((row != last_row) && (last_row < row)) { for (i = last_row; i < row; i++) { c->SQLite2.step_res = sqlite_step(c->SQLite2.vm, NULL, &c->SQLite2.values, &c->SQLite2.col_names); if (c->SQLite2.step_res == SQLITE_ROW) break; else return &the_null_array; } } /* SQLite v2 does not provide any functions for obtaining the values based on * their datatypes like v3 does. It is completely typeless and everything is * returned as a (char *). Thus we need a way of determining if the value is * numeric or a string. I do make some assumptions here, but all in all it * does work for the vast majority of cases. There is no support for blobs * to be returned as LPC buffers with v2. Support for binary data in v2 is * suspect at best and is not recommended anyway, if you need that use v3. * * To determine the datatype, we do the following. Run the value through * strtoul() if it fails then the value could not be converted to a number * so we assume it's a string and return it as such. If it works but also * has trailing data, then it might be a real number or a string. Both * "12.34" and "12 bottles" will cause strtoul() to work returning 12 but * both will also have trailing data. Thus we try converting it to a real * number using strtod() if this fails then we assume its a string that * starts with a number ie: "12 bottles" and return it as a string. If it * works then we return it as a real number (float). * * It's by no means perfect, but it does catch pretty much everything I've * thrown at it and is the best solution, bar walking the embedded datatype * description, if one was set, and working it out from that. */ v = allocate_empty_array(c->SQLite2.ncolumns); for (i = 0; i < c->SQLite2.ncolumns; i++) { /* If we have a NULL value get out now or we'll segfault */ if (c->SQLite2.values[i] == NULL) { v->item[i] = const0u; continue; } errno = 0; l = strtoul(c->SQLite2.values[i], &p_end, 10); if (errno != 0 || c->SQLite2.values[i] == p_end) { /* The conversion failed so assume it's a string */ v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)c->SQLite2.values[i], "SQLite2_fetch"); } else if (*p_end != 0) { /* The conversion left trailing characters behind, see if its a float */ errno = 0; d = strtod(c->SQLite2.values[i], &p_end); if (errno != 0 || c->SQLite2.values[i] == p_end || *p_end != 0) { /* The conversion to float failed so it must be a string */ v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)c->SQLite2.values[i], "SQLite2_fetch"); } else { /* It was a floating point number */ v->item[i].type = T_REAL; v->item[i].u.real = (double)d; } } else if (errno == 0) { /* It was an integer */ v->item[i].type = T_NUMBER; v->item[i].u.number = (int)l; } else { /* No idea what it was */ v->item[i] = const0u; } } c->SQLite2.last_row = row; return v; }
/* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result ** the xCallback() function is called. pArg becomes the first ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ int sqlite_exec( sqlite *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE_OK; const char *zLeftover; sqlite_vm *pVm; int nRetry = 0; int nChange = 0; int nCallback; if( zSql==0 ) return SQLITE_OK; while( rc==SQLITE_OK && zSql[0] ){ pVm = 0; rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg); if( rc!=SQLITE_OK ){ assert( pVm==0 || sqlite_malloc_failed ); return rc; } if( pVm==0 ){ /* This happens if the zSql input contained only whitespace */ break; } db->nChange += nChange; nCallback = 0; while(1){ int nArg; char **azArg, **azCol; rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol); if( rc==SQLITE_ROW ){ if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){ sqlite_finalize(pVm, 0); return SQLITE_ABORT; } nCallback++; }else{ if( rc==SQLITE_DONE && nCallback==0 && (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){ xCallback(pArg, nArg, azArg, azCol); } rc = sqlite_finalize(pVm, pzErrMsg); if( rc==SQLITE_SCHEMA && nRetry<2 ){ nRetry++; rc = SQLITE_OK; break; } if( db->pVdbe==0 ){ nChange = db->nChange; } nRetry = 0; zSql = zLeftover; while( isspace(zSql[0]) ) zSql++; break; } } } return rc; }
struct _ds_storage_signature * _ds_get_nextsignature (DSPAM_CTX * CTX) { struct _sqlite_drv_storage *s = (struct _sqlite_drv_storage *) CTX->storage; struct _ds_storage_signature *st; unsigned long length; char query[128]; unsigned char *mem; char *err=NULL; const char **row, *query_tail=NULL; int ncolumn, x; if (s->dbh == NULL) { LOGDEBUG ("_ds_get_nextsignature: invalid database handle (NULL)"); return NULL; } st = calloc (1, sizeof (struct _ds_storage_signature)); if (st == NULL) { LOG (LOG_CRIT, ERR_MEM_ALLOC); return NULL; } if (s->iter_sig == NULL) { snprintf (query, sizeof (query), "select data, signature, strftime('%%s', created_on), " "length(data) from dspam_signature_data"); if ((sqlite_compile(s->dbh, query, &query_tail, &s->iter_sig, &err)) !=SQLITE_OK) { _sqlite_drv_query_error (err, query); free(st); return NULL; } } if ((x = sqlite_step(s->iter_sig, &ncolumn, &row, NULL)) !=SQLITE_ROW) { if (x != SQLITE_DONE) { _sqlite_drv_query_error (err, query); s->iter_sig = NULL; free(st); return NULL; } sqlite_finalize((struct sqlite_vm *) s->iter_sig, &err); s->iter_sig = NULL; free(st); return NULL; } length = strtol(row[3], NULL, 0); if (length == 0) { free(st); return _ds_get_nextsignature(CTX); } mem = malloc (length+1); if (mem == NULL) { LOG (LOG_CRIT, ERR_MEM_ALLOC); sqlite_finalize(s->iter_sig, &err); s->iter_sig = NULL; free(st); return NULL; } length = sqlite_decode_binary((const unsigned char *) &row[ncolumn], mem); if (length<0) { LOG(LOG_ERR, "sqlite_decode_binary() failed with error %d", length); s->iter_sig = NULL; free(st); return NULL; } st->data = realloc(mem, length); strlcpy(st->signature, row[1], sizeof(st->signature)); st->length = length; st->created_on = (time_t) strtol(row[2], NULL, 0); return st; }