[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: SQLite and callbacks

From: Stefan Sperling <stsp_at_elego.de>
Date: Tue, 30 Nov 2010 14:40:46 +0100

On Tue, Nov 30, 2010 at 01:32:27PM +0000, Philip Martin wrote:
> Stefan Sperling <stsp_at_elego.de> writes:
>
> > If you run this version of your test, it will run in an endless loop.
> > The callback inserts new values, the caller will see those and invoke
> > the callback again.
>
> Hmm, I expected the select to block the write causing it to return
> SQLITE_BUSY. That is what happens if the write is done by a separate
> process, but apparently not when it's the same process (or maybe it's
> using the same database handle that makes it work).

With a different db handle, the callback cannot insert values into the db:

$ ./test
Got number: 1
45: 5: database is locked
48: 5: database is locked
Got number: 2
45: 5: database is locked
48: 5: database is locked
Got number: 3
45: 5: database is locked
48: 5: database is locked
Got number: 4
45: 5: database is locked
48: 5: database is locked
Got number: 5
45: 5: database is locked
48: 5: database is locked
Got number: 6
45: 5: database is locked
48: 5: database is locked
Got number: 7
45: 5: database is locked
48: 5: database is locked
Got number: 8
45: 5: database is locked
48: 5: database is locked

#include <stdio.h>
#include <string.h>

#include <sqlite3.h>

#define CHECK_ERR \
  if (sqlite3_errcode(db) \
        && (sqlite3_errcode(db) != SQLITE_ROW) \
        && (sqlite3_errcode(db) != SQLITE_DONE)) \
    fprintf(stderr, "%d: %d: %s\n", __LINE__, sqlite3_errcode(db), sqlite3_errmsg(db));

#define TEST_DATA \
  "create table foo (num int, message text); " \
  "" \
  "insert into foo values (1, 'A is for Allegator'); " \
  "insert into foo values (2, 'B is for Bayou'); " \
  "insert into foo values (3, 'C is for Cyprus Trees'); " \
  "insert into foo values (4, 'D is for Dew'); " \
  "insert into foo values (5, 'E is for Everything like'); " \
  "insert into foo values (6, 'F Ferns or'); " \
  "insert into foo values (7, 'G Grass that''s'); " \
  "insert into foo values (8, 'H Home to you'); " \
  ""

void callback(int num)
{
  const char *query = "insert into foo values (?1,?2);";
  sqlite3_stmt *stmt;
  const unsigned char *msg = "new message for you!";
  sqlite3 *db;

  sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                  NULL);

  printf("Got number: %d\n", num);

  sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
  CHECK_ERR;

  sqlite3_bind_int(stmt, 1, 42);
  sqlite3_bind_text(stmt, 2, msg, strlen(msg) + 1, SQLITE_STATIC);
  CHECK_ERR;

  sqlite3_step(stmt);
  CHECK_ERR;

  sqlite3_finalize(stmt);
  CHECK_ERR;

  sqlite3_close(db);
}

void get_numbers(sqlite3 *db,
                 void (*callback)(int))
{
  const char *query = "select num from foo;";
  sqlite3_stmt *stmt;
  int code;

  sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
  CHECK_ERR;

  code = sqlite3_step(stmt);
  CHECK_ERR;
  while (code == SQLITE_ROW)
    {
      int number = sqlite3_column_int(stmt, 0);
      callback(number);

      code = sqlite3_step(stmt);
      CHECK_ERR;
    }

  sqlite3_finalize(stmt);
  CHECK_ERR;
}

int
main(int argc, char *argv[])
{
  sqlite3 *db;

  remove("test.db");

  sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                  NULL);
  CHECK_ERR;

  sqlite3_extended_result_codes(db, 1);
  CHECK_ERR;

  sqlite3_exec(db, TEST_DATA, NULL, NULL, NULL);
  CHECK_ERR;

  get_numbers(db, callback);

  sqlite3_close(db);

  return 0;
}
Received on 2010-11-30 14:41:27 CET

This is an archived mail posted to the Subversion Dev mailing list.