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

/* Instructions: grab a read lock, then try two inserts without resetting.
 * $ rm a.db
 * $ sqlite3 a.db < write-misuse-demo.sql
 * $ sqlite3 a.db
 * sqlite> BEGIN; SELECT * FROM c;
 * a|b
 * c|d
 * sqlite> [stay at prompt]
 *
 * Now, in another shell:
 * ./write-misuse-demo.sql a.db
 * Insert 1 SQL error 5: database is locked
 * Insert 2 succeeded, 1 rows changed          [?!]
 *
 * However, Insert 2 did not actually insert a row.
 *
 * Tested with SQLite 3.6.11 [prepare_v2] and 3.1.3 [prepare]
 */

int main(int argc, char **argv){
  sqlite3 *db;
  sqlite3_stmt *s1 = NULL, *s2 = NULL;
  char *zErrMsg = 0;
  int rc;

  if (argc != 2){
    fprintf(stderr, "usage: %s db\n", argv[0]);
    exit(1);
  }
  rc = sqlite3_open(argv[1], &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }

  rc = sqlite3_prepare_v2(db, "INSERT into c(k,v) VALUES('d', 'e');",
                          -1, &s1, NULL);
  if( rc!=SQLITE_OK ){
      fprintf(stderr, "SQL error %d: %s\n", rc, sqlite3_errmsg(db));
      goto end;
  }

  rc = sqlite3_prepare_v2(db, "INSERT into c(k,v) VALUES('f', 'g');",
                          -1, &s2, NULL);
  if( rc!=SQLITE_OK ){
      fprintf(stderr, "SQL error %d: %s\n", rc, sqlite3_errmsg(db));
      goto end;
  }

  rc = sqlite3_step(s1);
  if( rc!=SQLITE_DONE ){
      fprintf(stderr, "Insert 1 SQL error %d: %s\n", rc, sqlite3_errmsg(db));
      /* sqlite3_reset(s1); */  /* reset required on BUSY, or Insert 2 "succeeds" */
  } else {
      fprintf(stderr, "Insert 1 succeeded, %d rows changed\n", sqlite3_changes(db));      
  }

  rc = sqlite3_step(s2);  
  if( rc!=SQLITE_DONE ){
      fprintf(stderr, "Insert 2 SQL error %d: %s\n", rc, sqlite3_errmsg(db));
  } else {
      fprintf(stderr, "Insert 2 succeeded, %d rows changed\n", sqlite3_changes(db));
  }
  

end:
  if (s1) sqlite3_finalize(s1);
  if (s2) sqlite3_finalize(s2);
  sqlite3_close(db);
  return 0;
}  
