示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
文件: ls_sqlite.c 项目: 0w/moai-dev
/*
** 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 */
	}
}
示例#4
0
文件: test1.c 项目: ErikGartner/ardb
/*
** 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;
}
示例#5
0
文件: ls_sqlite.c 项目: 0w/moai-dev
/*
** 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;
}
示例#7
0
文件: sqlite.c 项目: adh/dfsch
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;
    }
  }
}
示例#8
0
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;
}
示例#9
0
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);
}
示例#10
0
文件: db.c 项目: BPotato/fluffos
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;
}
示例#11
0
文件: main.c 项目: gitpan/DBD-SQLite2
/*
** 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;
}
示例#12
0
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;
}