1616
1717package org .gnucash .android .db ;
1818
19- import org .gnucash .android .model .Account .AccountType ;
20-
2119import android .content .ContentValues ;
2220import android .content .Context ;
21+ import android .database .Cursor ;
2322import android .database .sqlite .SQLiteDatabase ;
2423import android .database .sqlite .SQLiteOpenHelper ;
2524import android .util .Log ;
25+ import org .gnucash .android .model .Account .AccountType ;
2626
2727/**
2828 * Helper class for managing the SQLite database.
@@ -46,7 +46,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
4646 * Database version.
4747 * With any change to the database schema, this number must increase
4848 */
49- private static final int DATABASE_VERSION = 5 ;
49+ private static final int DATABASE_VERSION = 6 ;
5050
5151 /**
5252 * Name of accounts table
@@ -70,7 +70,13 @@ public class DatabaseHelper extends SQLiteOpenHelper {
7070 * Currently used by all tables
7171 */
7272 public static final String KEY_NAME = "name" ;
73-
73+
74+ /**
75+ * Key for fully qualified name of the account column
76+ * This name includes the parent hierarchy
77+ */
78+ public static final String KEY_FULL_NAME = "full_name" ;
79+
7480 /**
7581 * Unique Identifier.
7682 */
@@ -170,6 +176,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
170176 + KEY_DEFAULT_TRANSFER_ACCOUNT_UID + " varchar(255), "
171177 + KEY_COLOR_CODE + " varchar(255), "
172178 + KEY_FAVORITE + " tinyint default 0, "
179+ + KEY_FULL_NAME + " varchar(255), "
173180 + "UNIQUE (" + KEY_UID + ")"
174181 + ");" ;
175182
@@ -275,10 +282,109 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
275282
276283 oldVersion = 5 ;
277284 }
285+
286+ if (oldVersion == 5 && newVersion >= 6 ){
287+ Log .i (TAG , "Upgrading database to version 6" );
288+ String addFullAccountNameQuery = " ALTER TABLE " + ACCOUNTS_TABLE_NAME
289+ + " ADD COLUMN " + KEY_FULL_NAME + " varchar(255) " ;
290+ db .execSQL (addFullAccountNameQuery );
291+
292+ //update all existing accounts with their fully qualified name
293+ Cursor cursor = db .query (DatabaseHelper .ACCOUNTS_TABLE_NAME ,
294+ new String []{KEY_ROW_ID , KEY_UID },
295+ null , null , null , null , null );
296+ while (cursor != null && cursor .moveToNext ()){
297+ String uid = cursor .getString (cursor .getColumnIndexOrThrow (KEY_UID ));
298+ String fullName = getFullyQualifiedAccountName (db , uid );
299+
300+ if (fullName == null )
301+ continue ;
302+
303+ ContentValues contentValues = new ContentValues ();
304+ contentValues .put (KEY_FULL_NAME , fullName );
305+
306+ long id = cursor .getLong (cursor .getColumnIndexOrThrow (KEY_ROW_ID ));
307+ db .update (ACCOUNTS_TABLE_NAME , contentValues , KEY_ROW_ID + " = " + id , null );
308+ }
309+
310+ if (cursor != null ) {
311+ cursor .close ();
312+ }
313+
314+ oldVersion = 6 ;
315+ }
278316 }
279317
280318 if (oldVersion != newVersion ) {
281- Log .i (TAG , "Upgrade for the database failed. The Database is currently at version " + oldVersion );
319+ Log .w (TAG , "Upgrade for the database failed. The Database is currently at version " + oldVersion );
282320 }
283321 }
322+
323+ /**
324+ * Performs same functtion as {@link org.gnucash.android.db.AccountsDbAdapter#getFullyQualifiedAccountName(String)}
325+ * <p>This method is only necessary because we cannot open the database again (by instantiating {@link AccountsDbAdapter}
326+ * while it is locked for upgrades. So we reimplement the method here.</p>
327+ * @param db SQLite database
328+ * @param accountUID Unique ID of account whose fully qualified name is to be determined
329+ * @return Fully qualified (colon-sepaated) account name
330+ * @see org.gnucash.android.db.AccountsDbAdapter#getFullyQualifiedAccountName(String)
331+ */
332+ private String getFullyQualifiedAccountName (SQLiteDatabase db , String accountUID ){
333+ //get the parent account UID of the account
334+ Cursor cursor = db .query (DatabaseHelper .ACCOUNTS_TABLE_NAME ,
335+ new String [] {DatabaseHelper .KEY_ROW_ID , DatabaseHelper .KEY_PARENT_ACCOUNT_UID },
336+ DatabaseHelper .KEY_UID + " = ?" ,
337+ new String []{accountUID },
338+ null , null , null , null );
339+
340+ String parentAccountUID = null ;
341+ if (cursor != null && cursor .moveToFirst ()){
342+ parentAccountUID = cursor .getString (cursor .getColumnIndexOrThrow (DatabaseHelper .KEY_PARENT_ACCOUNT_UID ));
343+ cursor .close ();
344+ }
345+
346+ //get the name of the account
347+ cursor = db .query (DatabaseHelper .ACCOUNTS_TABLE_NAME ,
348+ new String []{DatabaseHelper .KEY_ROW_ID , DatabaseHelper .KEY_NAME },
349+ DatabaseHelper .KEY_UID + " = '" + accountUID + "'" ,
350+ null , null , null , null );
351+
352+ String accountName = null ;
353+ if (cursor != null && cursor .moveToFirst ()){
354+ accountName = cursor .getString (cursor .getColumnIndexOrThrow (DatabaseHelper .KEY_NAME ));
355+ cursor .close ();
356+ }
357+
358+ String gnucashRootAccountUID = getGnuCashRootAccountUID (db );
359+ if (parentAccountUID == null || accountName == null
360+ || parentAccountUID .equalsIgnoreCase (gnucashRootAccountUID )){
361+ return accountName ;
362+ }
363+
364+ String parentAccountName = getFullyQualifiedAccountName (db , parentAccountUID );
365+
366+ return parentAccountName + AccountsDbAdapter .ACCOUNT_NAME_SEPARATOR + accountName ;
367+ }
368+
369+ /**
370+ * Returns the GnuCash ROOT account UID.
371+ * <p>In GnuCash desktop account structure, there is a root account (which is not visible in the UI) from which
372+ * other top level accounts derive. GnuCash Android does not have this ROOT account by default unless the account
373+ * structure was imported from GnuCash for desktop. Hence this method also returns <code>null</code> as an
374+ * acceptable result.</p>
375+ * <p><b>Note:</b> NULL is an acceptable response, be sure to check for it</p>
376+ * @return Unique ID of the GnuCash root account.
377+ */
378+ private String getGnuCashRootAccountUID (SQLiteDatabase db ){
379+ String condition = DatabaseHelper .KEY_TYPE + "= '" + AccountType .ROOT .name () + "'" ;
380+ Cursor cursor = db .query (DatabaseHelper .ACCOUNTS_TABLE_NAME ,
381+ null , condition , null , null , null ,
382+ DatabaseHelper .KEY_NAME + " ASC" );
383+ String rootUID = null ;
384+ if (cursor != null && cursor .moveToFirst ()){
385+ rootUID = cursor .getString (DatabaseAdapter .COLUMN_UID );
386+ cursor .close ();
387+ }
388+ return rootUID ;
389+ }
284390}
0 commit comments