On Thu, Feb 21, 2013 at 1:32 PM, Peter Aronson <[email protected]> wrote:
> 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.
>
(1) CREATE TEMP TABLE xyz AS SELECT...;
(2) Query the xyz table while doing whatever updates are needed.
(3) DROP TABLE xyz;
The other thing you can do is open two database connections on the same
database (in WAL mode) and query from one while updating on the other.
>
> 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
>
--
D. Richard Hipp
[email protected]
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users