Skip to content

Commit 0e4e1ce

Browse files
committed
Recover book records if the database is found empty
For some reason sometimes the books database is found empty at startup. This tries to restore the database by recovering the book records. Fixes http://crashes.to/s/d7c34870c8d
1 parent 6e3eec3 commit 0e4e1ce

2 files changed

Lines changed: 79 additions & 2 deletions

File tree

app/src/main/java/org/gnucash/android/db/adapter/BooksDbAdapter.java

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
import android.database.sqlite.SQLiteStatement;
2424
import android.net.Uri;
2525
import android.support.annotation.NonNull;
26+
import android.util.Log;
2627

2728
import org.gnucash.android.R;
2829
import org.gnucash.android.app.GnuCashApplication;
30+
import org.gnucash.android.db.DatabaseHelper;
2931
import org.gnucash.android.db.DatabaseSchema.BookEntry;
3032
import org.gnucash.android.model.Book;
3133
import org.gnucash.android.ui.settings.PreferenceActivity;
@@ -190,11 +192,70 @@ public NoActiveBookFoundException(String message) {
190192
}
191193
}
192194

193-
/** Sets the first book in the database as active. */
195+
/** Tries to fix the books database. */
194196
public void fixBooksDatabase() {
197+
Log.w(LOG_TAG, "Looking for books to set as active...");
198+
if (getRecordsCount() <= 0) {
199+
Log.w(LOG_TAG, "No books found in the database. Recovering books records...");
200+
recoverBookRecords();
201+
}
202+
setFirstBookAsActive();
203+
}
204+
205+
/**
206+
* Restores the records in the book database.
207+
*
208+
* Does so by looking for database files from books.
209+
*/
210+
private void recoverBookRecords() {
211+
for (String dbName : getBookDatabases()) {
212+
Book book = new Book(getRootAccountUID(dbName));
213+
book.setUID(dbName);
214+
book.setDisplayName(generateDefaultBookName());
215+
addRecord(book);
216+
Log.w(LOG_TAG, "Recovered book record: " + book.getUID());
217+
}
218+
}
219+
220+
/**
221+
* Returns the root account UID from the database with name dbName.
222+
*/
223+
private String getRootAccountUID(String dbName) {
224+
Context context = GnuCashApplication.getAppContext();
225+
DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName);
226+
SQLiteDatabase db = databaseHelper.getReadableDatabase();
227+
AccountsDbAdapter accountsDbAdapter = new AccountsDbAdapter(db,
228+
new TransactionsDbAdapter(db, new SplitsDbAdapter(db)));
229+
String uid = accountsDbAdapter.getOrCreateGnuCashRootAccountUID();
230+
db.close();
231+
return uid;
232+
}
233+
234+
/**
235+
* Sets the first book in the database as active.
236+
*/
237+
private void setFirstBookAsActive() {
195238
Book firstBook = getAllRecords().get(0);
196239
firstBook.setActive(true);
197-
BooksDbAdapter.getInstance().addRecord(firstBook);
240+
addRecord(firstBook);
241+
Log.w(LOG_TAG, "Book " + firstBook.getUID() + " set as active.");
242+
}
243+
244+
/**
245+
* Returns a list of database names corresponding to book databases.
246+
*/
247+
private List<String> getBookDatabases() {
248+
List<String> bookDatabases = new ArrayList<>();
249+
for (String database : GnuCashApplication.getAppContext().databaseList()) {
250+
if (isBookDatabase(database)) {
251+
bookDatabases.add(database);
252+
}
253+
}
254+
return bookDatabases;
255+
}
256+
257+
private boolean isBookDatabase(String databaseName) {
258+
return databaseName.matches("[a-z0-9]{32}"); // UID regex
198259
}
199260

200261
public @NonNull List<String> getAllBookUIDs(){

app/src/test/java/org/gnucash/android/test/unit/db/BooksDbAdapterTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,22 @@ public void recoverFromNoActiveBookFound() {
179179
assertThat(mBooksDbAdapter.getActiveBookUID()).isEqualTo(book1.getUID());
180180
}
181181

182+
/**
183+
* Tests the recovery from an empty books database.
184+
*/
185+
@Test
186+
public void recoverFromEmptyDatabase() {
187+
createNewBookWithDefaultAccounts();
188+
mBooksDbAdapter.deleteAllRecords();
189+
assertThat(mBooksDbAdapter.getRecordsCount()).isZero();
190+
191+
mBooksDbAdapter.fixBooksDatabase();
192+
193+
// Should've recovered the one from setUp() plus the one created above
194+
assertThat(mBooksDbAdapter.getRecordsCount()).isEqualTo(2);
195+
mBooksDbAdapter.getActiveBookUID(); // should not throw exception
196+
}
197+
182198
/**
183199
* Creates a new database with default accounts
184200
* @return The book UID for the new database

0 commit comments

Comments
 (0)