Someone on IRC got "E200030: I/O error", which prompted me to write a patch that exposes the sqlite integer error code via the error string (the err->apr_err value remains unchanged, 200030 SVN_ERR_SQLITE_ERROR).
Any objections in principle, or should I go ahead and see how many tests this breaks? Daniel (I would have liked an "E%06d"-like syntax for this, but didn't come up with one) Index: subversion/libsvn_subr/sqlite.c =================================================================== --- subversion/libsvn_subr/sqlite.c (revision 1446314) +++ subversion/libsvn_subr/sqlite.c (working copy) @@ -140,8 +140,9 @@ struct svn_sqlite__value_t int sqlite_err__temp = (x); \ if (sqlite_err__temp != SQLITE_OK) \ return svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \ - NULL, "sqlite: %s", \ - sqlite3_errmsg((db)->db3)); \ + NULL, "sqlite: %s (%d)", \ + sqlite3_errmsg((db)->db3), \ + sqlite_err__temp); \ } while (0) #define SQLITE_ERR_MSG(x, msg) do \ @@ -149,7 +150,8 @@ struct svn_sqlite__value_t int sqlite_err__temp = (x); \ if (sqlite_err__temp != SQLITE_OK) \ return svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \ - NULL, "sqlite: %s", (msg)); \ + NULL, "sqlite: %s (%d)", (msg), \ + sqlite_err__temp); \ } while (0) @@ -171,8 +173,9 @@ exec_sql2(svn_sqlite__db_t *db, const char *sql, i if (sqlite_err != SQLITE_OK && sqlite_err != ignored_err) { svn_error_t *err = svn_error_createf(SQLITE_ERROR_CODE(sqlite_err), NULL, - _("sqlite: %s, executing statement '%s'"), - err_msg, sql); + _("sqlite: %s (%d)," + " executing statement '%s'"), + err_msg, sqlite_err, sql); sqlite3_free(err_msg); return err; } @@ -289,7 +292,8 @@ svn_sqlite__step(svn_boolean_t *got_row, svn_sqlit svn_error_t *err1, *err2; err1 = svn_error_createf(SQLITE_ERROR_CODE(sqlite_result), NULL, - "sqlite: %s", sqlite3_errmsg(stmt->db->db3)); + "sqlite: %s (%d)", + sqlite3_errmsg(stmt->db->db3), sqlite_result); err2 = svn_sqlite__reset(stmt); return svn_error_compose_create(err1, err2); } @@ -739,8 +743,8 @@ init_sqlite(void *baton, apr_pool_t *pool) { int err = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); if (err != SQLITE_OK && err != SQLITE_MISUSE) - return svn_error_create(SQLITE_ERROR_CODE(err), NULL, - _("Could not configure SQLite")); + return svn_error_createf(SQLITE_ERROR_CODE(err), NULL, + _("Could not configure SQLite (%d)"), err); } SQLITE_ERR_MSG(sqlite3_initialize(), _("Could not initialize SQLite")); @@ -793,7 +797,8 @@ internal_open(sqlite3 **db3, const char *path, svn sqlite3_close(*db3); return svn_error_createf(SQLITE_ERROR_CODE(err_code), NULL, - "sqlite: %s: '%s'", msg, path); + "sqlite: %s (%d): '%s'", + msg, err_code, path); } } } @@ -863,7 +868,7 @@ close_apr(void *data) } if (result != SQLITE_OK) - return SQLITE_ERROR_CODE(result); + return SQLITE_ERROR_CODE(result); /* ### lossy */ db->db3 = NULL;