r19798 - gnucash/trunk/src - Bug 634392: New sql database raises clobber warning

John Ralls jralls at code.gnucash.org
Thu Nov 11 01:12:20 EST 2010


Author: jralls
Date: 2010-11-11 01:12:20 -0500 (Thu, 11 Nov 2010)
New Revision: 19798
Trac: http://svn.gnucash.org/trac/changeset/19798

Modified:
   gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c
   gnucash/trunk/src/backend/dbi/test/test-dbi-business-stuff.c
   gnucash/trunk/src/backend/dbi/test/test-dbi-stuff.c
   gnucash/trunk/src/backend/dbi/test/test-dbi.c
   gnucash/trunk/src/backend/xml/gnc-backend-xml.c
   gnucash/trunk/src/backend/xml/test/test-load-xml2.c
   gnucash/trunk/src/backend/xml/test/test-save-in-lang.c
   gnucash/trunk/src/bin/gnucash-bin.c
   gnucash/trunk/src/business/business-core/test/test-customer.c
   gnucash/trunk/src/business/business-core/test/test-employee.c
   gnucash/trunk/src/business/business-core/test/test-job.c
   gnucash/trunk/src/business/business-core/test/test-vendor.c
   gnucash/trunk/src/engine/test/test-recursive.c
   gnucash/trunk/src/gnome-utils/druid-gnc-xml-import.c
   gnucash/trunk/src/gnome-utils/gnc-file.c
   gnucash/trunk/src/libqof/qof/qofbackend-p.h
   gnucash/trunk/src/libqof/qof/qofbackend.h
   gnucash/trunk/src/libqof/qof/qofsession.c
   gnucash/trunk/src/libqof/qof/qofsession.h
Log:
Bug 634392: New sql database raises clobber warning

A fairly extensive change, because I changed may_clobber from a global 
qof function (which passed through qofbackend and fetched up in the 
actual backends) to a local static in the individual backends which 
raise a new qof_backend_error, QOF_ABCKEND_STORE_EXISTS. This was 
necessary to reorder the existence check before the lock, because with 
the sql backends, locking creates the database... which then would 
return may_clobber as true, even though it really wasn't.

New parameter "force" added to session_begin() functions, and 
"create_if_nonexistant" is renamed to simply "create". The reason for 
the latter is that the file/database is created regardless of whether it 
already exists; that's what the clobber check is about. The new "force" 
parameter is set to true the second time through, after the user has 
responded to the clobber dialog indicating that the data should be 
destroyed.

Many of the extraneous changes are just adding the new parameter to the 
session_begin() calls.

gnc-file changes to handle the error in favor of calling the 
no-longer-existing qof_check_may_clobber_data() call after 
session_begin().

Two minor changes to gnc_file_do_save_as: gnc_add_history and 
gnc_hook_run are now called on new_session instead of old_session; this 
ensures that the new file/database is used at the next startup of 
gnucash. Second, the filename/url is filtered before displaying the 
"may_clobber" dialog box to prevent displaying plaintext database 
passwords.



Modified: gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c
===================================================================
--- gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/dbi/gnc-backend-dbi.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -122,6 +122,7 @@
 static void append_pgsql_col_def( GString* ddl, GncSqlColumnInfo* info );
 static gboolean gnc_dbi_lock_database( QofBackend *qbe, gboolean ignore_lock );
 static void gnc_dbi_unlock( QofBackend *qbe );
+static gboolean save_may_clobber_data( QofBackend* qbe );
 
 static provider_functions_t provider_pgsql =
 {
@@ -260,7 +261,7 @@
 static void
 gnc_dbi_sqlite3_session_begin( QofBackend *qbe, QofSession *session,
                                const gchar *book_id, gboolean ignore_lock,
-                               gboolean create_if_nonexistent )
+                               gboolean create, gboolean force )
 {
     GncDbiBackend *be = (GncDbiBackend*)qbe;
     gint result;
@@ -277,14 +278,23 @@
     /* Remove uri type if present */
     filepath = gnc_uri_get_path ( book_id );
 
-    if ( !create_if_nonexistent
-            && !g_file_test( filepath, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS ) )
+    if ( !create &&
+	 !g_file_test( filepath, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS ) )
     {
         qof_backend_set_error( qbe, ERR_FILEIO_FILE_NOT_FOUND );
         LEAVE(" ");
         return;
     }
 
+    if ( create && !force && 
+	 g_file_test( filepath, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS ) )
+    {
+        qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS);
+        LEAVE("Might clobber, no force");
+        return;
+    }
+
+
     if ( be->conn != NULL )
     {
         dbi_conn_close( be->conn );
@@ -668,7 +678,7 @@
 static void
 gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
                              const gchar *book_id, gboolean ignore_lock,
-                             gboolean create_if_nonexistent )
+                             gboolean create, gboolean force )
 {
     GncDbiBackend *be = (GncDbiBackend*)qbe;
     gchar* protocol = NULL;
@@ -692,7 +702,7 @@
     gnc_uri_get_components ( book_id, &protocol, &host, &portnum,
                              &username, &password, &dbname );
 
-    // Try to connect to the db.  If it doesn't exist and the create_if_nonexistent
+    // Try to connect to the db.  If it doesn't exist and the create
     // flag is TRUE, we'll need to connect to the 'mysql' db and execute the
     // CREATE DATABASE ddl statement there.
     if ( be->conn != NULL )
@@ -715,6 +725,13 @@
     result = dbi_conn_connect( be->conn );
     if ( result == 0 )
     {
+	if (create && !force && save_may_clobber_data( qbe ) )
+	{
+	    qof_backend_set_error ( qbe, ERR_BACKEND_STORE_EXISTS );
+	    PWARN("Databse already exists, Might clobber it.");
+	    goto exit;
+	}
+
         success = gnc_dbi_lock_database ( qbe, ignore_lock );
     }
     else
@@ -728,7 +745,7 @@
         }
 
         // The db does not already exist.  Connect to the 'mysql' db and try to create it.
-        if ( create_if_nonexistent )
+        if ( create )
         {
             dbi_result dresult;
             result = dbi_conn_set_option( be->conn, "dbname", "mysql" );
@@ -862,7 +879,7 @@
 static void
 gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
                                 const gchar *book_id, gboolean ignore_lock,
-                                gboolean create_if_nonexistent )
+                                gboolean create, gboolean force )
 {
     GncDbiBackend *be = (GncDbiBackend*)qbe;
     gint result = 0;
@@ -888,7 +905,7 @@
     if ( portnum == 0 )
         portnum = PGSQL_DEFAULT_PORT;
 
-    // Try to connect to the db.  If it doesn't exist and the create_if_nonexistent
+    // Try to connect to the db.  If it doesn't exist and the create
     // flag is TRUE, we'll need to connect to the 'postgres' db and execute the
     // CREATE DATABASE ddl statement there.
     if ( be->conn != NULL )
@@ -911,6 +928,13 @@
     result = dbi_conn_connect( be->conn );
     if ( result == 0 )
     {
+	if (create && !force && save_may_clobber_data( qbe ) )
+	{
+	    qof_backend_set_error ( qbe, ERR_BACKEND_STORE_EXISTS );
+	    PWARN("Databse already exists, Might clobber it.");
+	    goto exit;
+	}
+
         success = gnc_dbi_lock_database ( qbe, ignore_lock );
     }
     else
@@ -924,7 +948,7 @@
         }
 
         // The db does not already exist.  Connect to the 'postgres' db and try to create it.
-        if ( create_if_nonexistent )
+        if ( create )
         {
             dbi_result dresult;
             result = dbi_conn_set_option( be->conn, "dbname", "postgres" );
@@ -1066,29 +1090,22 @@
 /* ================================================================= */
 
 static gboolean
-gnc_dbi_save_may_clobber_data( QofBackend* qbe )
+save_may_clobber_data( QofBackend* qbe )
 {
     GncDbiBackend* be = (GncDbiBackend*)qbe;
     const gchar* dbname;
-    GSList* table_name_list;
-    gint numTables = 0;
-    gint status;
+    dbi_result result;
+    gboolean retval = FALSE;
 
     /* Data may be clobbered iff the number of tables != 0 */
     dbname = dbi_conn_get_option( be->conn, "dbname" );
-    table_name_list = ((GncDbiSqlConnection*)(be->sql_be.conn))->provider->get_table_list( be->conn, dbname );
-    if ( table_name_list != NULL )
+    result = dbi_conn_get_table_list( be->conn, dbname, NULL );
+    if ( result )
     {
-        GSList* node;
-        numTables = g_slist_length( table_name_list );
-        for ( node = table_name_list; node != NULL; node = node->next )
-        {
-            g_free( node->data );
-        }
-        g_slist_free( table_name_list );
+      retval =  dbi_result_get_numrows( result ) > 0;
+      dbi_result_free( result );
     }
-
-    return (numTables != 0);
+    return retval;
 }
 
 static void
@@ -1195,7 +1212,6 @@
     be->destroy_backend = gnc_dbi_destroy_backend;
 
     be->load = gnc_dbi_load;
-    be->save_may_clobber_data = gnc_dbi_save_may_clobber_data;
 
     /* The gda backend treats accounting periods transactionally. */
     be->begin = gnc_dbi_begin_edit;
@@ -1223,7 +1239,9 @@
 
 static QofBackend*
 new_backend( void (*session_begin)( QofBackend *, QofSession *, const gchar *,
-                                    /*@ unused @*/ gboolean, /*@ unused @*/ gboolean ) )
+                                    /*@ unused @*/ gboolean,
+                                    /*@ unused @*/ gboolean,
+				    /*@ unused @*/ gboolean ) )
 {
     GncDbiBackend *dbi_be;
     QofBackend *be;

Modified: gnucash/trunk/src/backend/dbi/test/test-dbi-business-stuff.c
===================================================================
--- gnucash/trunk/src/backend/dbi/test/test-dbi-business-stuff.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/dbi/test/test-dbi-business-stuff.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -198,13 +198,13 @@
 
     // Save the session data
     session_2 = qof_session_new();
-    qof_session_begin( session_2, url, FALSE, TRUE );
+    qof_session_begin( session_2, url, FALSE, TRUE, TRUE );
     qof_session_swap_data( session_1, session_2 );
     qof_session_save( session_2, NULL );
 
     // Reload the session data
     session_3 = qof_session_new();
-    qof_session_begin( session_3, url, TRUE, FALSE );
+    qof_session_begin( session_3, url, TRUE, FALSE, FALSE );
     qof_session_load( session_3, NULL );
 
     // Compare with the original data

Modified: gnucash/trunk/src/backend/dbi/test/test-dbi-stuff.c
===================================================================
--- gnucash/trunk/src/backend/dbi/test/test-dbi-stuff.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/dbi/test/test-dbi-stuff.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -151,13 +151,13 @@
 
     // Save the session data
     session_2 = qof_session_new();
-    qof_session_begin( session_2, url, FALSE, TRUE );
+    qof_session_begin( session_2, url, FALSE, TRUE, TRUE );
     qof_session_swap_data( session_1, session_2 );
     qof_session_save( session_2, NULL );
 
     // Reload the session data
     session_3 = qof_session_new();
-    qof_session_begin( session_3, url, TRUE, FALSE );
+    qof_session_begin( session_3, url, TRUE, FALSE, FALSE );
     qof_session_load( session_3, NULL );
 
     // Compare with the original data

Modified: gnucash/trunk/src/backend/dbi/test/test-dbi.c
===================================================================
--- gnucash/trunk/src/backend/dbi/test/test-dbi.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/dbi/test/test-dbi.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -52,7 +52,7 @@
 
     // Create a session with data
     session_1 = qof_session_new();
-    qof_session_begin( session_1, DBI_TEST_XML_FILENAME, FALSE, FALSE );
+    qof_session_begin( session_1, DBI_TEST_XML_FILENAME, FALSE, FALSE, FALSE );
     qof_session_load( session_1, NULL );
 
     filename = tempnam( "/tmp", "test-sqlite3-" );
@@ -63,7 +63,7 @@
     if ( strlen( TEST_MYSQL_URL ) > 0 )
     {
         session_1 = qof_session_new();
-        qof_session_begin( session_1, DBI_TEST_XML_FILENAME, FALSE, FALSE );
+        qof_session_begin( session_1, DBI_TEST_XML_FILENAME, FALSE, FALSE, FALSE );
         qof_session_load( session_1, NULL );
         test_dbi_store_and_reload( "mysql", session_1, TEST_MYSQL_URL );
     }
@@ -72,7 +72,7 @@
     if ( strlen( TEST_PGSQL_URL ) > 0 )
     {
         session_1 = qof_session_new();
-        qof_session_begin( session_1, DBI_TEST_XML_FILENAME, FALSE, FALSE );
+        qof_session_begin( session_1, DBI_TEST_XML_FILENAME, FALSE, FALSE, FALSE );
         qof_session_load( session_1, NULL );
         test_dbi_store_and_reload( "pgsql", session_1, TEST_PGSQL_URL );
     }

Modified: gnucash/trunk/src/backend/xml/gnc-backend-xml.c
===================================================================
--- gnucash/trunk/src/backend/xml/gnc-backend-xml.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/xml/gnc-backend-xml.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -108,6 +108,8 @@
     GNC_BOOK_XML2_FILE_NO_ENCODING,
 } QofBookFileType;
 
+static gboolean save_may_clobber_data (QofBackend *bend);
+
 /* ================================================================= */
 
 static gboolean
@@ -232,8 +234,8 @@
 
 static void
 xml_session_begin(QofBackend *be_start, QofSession *session,
-                  const char *book_id,
-                  gboolean ignore_lock, gboolean create_if_nonexistent)
+                  const char *book_id, gboolean ignore_lock,
+		  gboolean create, gboolean force)
 {
     FileBackend *be = (FileBackend*) be_start;
 
@@ -248,6 +250,13 @@
         LEAVE("");
         return;
     }
+    if (create && !force && save_may_clobber_data( be_start ) )
+    {
+        qof_backend_set_error (be_start, ERR_BACKEND_STORE_EXISTS);
+        LEAVE("Might clobber, no force");
+        return;
+    }
+
     be->be.fullpath = be->fullpath;
     be->dirname = g_path_get_dirname (be->fullpath);
 
@@ -278,7 +287,7 @@
 
         /* Now check whether we can g_stat the file itself */
         rc = g_stat (be->fullpath, &statbuf);
-        if ((rc != 0) && (!create_if_nonexistent))
+        if ((rc != 0) && (!create))
         {
             /* Error on stat means the file doesn't exist */
             qof_backend_set_error (be_start, ERR_FILEIO_FILE_NOT_FOUND);
@@ -1084,7 +1093,7 @@
 /* ---------------------------------------------------------------------- */
 
 static gboolean
-gnc_xml_be_save_may_clobber_data (QofBackend *bend)
+save_may_clobber_data (QofBackend *bend)
 {
     struct stat statbuf;
     if (!bend->fullpath) return FALSE;
@@ -1178,7 +1187,6 @@
     be->destroy_backend = xml_destroy_backend;
 
     be->load = gnc_xml_be_load_from_file;
-    be->save_may_clobber_data = gnc_xml_be_save_may_clobber_data;
 
     /* The file backend treats accounting periods transactionally. */
     be->begin = xml_begin_edit;

Modified: gnucash/trunk/src/backend/xml/test/test-load-xml2.c
===================================================================
--- gnucash/trunk/src/backend/xml/test/test-load-xml2.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/xml/test/test-load-xml2.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -85,7 +85,7 @@
     remove_locks(filename);
 
     ignore_lock = (safe_strcmp(g_getenv("SRCDIR"), ".") != 0);
-    qof_session_begin(session, filename, ignore_lock, FALSE);
+    qof_session_begin(session, filename, ignore_lock, FALSE, TRUE);
 
     qof_session_load(session, NULL);
     book = qof_session_get_book (session);

Modified: gnucash/trunk/src/backend/xml/test/test-save-in-lang.c
===================================================================
--- gnucash/trunk/src/backend/xml/test/test-save-in-lang.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/backend/xml/test/test-save-in-lang.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -79,7 +79,7 @@
 
         session = qof_session_new();
 
-        qof_session_begin(session, filename, TRUE, FALSE);
+        qof_session_begin(session, filename, TRUE, FALSE, FALSE);
         err = qof_session_pop_error (session);
         if (err)
         {
@@ -100,7 +100,7 @@
 
         new_session = qof_session_new();
 
-        qof_session_begin(new_session, new_file, FALSE, FALSE);
+        qof_session_begin(new_session, new_file, FALSE, FALSE, FALSE);
         err = qof_session_pop_error (new_session);
         if (err)
         {

Modified: gnucash/trunk/src/bin/gnucash-bin.c
===================================================================
--- gnucash/trunk/src/bin/gnucash-bin.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/bin/gnucash-bin.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -627,7 +627,7 @@
     session = gnc_get_current_session();
     if (!session) goto fail;
 
-    qof_session_begin(session, add_quotes_file, FALSE, FALSE);
+    qof_session_begin(session, add_quotes_file, FALSE, FALSE, FALSE);
     if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
 
     qof_session_load(session, NULL);

Modified: gnucash/trunk/src/business/business-core/test/test-customer.c
===================================================================
--- gnucash/trunk/src/business/business-core/test/test-customer.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/business/business-core/test/test-customer.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -65,7 +65,7 @@
 
     session = qof_session_new();
     be = NULL;
-    qof_session_begin(session, FILE_NAME, FALSE, FALSE);
+    qof_session_begin(session, FILE_NAME, FALSE, FALSE, FALSE);
     book = qof_session_get_book(session);
     be = qof_book_get_backend(book);
 

Modified: gnucash/trunk/src/business/business-core/test/test-employee.c
===================================================================
--- gnucash/trunk/src/business/business-core/test/test-employee.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/business/business-core/test/test-employee.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -71,7 +71,7 @@
     GncEmployee *employee;
 
     session = qof_session_new();
-    qof_session_begin(session, FILE_NAME, FALSE, FALSE);
+    qof_session_begin(session, FILE_NAME, FALSE, FALSE, FALSE);
     book = qof_session_get_book(session);
     be = qof_book_get_backend (book);
 

Modified: gnucash/trunk/src/business/business-core/test/test-job.c
===================================================================
--- gnucash/trunk/src/business/business-core/test/test-job.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/business/business-core/test/test-job.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -74,7 +74,7 @@
 
     session = qof_session_new();
     be = NULL;
-    qof_session_begin(session, FILE_NAME, FALSE, FALSE);
+    qof_session_begin(session, FILE_NAME, FALSE, FALSE, FALSE);
     book = qof_session_get_book (session);
     be = qof_book_get_backend(book);
 

Modified: gnucash/trunk/src/business/business-core/test/test-vendor.c
===================================================================
--- gnucash/trunk/src/business/business-core/test/test-vendor.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/business/business-core/test/test-vendor.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -73,7 +73,7 @@
 
     session = qof_session_new();
     be = NULL;
-    qof_session_begin(session, FILE_NAME, FALSE, FALSE);
+    qof_session_begin(session, FILE_NAME, FALSE, FALSE, FALSE);
     book = qof_session_get_book (session);
     be = qof_book_get_backend(book);
 

Modified: gnucash/trunk/src/engine/test/test-recursive.c
===================================================================
--- gnucash/trunk/src/engine/test/test-recursive.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/engine/test/test-recursive.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -1169,7 +1169,7 @@
     if (debug)
     {
         /*         FIXME XML backend can't handle STDOUT
-         *         qof_session_begin(copy, QOF_STDOUT, TRUE, FALSE); */
+         *         qof_session_begin(copy, QOF_STDOUT, TRUE, FALSE, FALSE); */
     }
     /* TODO: implement QOF_TYPE_CHOICE testing. */
     qof_instance_copy_coll_r(copy, grand_coll);
@@ -1214,7 +1214,7 @@
         if (debug)
         {
             /*          FIXME XML backend can't handle STDOUT
-             *          qof_session_begin(original, QOF_STDOUT, TRUE, FALSE); */
+             *          qof_session_begin(original, QOF_STDOUT, TRUE, FALSE, FALSE); */
         }
         create_data(original, (counter % 5));
         test_recursion(original, (counter % 5));

Modified: gnucash/trunk/src/gnome-utils/druid-gnc-xml-import.c
===================================================================
--- gnucash/trunk/src/gnome-utils/druid-gnc-xml-import.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/gnome-utils/druid-gnc-xml-import.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -743,7 +743,7 @@
     gxi_session_destroy (data);
     session = qof_session_new ();
     data->session = session;
-    qof_session_begin (session, data->filename, TRUE, FALSE);
+    qof_session_begin (session, data->filename, TRUE, FALSE, FALSE);
     io_err = qof_session_get_error (session);
     if (io_err != ERR_BACKEND_NO_ERR)
     {

Modified: gnucash/trunk/src/gnome-utils/gnc-file.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-file.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/gnome-utils/gnc-file.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -651,7 +651,7 @@
     /* but first, check to make sure we've got a session going. */
     new_session = qof_session_new ();
 
-    qof_session_begin (new_session, newfile, FALSE, FALSE);
+    qof_session_begin (new_session, newfile, FALSE, FALSE, FALSE);
     io_err = qof_session_get_error (new_session);
     /* if file appears to be locked, ask the user ... */
     if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
@@ -708,7 +708,7 @@
             // reports may take some time
             gnc_show_splash_screen();
             /* user told us to ignore locks. So ignore them. */
-            qof_session_begin (new_session, newfile, TRUE, FALSE);
+            qof_session_begin (new_session, newfile, TRUE, FALSE, FALSE);
         }
         else
         {
@@ -725,8 +725,10 @@
     {
         if (FALSE == show_session_error (io_err, newfile, GNC_FILE_DIALOG_OPEN))
         {
-            /* user told us to create a new database. Do it. */
-            qof_session_begin (new_session, newfile, FALSE, TRUE);
+            /* user told us to create a new database. Do it. We
+	     * shouldn't have to worry about locking or clobbering,
+	     * it's supposed to be new. */
+            qof_session_begin (new_session, newfile, FALSE, TRUE, FALSE);
         }
     }
 
@@ -1019,37 +1021,38 @@
     /* -- this session code is NOT identical in FileOpen and FileSaveAs -- */
 
     new_session = qof_session_new ();
-    qof_session_begin (new_session, newfile, FALSE, TRUE);
+    qof_session_begin (new_session, newfile, FALSE, TRUE, FALSE);
 
     io_err = qof_session_get_error (new_session);
+    /* If the file exists and would be clobbered, ask the user */
+    if (ERR_BACKEND_STORE_EXISTS == io_err) {
+        const char *format = _("The file %s already exists. "
+                               "Are you sure you want to overwrite it?");
 
+ 	const char *name;
+	if ( gnc_uri_is_file_uri ( newfile ) )
+	    name = gnc_uri_get_path ( newfile );
+	else
+	    name = gnc_uri_normalize_uri ( newfile, FALSE );
+       /* if user says cancel, we should break out */
+        if (!gnc_verify_dialog (NULL, FALSE, format, name))
+	{
+            return;
+        }
+	qof_session_begin (new_session, newfile, FALSE, TRUE, TRUE);
+    }
     /* if file appears to be locked, ask the user ... */
     if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
     {
         if (FALSE == show_session_error (io_err, newfile, GNC_FILE_DIALOG_EXPORT))
         {
             /* user told us to ignore locks. So ignore them. */
-            qof_session_begin (new_session, newfile, TRUE, FALSE);
+            qof_session_begin (new_session, newfile, TRUE, FALSE, FALSE);
         }
     }
 
     /* --------------- END CORE SESSION CODE -------------- */
 
-    /* oops ... file already exists ... ask user what to do... */
-    if (qof_session_save_may_clobber_data (new_session))
-    {
-        const char *format = _("The file %s already exists. "
-                               "Are you sure you want to overwrite it?");
-
-        /* if user says cancel, we should break out */
-        if (!gnc_verify_dialog (NULL, FALSE, format, newfile))
-        {
-            return;
-        }
-
-        /* Whoa-ok. Blow away the previous file. */
-    }
-
     /* use the current session to save to file */
     gnc_set_busy_cursor (NULL, TRUE);
     gnc_window_show_progress(_("Exporting file..."), 0.0);
@@ -1233,17 +1236,40 @@
     save_in_progress++;
 
     new_session = qof_session_new ();
-    qof_session_begin (new_session, newfile, FALSE, FALSE);
+    qof_session_begin (new_session, newfile, FALSE, TRUE, FALSE);
 
     io_err = qof_session_get_error (new_session);
 
     /* if file appears to be locked, ask the user ... */
-    if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
+    /* If the file exists and would be clobbered, ask the user */
+    if (ERR_BACKEND_STORE_EXISTS == io_err) {
+        const char *format = _("The file %s already exists. "
+                               "Are you sure you want to overwrite it?");
+
+	const char *name;
+	if ( gnc_uri_is_file_uri ( newfile ) )
+	    name = gnc_uri_get_path ( newfile );
+	else
+	    name = gnc_uri_normalize_uri ( newfile, FALSE );
+ 
+	/* if user says cancel, we should break out */
+        if (!gnc_verify_dialog (NULL, FALSE, format, name ))
+        {
+	    xaccLogDisable();
+            qof_session_destroy (new_session);
+            xaccLogEnable();
+            g_free (newfile);
+            save_in_progress--;
+            return;
+        }
+	qof_session_begin (new_session, newfile, FALSE, TRUE, TRUE);
+    }
+    else if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
     {
         if (FALSE == show_session_error (io_err, newfile, GNC_FILE_DIALOG_SAVE))
         {
             /* user told us to ignore locks. So ignore them. */
-            qof_session_begin (new_session, newfile, TRUE, FALSE);
+            qof_session_begin (new_session, newfile, TRUE, FALSE, FALSE);
         }
     }
 
@@ -1255,7 +1281,7 @@
         if (FALSE == show_session_error (io_err, newfile, GNC_FILE_DIALOG_SAVE))
         {
             /* user told us to create a new database. Do it. */
-            qof_session_begin (new_session, newfile, FALSE, TRUE);
+            qof_session_begin (new_session, newfile, FALSE, TRUE, FALSE);
         }
     }
 
@@ -1275,26 +1301,6 @@
         return;
     }
 
-    /* oops ... file already exists ... ask user what to do... */
-    if (qof_session_save_may_clobber_data (new_session))
-    {
-        const char *format = _("The file %s already exists. "
-                               "Are you sure you want to overwrite it?");
-
-        /* if user says cancel, we should break out */
-        if (!gnc_verify_dialog (NULL, FALSE, format, newfile))
-        {
-            xaccLogDisable();
-            qof_session_destroy (new_session);
-            xaccLogEnable();
-            g_free (newfile);
-            save_in_progress--;
-            return;
-        }
-
-        /* Whoa-ok. Blow away the previous file. */
-    }
-
     /* If the new "file" is a database, attempt to store the password
      * in a keyring. GnuCash itself will not save it.
      */
@@ -1349,8 +1355,8 @@
 	session = NULL;
 
 	xaccReopenLog();
-	gnc_add_history (session);
-	gnc_hook_run(HOOK_BOOK_SAVED, session);
+	gnc_add_history (new_session);
+	gnc_hook_run(HOOK_BOOK_SAVED, new_session);
     }
     /* --------------- END CORE SESSION CODE -------------- */
 

Modified: gnucash/trunk/src/libqof/qof/qofbackend-p.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbackend-p.h	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/libqof/qof/qofbackend-p.h	2010-11-11 06:12:20 UTC (rev 19798)
@@ -298,7 +298,8 @@
                            QofSession *session,
                            const char *book_id,
                            gboolean ignore_lock,
-                           gboolean create_if_nonexistent);
+                           gboolean create,
+			   gboolean force);
     void (*session_end) (QofBackend *);
     void (*destroy_backend) (/*@ only @*/ QofBackend *);
 
@@ -325,20 +326,6 @@
 
     QofBackendProvider *provider;
 
-    /** Detect if the sync operation will overwrite data
-     *
-     * File based backends tend to consider the original file
-     * as 'stale' immediately the data finishes loading. New data
-     * only exists in memory and the data in the file is completely
-     * replaced when qof_session_save is called. e.g. this routine can be
-     * used to detect if a Save As... operation would overwrite a
-     * possibly unrelated file. Not all file backends use this function.
-     *
-     * @return TRUE if the user may need to be warned about possible
-     * data loss, otherwise FALSE.
-     */
-    gboolean (*save_may_clobber_data) (QofBackend *);
-
     QofBackendError last_err;
     char * error_msg;
 

Modified: gnucash/trunk/src/libqof/qof/qofbackend.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbackend.h	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/libqof/qof/qofbackend.h	2010-11-11 06:12:20 UTC (rev 19798)
@@ -62,6 +62,7 @@
     ERR_BACKEND_CANT_CONNECT, /**< bad dbname/login/passwd or network failure */
     ERR_BACKEND_CONN_LOST,    /**< Lost connection to server */
     ERR_BACKEND_LOCKED,       /**< in use by another user (ETXTBSY) */
+    ERR_BACKEND_STORE_EXISTS, /**< File exists, data would be destroyed */
     ERR_BACKEND_READONLY,	    /**< cannot write to file/directory */
     ERR_BACKEND_TOO_NEW,      /**< file/db version newer than what we can read */
     ERR_BACKEND_DATA_CORRUPT, /**< data in db is corrupt */

Modified: gnucash/trunk/src/libqof/qof/qofsession.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofsession.c	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/libqof/qof/qofsession.c	2010-11-11 06:12:20 UTC (rev 19798)
@@ -1098,7 +1098,7 @@
 
 void
 qof_session_begin (QofSession *session, const char * book_id,
-                   gboolean ignore_lock, gboolean create_if_nonexistent)
+                   gboolean ignore_lock, gboolean create, gboolean force)
 {
     gchar **splituri;
 
@@ -1163,7 +1163,7 @@
 
         (session->backend->session_begin)(session->backend, session,
                                           session->book_id, ignore_lock,
-                                          create_if_nonexistent);
+                                          create, force);
         PINFO("Done running session_begin on backend");
         err = qof_backend_get_error(session->backend);
         msg = qof_backend_get_message(session->backend);
@@ -1277,16 +1277,6 @@
 
 /* ====================================================================== */
 
-gboolean
-qof_session_save_may_clobber_data (const QofSession *session)
-{
-    if (!session) return FALSE;
-    if (!session->backend) return FALSE;
-    if (!session->backend->save_may_clobber_data) return FALSE;
-
-    return (*(session->backend->save_may_clobber_data)) (session->backend);
-}
-
 static gboolean
 save_error_handler(QofBackend *be, QofSession *session)
 {
@@ -1373,11 +1363,11 @@
                 {
                     /* Call begin - backend has been changed,
                        so make sure a file can be written,
-                       use ignore_lock and create_if_nonexistent */
+                       use ignore_lock and force create */
                     g_free(session->book_id);
                     session->book_id = NULL;
                     (session->backend->session_begin)(session->backend, session,
-                                                      book_id, TRUE, TRUE);
+                                                      book_id, TRUE, TRUE, TRUE);
                     PINFO("Done running session_begin on changed backend");
                     err = qof_backend_get_error(session->backend);
                     msg = qof_backend_get_message(session->backend);

Modified: gnucash/trunk/src/libqof/qof/qofsession.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofsession.h	2010-11-10 19:59:36 UTC (rev 19797)
+++ gnucash/trunk/src/libqof/qof/qofsession.h	2010-11-11 06:12:20 UTC (rev 19798)
@@ -131,20 +131,25 @@
  *    obeyed.
  *
  *    If the datastore exists, can be reached (e.g over the net),
- *    connected to, opened and read, and a lock can be obtained then
- *    a lock will be obtained.   Note that multi-user datastores
- *    (e.g. the SQL backend) typically will not need to get a global
- *    lock, and thus, the user will not be locked out.  That's the
- *    whole point of 'multi-user'.
+ *    connected to, opened and read, and a lock can be obtained then a
+ *    lock will be obtained.  Note that while multi-user datastores
+ *    (e.g. the SQL backend) typically will have record-level locking
+ *    and therefor should not need to get a global lock, qof works by
+ *    having a local copy of the whole database and can't be trusted
+ *    to handle multiple users writing data, so we lock the database
+ *    anyway.
  *
- *    If the file/database doesn't exist, and the create_if_nonexistent
- *    flag is set to TRUE, then the database is created.
+ *    If qof_session_begin is called with create == TRUE, then it will
+ *    check for the existence of the file or database and return after
+ *    posting a QOF_BACKEND_STORE_EXISTS error if it exists, unless
+ *    force is also set to true.
  *
  *    If an error occurs, it will be pushed onto the session error
  *    stack, and that is where it should be examined.
  */
 void qof_session_begin (QofSession *session, const char * book_id,
-                        gboolean ignore_lock, gboolean create_if_nonexistent);
+                        gboolean ignore_lock, gboolean create,
+			gboolean force);
 
 
 /**
@@ -221,9 +226,6 @@
 /* gboolean qof_session_not_saved(const QofSession *session); <- unimplemented */
 gboolean qof_session_save_in_progress(const QofSession *session);
 
-/** Allows the backend to warn the user if a dataset already exists. */
-gboolean qof_session_save_may_clobber_data (const QofSession *session);
-
 /** The qof_session_save() method will commit all changes that have been
  *    made to the session. For the file backend, this is nothing
  *    more than a write to the file of the current Accounts & etc.



More information about the gnucash-changes mailing list