[GRASS-SVN] r48332 - grass/trunk/db/drivers/sqlite

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Sep 17 10:38:38 EDT 2011


Author: mmetz
Date: 2011-09-17 07:38:36 -0700 (Sat, 17 Sep 2011)
New Revision: 48332

Modified:
   grass/trunk/db/drivers/sqlite/create_table.c
   grass/trunk/db/drivers/sqlite/describe.c
   grass/trunk/db/drivers/sqlite/execute.c
   grass/trunk/db/drivers/sqlite/fetch.c
   grass/trunk/db/drivers/sqlite/index.c
   grass/trunk/db/drivers/sqlite/main.c
   grass/trunk/db/drivers/sqlite/select.c
Log:
SQLITE driver: fix for #548

Modified: grass/trunk/db/drivers/sqlite/create_table.c
===================================================================
--- grass/trunk/db/drivers/sqlite/create_table.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/create_table.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -112,26 +112,38 @@
 
     G_debug(3, " SQL: %s", db_get_string(&sql));
 
-    ret = sqlite3_prepare(sqlite, db_get_string(&sql), -1, &statement, &rest);
+    /* SQLITE bug?
+     * If the database schema has changed, sqlite can prepare a statement,
+     * but sqlite can not step, the statement needs to be prepared anew again */
+    while (1) {
+	ret = sqlite3_prepare(sqlite, db_get_string(&sql), -1, &statement, &rest);
 
-    if (ret != SQLITE_OK) {
-	append_error("Cannot create table:\n");
-	append_error(db_get_string(&sql));
-	append_error("\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	sqlite3_finalize(statement);
-	db_free_string(&sql);
-	return DB_FAILED;
-    }
+	if (ret != SQLITE_OK) {
+	    append_error("Cannot create table:\n");
+	    append_error(db_get_string(&sql));
+	    append_error("\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    sqlite3_finalize(statement);
+	    db_free_string(&sql);
+	    return DB_FAILED;
+	}
 
-    ret = sqlite3_step(statement);
+	ret = sqlite3_step(statement);
 
-    if (ret != SQLITE_DONE) {
-	append_error("Error in sqlite3_step():\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	return DB_FAILED;
+	if (ret == SQLITE_SCHEMA) {
+	    sqlite3_finalize(statement);
+	    /* try again */
+	}
+	else if (ret != SQLITE_DONE) {
+	    append_error("Error in sqlite3_step():\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    sqlite3_finalize(statement);
+	    return DB_FAILED;
+	}
+	else
+	    break;
     }
 
     sqlite3_finalize(statement);

Modified: grass/trunk/db/drivers/sqlite/describe.c
===================================================================
--- grass/trunk/db/drivers/sqlite/describe.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/describe.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -49,30 +49,43 @@
     db_append_string(&sql, db_get_string(table_name));
     db_append_string(&sql, " where oid < 0");
 
-    ret = sqlite3_prepare(sqlite, db_get_string(&sql), -1, &statement, &rest);
-    while (ret == SQLITE_BUSY || ret == SQLITE_IOERR_BLOCKED) {
-	ret = sqlite3_busy_handler(sqlite, sqlite_busy_callback, NULL);
-    }
+    /* SQLITE bug?
+     * If the database schema has changed, sqlite can prepare a statement,
+     * but sqlite can not step, the statement needs to be prepared anew again */
+    while (1) {
+	ret = sqlite3_prepare(sqlite, db_get_string(&sql), -1, &statement, &rest);
 
-    if (ret != SQLITE_OK) {
-	append_error("Error in sqlite3_prepare():");
-	append_error(db_get_string(&sql));
-	append_error("\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	db_free_string(&sql);
-	return DB_FAILED;
+	if (ret != SQLITE_OK) {
+	    append_error("Error in sqlite3_prepare():");
+	    append_error(db_get_string(&sql));
+	    append_error("\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    db_free_string(&sql);
+	    return DB_FAILED;
+	}
+
+	if (describe_table(statement, table, NULL) == DB_FAILED) {
+
+	    ret = sqlite3_errcode(sqlite);
+	    if (ret == SQLITE_SCHEMA) {
+		sqlite3_finalize(statement);
+		/* try again */
+	    }
+	    else {
+		append_error("Cannot describe table:\n");
+		append_error((char *)sqlite3_errmsg(sqlite));
+		report_error();
+		sqlite3_finalize(statement);
+		return DB_FAILED;
+	    }
+	}
+	else
+	    break;
     }
 
     db_free_string(&sql);
 
-    if (describe_table(statement, table, NULL) == DB_FAILED) {
-	append_error("Cannot describe table\n");
-	report_error();
-	sqlite3_finalize(statement);
-	return DB_FAILED;
-    }
-
     sqlite3_finalize(statement);
 
     return DB_OK;
@@ -94,15 +107,19 @@
 
 int describe_table(sqlite3_stmt * statement, dbTable ** table, cursor * c)
 {
-    int i, ncols, nkcols;
+    int i, ncols, nkcols, ret;
 
     G_debug(3, "describe_table()");
 
     ncols = sqlite3_column_count(statement);
-    G_debug(3, "ncols = %d", ncols);
 
     /* Try to get first row */
-    sqlite3_step(statement);
+    ret = sqlite3_step(statement);
+    if (ret != SQLITE_DONE && ret != SQLITE_ROW) {
+	ret = sqlite3_reset(statement);
+	G_warning(_("SQLite driver: %s"), sqlite3_errmsg(sqlite));
+	return DB_FAILED;
+    }
 
     /* Count columns of known type */
     nkcols = 0;

Modified: grass/trunk/db/drivers/sqlite/execute.c
===================================================================
--- grass/trunk/db/drivers/sqlite/execute.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/execute.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -41,23 +41,34 @@
 
     G_debug(3, "execute: %s", s);
 
-    ret = sqlite3_prepare(sqlite, s, -1, &stmt, &rest);
+    /* SQLITE bug?
+     * If the database schema has changed, sqlite can prepare a statement,
+     * but sqlite can not step, the statement needs to be prepared anew again */
+    while (1) {
+	ret = sqlite3_prepare(sqlite, s, -1, &stmt, &rest);
 
-    if (ret != SQLITE_OK) {
-	append_error("Error in sqlite3_prepare():\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	return DB_FAILED;
-    }
+	if (ret != SQLITE_OK) {
+	    append_error("Error in sqlite3_prepare():\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    return DB_FAILED;
+	}
 
-    ret = sqlite3_step(stmt);
-    /* check if sqlite is still busy preparing the statement? */
+	ret = sqlite3_step(stmt);
 
-    if (ret != SQLITE_DONE) {
-	append_error("Error in sqlite3_step():\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	return DB_FAILED;
+	if (ret == SQLITE_SCHEMA) {
+	    sqlite3_finalize(stmt);
+	    /* try again */
+	}
+	else if (ret != SQLITE_DONE) {
+	    append_error("Error in sqlite3_step():\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    ret = sqlite3_finalize(stmt);
+	    return DB_FAILED;
+	}
+	else
+	    break;
     }
 
     ret = sqlite3_finalize(stmt);
@@ -69,11 +80,6 @@
 	return DB_FAILED;
     }
 
-    /*
-       if ( rest )
-       G_free ( rest );
-     */
-
     return DB_OK;
 }
 

Modified: grass/trunk/db/drivers/sqlite/fetch.c
===================================================================
--- grass/trunk/db/drivers/sqlite/fetch.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/fetch.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -249,7 +249,7 @@
 {
     cursor *c;
     dbToken token;
-    int row;
+    int row, ret;
 
     /* get cursor token */
     token = db_get_cursor_token(cn);
@@ -268,10 +268,18 @@
     sqlite3_reset(c->statement);
 
     c->nrows = 0;
-    while (sqlite3_step(c->statement) == SQLITE_ROW) {
+    while ((ret = sqlite3_step(c->statement)) == SQLITE_ROW) {
 	c->nrows++;
     }
 
+    if (ret != SQLITE_DONE) {
+	ret = sqlite3_reset(c->statement);
+	append_error("Cannot get number of rows\n");
+	append_error((char *)sqlite3_errmsg(sqlite));
+	report_error();
+	return DB_FAILED;
+    }
+
     sqlite3_reset(c->statement);
 
     /* Reset cursor position */

Modified: grass/trunk/db/drivers/sqlite/index.c
===================================================================
--- grass/trunk/db/drivers/sqlite/index.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/index.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -65,26 +65,37 @@
 
     G_debug(3, " SQL: %s", db_get_string(&sql));
 
-    ret = sqlite3_prepare(sqlite, db_get_string(&sql), -1, &statement, &rest);
+    /* SQLITE bug?
+     * If the database schema has changed, sqlite can prepare a statement,
+     * but sqlite can not step, the statement needs to be prepared anew again */
+    while (1) {
+	ret = sqlite3_prepare(sqlite, db_get_string(&sql), -1, &statement, &rest);
 
-    if (ret != SQLITE_OK) {
-	append_error("Cannot create index:\n");
-	append_error(db_get_string(&sql));
-	append_error("\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	sqlite3_finalize(statement);
-	db_free_string(&sql);
-	return DB_FAILED;
-    }
+	if (ret != SQLITE_OK) {
+	    append_error("Cannot create index:\n");
+	    append_error(db_get_string(&sql));
+	    append_error("\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    sqlite3_finalize(statement);
+	    db_free_string(&sql);
+	    return DB_FAILED;
+	}
 
-    ret = sqlite3_step(statement);
+	ret = sqlite3_step(statement);
 
-    if (ret != SQLITE_DONE) {
-	append_error("Error in sqlite3_step():\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	return DB_FAILED;
+	if (ret == SQLITE_SCHEMA) {
+	    sqlite3_finalize(statement);
+	    /* try again */
+	}
+	else if (ret != SQLITE_DONE) {
+	    append_error("Error in sqlite3_step():\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    return DB_FAILED;
+	}
+	else
+	    break;
     }
 
     sqlite3_reset(statement);

Modified: grass/trunk/db/drivers/sqlite/main.c
===================================================================
--- grass/trunk/db/drivers/sqlite/main.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/main.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -15,7 +15,9 @@
 
 #include <stdlib.h>
 #include <time.h>
+#include <grass/gis.h>
 #include <grass/dbmi.h>
+#include <grass/glocale.h>
 #include "globals.h"
 #include "dbdriver.h"
 
@@ -31,21 +33,23 @@
 {
     static time_t start_time = 0;
     time_t curr_time;
-    int min;
-    static int last_min = -1;
+    int sec;
+    static int last_sec = -1;
 
+    G_debug(4, "sqlite_busy_callback()");
+
     /* do something here while waiting? */
-    if (n_calls > 0 && last_min > -1) {
+    if (n_calls > 0 && last_sec > -1) {
 	time(&curr_time);
-	min = (curr_time - start_time) / 60;
-	if (min > 1 && min > last_min) {
-	    last_min = min;
-	    G_debug(3, "Already waiting for %d minutes...", min);
+	sec = (curr_time - start_time);
+	if (sec > 1 && sec > last_sec && sec % 10 == 0) {
+	    last_sec = sec;
+	    G_warning(_("Busy SQLITE db, already waiting for %d seconds..."), sec);
 	}
     }
     else {
 	time(&start_time);
-	last_min = 0;
+	last_sec = 0;
     }
 
     return 1;

Modified: grass/trunk/db/drivers/sqlite/select.c
===================================================================
--- grass/trunk/db/drivers/sqlite/select.c	2011-09-17 12:12:23 UTC (rev 48331)
+++ grass/trunk/db/drivers/sqlite/select.c	2011-09-17 14:38:36 UTC (rev 48332)
@@ -53,26 +53,41 @@
     str = G_str_replace(db_get_string(sel), "\\", "\\\\");
     G_debug(3, "Escaped SQL: %s", str);
 
-    ret = sqlite3_prepare(sqlite, str, -1, &(c->statement), &rest);
+    /* SQLITE bug?
+     * If the database schema has changed, sqlite can prepare a statement,
+     * but sqlite can not step, the statement needs to be prepared anew again */
+    while (1) {
+	ret = sqlite3_prepare(sqlite, str, -1, &(c->statement), &rest);
 
+	if (ret != SQLITE_OK) {
+	    append_error("Error in sqlite3_prepare():");
+	    append_error(db_get_string(sel));
+	    append_error("\n");
+	    append_error((char *)sqlite3_errmsg(sqlite));
+	    report_error();
+	    return DB_FAILED;
+	}
+
+	if (describe_table(c->statement, &table, c) == DB_FAILED) {
+	    ret = sqlite3_errcode(sqlite);
+	    if (ret == SQLITE_SCHEMA) {
+		sqlite3_finalize(c->statement);
+		/* try again */
+	    }
+	    else {
+		append_error("Cannot describe table\n");
+		append_error((char *)sqlite3_errmsg(sqlite));
+		report_error();
+		return DB_FAILED;
+	    }
+	}
+	else
+	    break;
+    }
+    
     if (str)
 	G_free(str);
 
-    if (ret != SQLITE_OK) {
-	append_error("Error in sqlite3_prepare():");
-	append_error(db_get_string(sel));
-	append_error("\n");
-	append_error((char *)sqlite3_errmsg(sqlite));
-	report_error();
-	return DB_FAILED;
-    }
-
-    if (describe_table(c->statement, &table, c) == DB_FAILED) {
-	append_error("Cannot describe table\n");
-	report_error();
-	return DB_FAILED;
-    }
-
     c->nrows = -1;
     c->row = -1;
 



More information about the grass-commit mailing list