Someone over here was trying to use a shared-cache in-memory database with
two connections, one a read-write connection for purposes of populating
things, the other a read-only connection for purposes of letting a
(trusted) user make queries.  They were surprised to find out that they
could run write queries against the read-only handle (the insert query in
my example).  Also, if you flip the order of the opens so that the
read-only open happens first, then the create statement fails
with SQLITE_READONLY.

[Aside: I suggested that it might be more appropriate to use an authorizer,
rather than try to open an in-memory database read-only.]

A couple minutes in the code makes me think that the sense of
"cache=shared" is implemented at the btree.c layer, so it is somewhat
unlikely that this is reasonable to actually support.  That said, it is
unexpected.  It seems like the library should throw something like
SQLITE_MISUSE when you request a shared-cache open incompatible with
previous opens.  WDYT?

The same basic problem also appears to happen for on-disk databases, which
makes me wonder if we're just doing something wrong.

Thanks,
scott

---
/* gcc -g -o sqlmem sqlmem.c sqlite3.c */

#include "sqlite3.h"
#include <stdio.h>

int main(int argc, char** argv) {
  sqlite3* rw;
  sqlite3* ro;
  int rc;
  char* err;

  rc = sqlite3_open_v2("file::memory:?cache=shared", &rw,
                       SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI, NULL);
  if (rc!=SQLITE_OK) {
    fprintf(stderr, "rw rc==%d\n", rc);
    return 1;
  }

  rc = sqlite3_open_v2("file::memory:?cache=shared", &ro,
                       SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, NULL);
  if (rc!=SQLITE_OK) {
    fprintf(stderr, "ro rc==%d\n", rc);
    return 1;
  }

  rc = sqlite3_exec(rw, "CREATE TABLE t (a TEXT)", NULL, NULL, &err);
  if (rc!=SQLITE_OK) {
    fprintf(stderr, "rw create error: %d/%s\n", rc, err);
    return 1;
  }

  rc = sqlite3_exec(ro, "SELECT 1", NULL, NULL, &err);
  if (rc!=SQLITE_OK) {
    fprintf(stderr, "ro select error: %d/%s\n", rc, err);
    return 1;
  }

  rc = sqlite3_exec(ro, "INSERT INTO t (a) VALUES ('a')", NULL, NULL, &err);
  if (rc!=SQLITE_OK) {
    fprintf(stderr, "ro insert error: %d/%s\n", rc, err);
    return 1;
  } else {
    fprintf(stderr, "ro insert succeeeded?\n");
    return 1;
  }
}
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to