SQLite 3.7.15.2, Solaris and Windows (and presumably others).  Journal mode is 
delete, but WAL appears to behave in the same manner.

One of my coworkers ran into an infinite loop when accessing SQLite. 
Essentially 
an outer select loop was reading records, and an inner select loop was 
inserting 
records based on the records found into the same table.  The loop never ended 
as 
the records inserted showed up in the select.  This is not necessarily an 
error, 
of course.  But if you take the script and the program below which reproduces 
the problem, add "order by c3" to the select statement, it doesn't happen 
(presumably because we're reading the materialized temporary table, not the 
base 
table at that point).  This sort of inconsistency can be an unpleasant surprise.

If you look at SQL 92, it has a concept of INSENSITIVE cursors, which causes 
the 
cursor to logically (at least) work on a copy of the data, so that changes to 
the underlying table are not visible.  It would be nice if SQLite provided a 
method to make a insensitive select ("order by rowid" appears to get silently 
removed by the optimizer as you'd expect) less expensive than performing an 
otherwise unnecessary order by.

Peter

create table base1 (c1 integer,c2 text,c3 integer); 
insert into base1 (c1,c2,c3) values (1,'andrew',10); 
insert into base1 (c1,c2,c3) values (1,'jeffrey',15); 
insert into base1 (c1,c2,c3) values (1,'david',20); 
insert into base1 (c1,c2,c3) values (1,'Jonathan',25);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
int main (int  argc,
          char *argv[])
{
  sqlite3       *hdbc;
  int           s3err,rid,c3;
  sqlite3_stmt  *hupdate,*hselect;
  char          sql[256];

  /* Open our test database (assumed to be named test.db). */

  s3err = sqlite3_open_v2 ("test.db",
                           &hdbc,
                           SQLITE_OPEN_READWRITE,
                           NULL);
  if (SQLITE_OK != s3err) {
    fprintf (stderr,"Unable to open test.db, err = %d\n",s3err);
    return EXIT_FAILURE;
  }

  /* Start a select on base1. */

  s3err = sqlite3_prepare_v2 (hdbc,
                              "select rowid,c3 "
                              "from base1 "
                              "where c3 < 15 and c1 = 1",
                              -1,
                              &hselect,
                              NULL);
  if (SQLITE_OK != s3err) {
    fprintf (stderr,"Unable to prepare select on base1, err = %d\n",s3err);
    return EXIT_FAILURE;
  }

  while ((s3err = sqlite3_step (hselect)) == SQLITE_ROW) {
    rid = sqlite3_column_int (hselect,0);
    c3 = sqlite3_column_int (hselect,1);
    sprintf (sql,"insert into base1 (c1,c2,c3) values (1,'inactive',%d)",c3);
    
    /* Insert into base1. */

    s3err = sqlite3_prepare_v2 (hdbc,
                                sql,
                                -1,
                                &hupdate,
                                NULL);
    if (SQLITE_OK != s3err) {
      fprintf (stderr,"Unable to prepare insert on base1, err = %d\n",s3err);
      return EXIT_FAILURE;
    }

    switch (sqlite3_step (hupdate)) {
    case SQLITE_DONE:
    case SQLITE_ROW:
      printf ("%d:",rid);
      fflush (stdout);
      sqlite3_finalize (hupdate);
      break;
    default:
      fprintf (stderr,"Error on sqlite3_step for insert, err = %d\n",s3err);
      return EXIT_FAILURE;
    }
  }
  sqlite3_finalize (hselect);
  if (SQLITE_DONE != s3err) {
    fprintf (stderr,"Error on sqlite3_step for select, err = %d\n",s3err);
    return EXIT_FAILURE;
  }
  
  (void) sqlite3_close (hdbc);
  
  return EXIT_SUCCESS;
}

_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to