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.



git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@19798 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
John Ralls 2010-11-11 06:12:20 +00:00
parent 76da42522e
commit b334c7ffb2
19 changed files with 148 additions and 136 deletions

View File

@ -122,6 +122,7 @@ static GSList* conn_get_table_list_pgsql( dbi_conn conn, const gchar* dbname );
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 @@ sqlite3_error_fn( dbi_conn conn, /*@ unused @*/ void* user_data )
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 @@ gnc_dbi_sqlite3_session_begin( QofBackend *qbe, QofSession *session,
/* 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 @@ gnc_dbi_unlock( QofBackend *qbe )
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_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
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 @@ gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
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 @@ gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
}
// 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 @@ pgsql_error_fn( dbi_conn conn, void* user_data )
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 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
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 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
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 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
}
// 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 @@ gnc_dbi_load( QofBackend* qbe, /*@ dependent @*/ QofBook *book, QofBackendLoadTy
/* ================================================================= */
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 @@ init_sql_backend( GncDbiBackend* dbi_be )
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 @@ init_sql_backend( GncDbiBackend* dbi_be )
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;

View File

@ -198,13 +198,13 @@ test_dbi_business_store_and_reload( const gchar* driver, QofSession* session_1,
// 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

View File

@ -151,13 +151,13 @@ test_dbi_store_and_reload( const gchar* driver, QofSession* session_1, const gch
// 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

View File

@ -52,7 +52,7 @@ int main (int argc, char ** argv)
// 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 @@ int main (int argc, char ** argv)
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 @@ int main (int argc, char ** argv)
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 );
}

View File

@ -108,6 +108,8 @@ typedef enum
GNC_BOOK_XML2_FILE_NO_ENCODING,
} QofBookFileType;
static gboolean save_may_clobber_data (QofBackend *bend);
/* ================================================================= */
static gboolean
@ -232,8 +234,8 @@ gnc_xml_be_get_file_lock (FileBackend *be)
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 @@ xml_session_begin(QofBackend *be_start, QofSession *session,
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 @@ xml_session_begin(QofBackend *be_start, QofSession *session,
/* 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 @@ gnc_xml_be_load_from_file (QofBackend *bend, QofBook *book, QofBackendLoadType l
/* ---------------------------------------------------------------------- */
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 @@ gnc_backend_new(void)
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;

View File

@ -85,7 +85,7 @@ test_load_file(const char *filename)
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);

View File

@ -79,7 +79,7 @@ test_file(const char *filename)
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 @@ test_file(const char *filename)
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)
{

View File

@ -627,7 +627,7 @@ inner_main_add_price_quotes(void *closure, int argc, char **argv)
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);

View File

@ -65,7 +65,7 @@ test_customer (void)
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);

View File

@ -71,7 +71,7 @@ test_employee (void)
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);

View File

@ -74,7 +74,7 @@ test_job (void)
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);

View File

@ -73,7 +73,7 @@ test_vendor (void)
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);

View File

@ -1169,7 +1169,7 @@ test_recursion (QofSession *original, guint counter)
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 @@ main (int argc, const char *argv[])
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));

View File

@ -743,7 +743,7 @@ gxi_parse_file (GncXmlImportData *data)
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)
{

View File

@ -651,7 +651,7 @@ gnc_post_file_open (const char * filename)
/* 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 @@ gnc_post_file_open (const char * filename)
// 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 @@ gnc_post_file_open (const char * filename)
{
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 @@ gnc_file_do_export(const char * filename)
/* -- 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 @@ gnc_file_do_save_as (const char* filename)
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 @@ gnc_file_do_save_as (const char* filename)
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 @@ gnc_file_do_save_as (const char* filename)
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 @@ gnc_file_do_save_as (const char* filename)
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 -------------- */

View File

@ -298,7 +298,8 @@ struct QofBackend_s
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 @@ struct QofBackend_s
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;

View File

@ -62,6 +62,7 @@ typedef enum
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 */

View File

@ -1098,7 +1098,7 @@ qof_session_destroy_backend (QofSession *session)
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 @@ qof_session_begin (QofSession *session, const char * book_id,
(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 @@ qof_session_load (QofSession *session,
/* ====================================================================== */
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 @@ qof_session_save (QofSession *session,
{
/* 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);

View File

@ -131,20 +131,25 @@ void qof_session_swap_data (QofSession *session_1, QofSession *session_2);
* 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 @@ const char * qof_session_get_url (const QofSession *session);
/* 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.