[evolution-data-server] Provide database file name in SQLITE_CORRUPT error message
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Provide database file name in SQLITE_CORRUPT error message
- Date: Mon, 24 Jan 2022 13:32:46 +0000 (UTC)
commit 2e18d2f2b64b1c98beeef8ec39d04aab328ebc97
Author: Milan Crha <mcrha redhat com>
Date: Mon Jan 24 14:31:36 2022 +0100
Provide database file name in SQLITE_CORRUPT error message
This will help to locate the affected file.
Related to https://gitlab.gnome.org/GNOME/evolution/-/issues/1780
src/camel/camel-db.c | 53 +++++++++++++++++++++++++++++------------------
src/camel/camel-db.h | 19 +++++++++++++++++
src/libebackend/e-cache.c | 29 +++++++++++++-------------
src/libebackend/e-cache.h | 4 +++-
4 files changed, 69 insertions(+), 36 deletions(-)
---
diff --git a/src/camel/camel-db.c b/src/camel/camel-db.c
index 8656359c7..c1ded8c2b 100644
--- a/src/camel/camel-db.c
+++ b/src/camel/camel-db.c
@@ -43,6 +43,8 @@
/* how long to wait before invoking sync on the file */
#define SYNC_TIMEOUT_SECONDS 5
+G_DEFINE_QUARK (camel-db-error-quark, camel_db_error)
+
static sqlite3_vfs *old_vfs = NULL;
static GThreadPool *sync_pool = NULL;
@@ -540,20 +542,21 @@ camel_db_init (CamelDB *cdb)
/*
* cdb_sql_exec
- * @db:
- * @stmt:
- * @error:
- *
+ * @cdb:
+ * @stmt:
+ * @error:
+ *
* Callers should hold the lock
*/
static gint
-cdb_sql_exec (sqlite3 *db,
+cdb_sql_exec (CamelDB *cdb,
const gchar *stmt,
gint (*callback)(gpointer ,gint,gchar **,gchar **),
gpointer data,
gint *out_sqlite_error_code,
GError **error)
{
+ sqlite3 *db = cdb->priv->db;
gchar *errmsg = NULL;
gint ret = -1, retries = 0;
@@ -580,9 +583,19 @@ cdb_sql_exec (sqlite3 *db,
if (ret != SQLITE_OK) {
d (g_print ("Error in SQL EXEC statement: %s [%s].\n", stmt, errmsg));
- g_set_error (
- error, CAMEL_ERROR,
- CAMEL_ERROR_GENERIC, "%s", errmsg);
+ if (ret == SQLITE_CORRUPT) {
+ if (cdb->priv->filename && *cdb->priv->filename) {
+ g_set_error (error, CAMEL_DB_ERROR,
+ CAMEL_DB_ERROR_CORRUPT, "%s (%s)", errmsg, cdb->priv->filename);
+ } else {
+ g_set_error (error, CAMEL_DB_ERROR,
+ CAMEL_DB_ERROR_CORRUPT, "%s", errmsg);
+ }
+ } else {
+ g_set_error (
+ error, CAMEL_ERROR,
+ CAMEL_ERROR_GENERIC, "%s", errmsg);
+ }
sqlite3_free (errmsg);
errmsg = NULL;
return -1;
@@ -775,7 +788,7 @@ camel_db_command_internal (CamelDB *cdb,
cdb_writer_lock (cdb);
START (stmt);
- ret = cdb_sql_exec (cdb->priv->db, stmt, NULL, NULL, out_sqlite_error_code, error);
+ ret = cdb_sql_exec (cdb, stmt, NULL, NULL, out_sqlite_error_code, error);
END;
cdb_writer_unlock (cdb);
@@ -997,7 +1010,7 @@ camel_db_begin_transaction (CamelDB *cdb,
stmt = cdb_construct_transaction_stmt (cdb, "SAVEPOINT ");
STARTTS (stmt);
- res = cdb_sql_exec (cdb->priv->db, stmt, NULL, NULL, NULL, error);
+ res = cdb_sql_exec (cdb, stmt, NULL, NULL, NULL, error);
g_free (stmt);
return res;
@@ -1025,7 +1038,7 @@ camel_db_end_transaction (CamelDB *cdb,
return -1;
stmt = cdb_construct_transaction_stmt (cdb, "RELEASE SAVEPOINT ");
- ret = cdb_sql_exec (cdb->priv->db, stmt, NULL, NULL, NULL, error);
+ ret = cdb_sql_exec (cdb, stmt, NULL, NULL, NULL, error);
g_free (stmt);
ENDTS;
@@ -1054,7 +1067,7 @@ camel_db_abort_transaction (CamelDB *cdb,
gint ret;
stmt = cdb_construct_transaction_stmt (cdb, "ROLLBACK TO SAVEPOINT ");
- ret = cdb_sql_exec (cdb->priv->db, stmt, NULL, NULL, NULL, error);
+ ret = cdb_sql_exec (cdb, stmt, NULL, NULL, NULL, error);
g_free (stmt);
cdb_writer_unlock (cdb);
@@ -1086,7 +1099,7 @@ camel_db_add_to_transaction (CamelDB *cdb,
g_return_val_if_fail (cdb_is_in_transaction (cdb), -1);
g_return_val_if_fail (query != NULL, -1);
- return (cdb_sql_exec (cdb->priv->db, query, NULL, NULL, NULL, error));
+ return (cdb_sql_exec (cdb, query, NULL, NULL, NULL, error));
}
/**
@@ -1121,7 +1134,7 @@ camel_db_transaction_command (CamelDB *cdb,
while (qry_list) {
query = qry_list->data;
- ret = cdb_sql_exec (cdb->priv->db, query, NULL, NULL, NULL, error);
+ ret = cdb_sql_exec (cdb, query, NULL, NULL, NULL, error);
if (ret)
goto end;
qry_list = g_list_next (qry_list);
@@ -1180,7 +1193,7 @@ camel_db_count_message_info (CamelDB *cdb,
cdb_reader_lock (cdb);
START (query);
- ret = cdb_sql_exec (cdb->priv->db, query, count_cb, count, NULL, error);
+ ret = cdb_sql_exec (cdb, query, count_cb, count, NULL, error);
END;
cdb_reader_unlock (cdb);
@@ -1454,7 +1467,7 @@ camel_db_select (CamelDB *cdb,
cdb_reader_lock (cdb);
START (stmt);
- ret = cdb_sql_exec (cdb->priv->db, stmt, callback, user_data, NULL, error);
+ ret = cdb_sql_exec (cdb, stmt, callback, user_data, NULL, error);
END;
cdb_reader_unlock (cdb);
@@ -2945,12 +2958,12 @@ camel_db_maybe_run_maintenance (CamelDB *cdb,
cdb_writer_lock (cdb);
- if (cdb_sql_exec (cdb->priv->db, "PRAGMA page_count;", get_number_cb, &page_count, NULL,
&local_error) == SQLITE_OK &&
- cdb_sql_exec (cdb->priv->db, "PRAGMA page_size;", get_number_cb, &page_size, NULL, &local_error)
== SQLITE_OK &&
- cdb_sql_exec (cdb->priv->db, "PRAGMA freelist_count;", get_number_cb, &freelist_count, NULL,
&local_error) == SQLITE_OK) {
+ if (cdb_sql_exec (cdb, "PRAGMA page_count;", get_number_cb, &page_count, NULL, &local_error) ==
SQLITE_OK &&
+ cdb_sql_exec (cdb, "PRAGMA page_size;", get_number_cb, &page_size, NULL, &local_error) ==
SQLITE_OK &&
+ cdb_sql_exec (cdb, "PRAGMA freelist_count;", get_number_cb, &freelist_count, NULL, &local_error)
== SQLITE_OK) {
/* Vacuum, if there's more than 5% of the free pages, or when free pages use more than 10MB */
success = !page_count || !freelist_count || (freelist_count * page_size < 1024 * 1024 * 10 &&
freelist_count * 1000 / page_count <= 50) ||
- cdb_sql_exec (cdb->priv->db, "vacuum;", NULL, NULL, NULL, &local_error) == SQLITE_OK;
+ cdb_sql_exec (cdb, "vacuum;", NULL, NULL, NULL, &local_error) == SQLITE_OK;
}
cdb_writer_unlock (cdb);
diff --git a/src/camel/camel-db.h b/src/camel/camel-db.h
index ec42bf516..72f0bb356 100644
--- a/src/camel/camel-db.h
+++ b/src/camel/camel-db.h
@@ -46,8 +46,26 @@
(G_TYPE_INSTANCE_GET_CLASS \
((obj), CAMEL_TYPE_DB, CamelDBClass))
+/**
+ * CAMEL_DB_ERROR:
+ *
+ * Since: 3.44
+ **/
+#define CAMEL_DB_ERROR \
+ (camel_db_error_quark ())
+
G_BEGIN_DECLS
+/**
+ * CamelDBError:
+ * @CAMEL_DB_ERROR_CORRUPT: database is corrupt
+ *
+ * Since: 3.44
+ **/
+typedef enum {
+ CAMEL_DB_ERROR_CORRUPT
+} CamelDBError;
+
typedef struct _CamelDB CamelDB;
typedef struct _CamelDBClass CamelDBClass;
typedef struct _CamelDBPrivate CamelDBPrivate;
@@ -336,6 +354,7 @@ CamelDBKnownColumnNames camel_db_get_column_ident (GHashTable **hash, gint index
**/
typedef gint (* CamelDBSelectCB) (gpointer user_data, gint ncol, gchar **colvalues, gchar **colnames);
+GQuark camel_db_error_quark (void) G_GNUC_CONST;
GType camel_db_get_type (void) G_GNUC_CONST;
CamelDB * camel_db_new (const gchar *filename,
diff --git a/src/libebackend/e-cache.c b/src/libebackend/e-cache.c
index 240040cf5..7710e9ad0 100644
--- a/src/libebackend/e-cache.c
+++ b/src/libebackend/e-cache.c
@@ -504,20 +504,6 @@ e_cache_column_info_free (gpointer info)
}
}
-#define E_CACHE_SET_ERROR_FROM_SQLITE(error, code, message, stmt) \
- G_STMT_START { \
- if (code == SQLITE_CONSTRAINT) { \
- g_set_error_literal (error, E_CACHE_ERROR, E_CACHE_ERROR_CONSTRAINT, message); \
- } else if (code == SQLITE_ABORT || code == SQLITE_INTERRUPT) { \
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Operation cancelled: %s",
message); \
- } else { \
- gchar *valid_utf8 = e_util_utf8_make_valid (stmt); \
- g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_ENGINE, \
- "SQLite error code '%d': %s (statement:%s)", code, message, valid_utf8 ?
valid_utf8 : stmt); \
- g_free (valid_utf8); \
- } \
- } G_STMT_END
-
struct CacheSQLiteExecData {
ECache *cache;
ECacheSelectFunc callback;
@@ -587,8 +573,21 @@ e_cache_sqlite_exec_internal (ECache *cache,
g_rec_mutex_unlock (&cache->priv->lock);
if (ret != SQLITE_OK) {
- E_CACHE_SET_ERROR_FROM_SQLITE (error, ret, errmsg, stmt);
+ if (ret == SQLITE_CONSTRAINT) {
+ g_set_error_literal (error, E_CACHE_ERROR, E_CACHE_ERROR_CONSTRAINT, errmsg);
+ } else if (ret == SQLITE_ABORT || ret == SQLITE_INTERRUPT) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Operation cancelled: %s",
errmsg);
+ } else if (ret == SQLITE_CORRUPT && cache->priv->filename && *cache->priv->filename) {
+ g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_CORRUPT,
+ "%s (%s)", errmsg, cache->priv->filename);
+ } else {
+ gchar *valid_utf8 = e_util_utf8_make_valid (stmt);
+ g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_ENGINE,
+ "SQLite error code '%d': %s (statement:%s)", ret, errmsg, valid_utf8 ?
valid_utf8 : stmt);
+ g_free (valid_utf8);
+ }
sqlite3_free (errmsg);
+
return FALSE;
}
diff --git a/src/libebackend/e-cache.h b/src/libebackend/e-cache.h
index 3fe2e9c9d..b8645f734 100644
--- a/src/libebackend/e-cache.h
+++ b/src/libebackend/e-cache.h
@@ -78,6 +78,7 @@ GQuark e_cache_error_quark (void);
* @E_CACHE_ERROR_UNSUPPORTED_QUERY: A query was not supported.
* @E_CACHE_ERROR_END_OF_LIST: An attempt was made to fetch results past the end of a the list.
* @E_CACHE_ERROR_LOAD: An error occured while loading or creating the database.
+ * @E_CACHE_ERROR_CORRUPT: The database file is corrupt. (Since: 3.44)
*
* Defines the types of possible errors reported by the #ECache
*
@@ -91,7 +92,8 @@ typedef enum {
E_CACHE_ERROR_UNSUPPORTED_FIELD,
E_CACHE_ERROR_UNSUPPORTED_QUERY,
E_CACHE_ERROR_END_OF_LIST,
- E_CACHE_ERROR_LOAD
+ E_CACHE_ERROR_LOAD,
+ E_CACHE_ERROR_CORRUPT
} ECacheError;
typedef struct _ECacheColumnValues ECacheColumnValues;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]