Skip to content

Commit 67d24c5

Browse files
committed
Prepare for v1.4.0-beta3 release
Fixed: Crash when upgrading database due to invalid SQL query (for the old db version) Fixed: Future transactions not imported Show dialog during database upgrade operations Show richer exception message as toast when importing or exporting
1 parent 454b0f3 commit 67d24c5

14 files changed

+185
-119
lines changed

app/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
1919
package="org.gnucash.android"
20-
android:versionCode="31"
20+
android:versionCode="32"
2121
android:versionName="@string/app_version_name" >
2222

2323
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/>

app/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
1919
<string name="app_name">GnuCash</string>
20-
<string name="app_version_name">1.4.0-beta2</string>
20+
<string name="app_version_name">1.4.0-beta3</string>
2121
<string name="title_add_account">Create Account</string>
2222
<string name="title_edit_account">Edit Account</string>
2323
<string name="info_details">Info</string>

app/src/org/gnucash/android/db/DatabaseHelper.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616

1717
package org.gnucash.android.db;
1818

19+
import android.app.ProgressDialog;
1920
import android.content.ContentValues;
2021
import android.content.Context;
2122
import android.database.Cursor;
2223
import android.database.sqlite.SQLiteDatabase;
2324
import android.database.sqlite.SQLiteOpenHelper;
2425
import android.util.Log;
26+
import android.widget.Toast;
2527
import org.gnucash.android.export.ExportFormat;
2628
import org.gnucash.android.model.Account;
2729
import org.gnucash.android.model.AccountType;
@@ -102,12 +104,18 @@ public class DatabaseHelper extends SQLiteOpenHelper {
102104
+ "UNIQUE (" + SplitEntry.COLUMN_UID + ") "
103105
+ ");";
104106

107+
/**
108+
* Context passed in for database upgrade. Keep reference so as to be able to display UI dialogs
109+
*/
110+
private Context mContext;
111+
105112
/**
106113
* Constructor
107114
* @param context Application context
108115
*/
109116
public DatabaseHelper(Context context){
110117
super(context, DATABASE_NAME, null, DatabaseSchema.DATABASE_VERSION);
118+
mContext = context;
111119
}
112120

113121
@Override
@@ -119,7 +127,9 @@ public void onCreate(SQLiteDatabase db) {
119127
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
120128
Log.i(LOG_TAG, "Upgrading database from version "
121129
+ oldVersion + " to " + newVersion);
122-
130+
131+
ProgressDialog progressDialog = ProgressDialog.show(mContext, "Upgrading database", "Processing...", true);
132+
123133
if (oldVersion < newVersion){
124134
//introducing double entry accounting
125135
Log.i(LOG_TAG, "Upgrading database to version " + newVersion);
@@ -185,6 +195,8 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
185195

186196
if (oldVersion == 5 && newVersion >= 6){
187197
Log.i(LOG_TAG, "Upgrading database to version 6");
198+
progressDialog.setMessage("Upgrading database to version 6");
199+
188200
String addFullAccountNameQuery = " ALTER TABLE " + AccountEntry.TABLE_NAME
189201
+ " ADD COLUMN " + AccountEntry.COLUMN_FULL_NAME + " varchar(255) ";
190202
db.execSQL(addFullAccountNameQuery);
@@ -216,6 +228,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
216228

217229
if (oldVersion == 6 && newVersion >= DatabaseSchema.SPLITS_DB_VERSION){
218230
Log.i(LOG_TAG, "Upgrading database to version 7");
231+
progressDialog.setMessage("Upgrading to version " + SPLITS_DB_VERSION);
219232

220233
//for users who do not have double-entry activated, we create imbalance accounts for their splits
221234
//TODO: Enable when we can hide imbalance accounts from user
@@ -225,17 +238,27 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
225238
// accountsDbAdapter.getOrCreateImbalanceAccountUID(currency);
226239
// }
227240

228-
String filepath = MigrationHelper.exportDatabase(db, ExportFormat.GNC_XML);
241+
progressDialog.setMessage("Backing up database");
242+
try {
243+
String filepath = MigrationHelper.exportDatabase(db, ExportFormat.GNC_XML);
229244

230-
dropAllDatabaseTables(db);
231-
createDatabaseTables(db);
245+
progressDialog.setMessage("Upgrading database schema");
232246

233-
MigrationHelper.importGnucashXML(db, filepath);
247+
dropAllDatabaseTables(db);
248+
createDatabaseTables(db);
234249

250+
progressDialog.setMessage("Restoring database");
251+
252+
MigrationHelper.importGnucashXML(db, filepath);
253+
} catch (Exception e){
254+
Toast.makeText(mContext, "Error upgrading database.\n" + e.getMessage(), Toast.LENGTH_LONG).show();
255+
throw new RuntimeException(e);
256+
}
235257
oldVersion = DatabaseSchema.SPLITS_DB_VERSION;
236258
}
237259
}
238260

261+
progressDialog.dismiss();
239262
if (oldVersion != newVersion) {
240263
Log.w(LOG_TAG, "Upgrade for the database failed. The Database is currently at version " + oldVersion);
241264
}

app/src/org/gnucash/android/db/MigrationHelper.java

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,15 @@
2020
import android.database.sqlite.SQLiteDatabase;
2121
import android.os.Environment;
2222
import android.util.Log;
23-
import org.gnucash.android.app.GnuCashApplication;
2423
import org.gnucash.android.export.ExportFormat;
2524
import org.gnucash.android.export.ExportParams;
2625
import org.gnucash.android.export.Exporter;
2726
import org.gnucash.android.export.qif.QifExporter;
2827
import org.gnucash.android.export.xml.GncXmlExporter;
29-
import org.gnucash.android.importer.GncXmlHandler;
30-
import org.gnucash.android.importer.GncXmlImportTask;
28+
import org.gnucash.android.importer.GncXmlImporter;
3129
import org.gnucash.android.model.AccountType;
3230

3331
import java.io.*;
34-
import java.util.ArrayList;
35-
import java.util.Currency;
36-
import java.util.List;
3732

3833
import static org.gnucash.android.db.DatabaseSchema.AccountEntry;
3934

@@ -117,7 +112,7 @@ private static String getGnuCashRootAccountUID(SQLiteDatabase db){
117112
* Exports the database to a GnuCash XML file and returns the path to the file
118113
* @return String with exported GnuCash XML
119114
*/
120-
static String exportDatabase(SQLiteDatabase db, ExportFormat format) {
115+
static String exportDatabase(SQLiteDatabase db, ExportFormat format) throws IOException {
121116
Log.i(LOG_TAG, "Exporting database to GnuCash XML");
122117
ExportParams exportParams = new ExportParams(format);
123118
exportParams.setExportAllTransactions(true);
@@ -128,6 +123,7 @@ static String exportDatabase(SQLiteDatabase db, ExportFormat format) {
128123
exportParams.setTargetFilepath(Environment.getExternalStorageDirectory()
129124
+ "/gnucash/" + Exporter.buildExportFilename(format));
130125

126+
//we do not use the ExporterAsyncTask here because we want to use an already open db
131127
Exporter exporter = null;
132128
switch (format){
133129
case QIF:
@@ -137,33 +133,23 @@ static String exportDatabase(SQLiteDatabase db, ExportFormat format) {
137133
default:
138134
exporter = new GncXmlExporter(exportParams, db);
139135
}
140-
try {
141-
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
142-
new FileOutputStream(exportParams.getTargetFilepath()), "UTF-8"));
143-
writer.write(exporter.generateExport());
144-
145-
writer.flush();
146-
writer.close();
147-
} catch (IOException e) {
148-
e.printStackTrace();
149-
throw new RuntimeException("Error backing up database for upgrade", e);
150-
}
151136

137+
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
138+
new FileOutputStream(exportParams.getTargetFilepath()), "UTF-8"));
139+
writer.write(exporter.generateExport());
140+
141+
writer.flush();
142+
writer.close();
152143
return exportParams.getTargetFilepath();
153144
}
154145

155146
/**
156147
* Imports GnuCash XML into the database from file
157148
* @param filepath Path to GnuCash XML file
158149
*/
159-
static void importGnucashXML(SQLiteDatabase db, String filepath) {
150+
static void importGnucashXML(SQLiteDatabase db, String filepath) throws Exception {
160151
Log.i(LOG_TAG, "Importing GnuCash XML");
161-
try {
162-
FileInputStream inputStream = new FileInputStream(filepath);
163-
GncXmlHandler.parse(db, inputStream);
164-
} catch (FileNotFoundException e) {
165-
e.printStackTrace();
166-
throw new RuntimeException(e);
167-
}
152+
FileInputStream inputStream = new FileInputStream(filepath);
153+
GncXmlImporter.parse(db, inputStream);
168154
}
169155
}

app/src/org/gnucash/android/db/TransactionsDbAdapter.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,21 +151,33 @@ public Transaction getTransaction(long rowId){
151151
* i.e <code>accountUID</code> is double entry account UID
152152
* @param accountUID UID of the account whose transactions are to be retrieved
153153
* @return Cursor holding set of transactions for particular account
154+
* @throws java.lang.IllegalArgumentException if the accountUID is null
154155
*/
155156
public Cursor fetchAllTransactionsForAccount(String accountUID){
156-
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
157-
queryBuilder.setTables(TransactionEntry.TABLE_NAME
158-
+ " INNER JOIN " + SplitEntry.TABLE_NAME + " ON "
159-
+ TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + " = "
160-
+ SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_TRANSACTION_UID);
161-
queryBuilder.setDistinct(true);
162-
String[] projectionIn = new String[]{TransactionEntry.TABLE_NAME + ".*"};
163-
String selection = SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_ACCOUNT_UID + " = ?"
164-
+ " AND " + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_RECURRENCE_PERIOD + " = 0";
165-
String[] selectionArgs = new String[]{accountUID};
166-
String sortOrder = TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_TIMESTAMP + " DESC";
167-
168-
return queryBuilder.query(mDb, projectionIn, selection, selectionArgs, null, null, sortOrder);
157+
if (accountUID == null)
158+
throw new IllegalArgumentException("Unique ID of the account cannot be null");
159+
160+
if (mDb.getVersion() < DatabaseSchema.SPLITS_DB_VERSION){ //legacy from previous database format
161+
return mDb.query(TransactionEntry.TABLE_NAME, null,
162+
"((" + SplitEntry.COLUMN_ACCOUNT_UID + " = '" + accountUID + "') "
163+
+ "OR (" + DatabaseHelper.KEY_DOUBLE_ENTRY_ACCOUNT_UID + " = '" + accountUID + "' ))"
164+
+ " AND " + TransactionEntry.COLUMN_RECURRENCE_PERIOD + " = 0",
165+
null, null, null, TransactionEntry.COLUMN_TIMESTAMP + " DESC");
166+
} else {
167+
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
168+
queryBuilder.setTables(TransactionEntry.TABLE_NAME
169+
+ " INNER JOIN " + SplitEntry.TABLE_NAME + " ON "
170+
+ TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + " = "
171+
+ SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_TRANSACTION_UID);
172+
queryBuilder.setDistinct(true);
173+
String[] projectionIn = new String[]{TransactionEntry.TABLE_NAME + ".*"};
174+
String selection = SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_ACCOUNT_UID + " = ?"
175+
+ " AND " + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_RECURRENCE_PERIOD + " = 0";
176+
String[] selectionArgs = new String[]{accountUID};
177+
String sortOrder = TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_TIMESTAMP + " DESC";
178+
179+
return queryBuilder.query(mDb, projectionIn, selection, selectionArgs, null, null, sortOrder);
180+
}
169181
}
170182

171183
/**

app/src/org/gnucash/android/export/ExportDialogFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void onClick(View v) {
9595
dismiss();
9696

9797
Log.i(TAG, "Commencing async export of transactions");
98-
new ExporterTask(getActivity()).execute(exportParameters);
98+
new ExporterAsyncTask(getActivity()).execute(exportParameters);
9999
}
100100

101101
}

app/src/org/gnucash/android/export/ExportParams.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* The parameters are determined by the user in the export dialog and are then transmitted to the asynchronous task which
2222
* actually performs the export.
2323
* @see org.gnucash.android.export.ExportDialogFragment
24-
* @see org.gnucash.android.export.ExporterTask
24+
* @see ExporterAsyncTask
2525
*
2626
* @author Ngewi Fet <[email protected]>
2727
*/

app/src/org/gnucash/android/export/ExporterTask.java renamed to app/src/org/gnucash/android/export/ExporterAsyncTask.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
*
4545
* @author Ngewi Fet <[email protected]>
4646
*/
47-
public class ExporterTask extends AsyncTask<ExportParams, Void, Boolean> {
47+
public class ExporterAsyncTask extends AsyncTask<ExportParams, Void, Boolean> {
4848
/**
4949
* App context
5050
*/
@@ -55,14 +55,14 @@ public class ExporterTask extends AsyncTask<ExportParams, Void, Boolean> {
5555
/**
5656
* Log tag
5757
*/
58-
public static final String TAG = "ExporterTask";
58+
public static final String TAG = "ExporterAsyncTask";
5959

6060
/**
6161
* Export parameters
6262
*/
6363
private ExportParams mExportParams;
6464

65-
public ExporterTask(Context context){
65+
public ExporterAsyncTask(Context context){
6666
this.mContext = context;
6767
}
6868

@@ -111,7 +111,8 @@ protected Boolean doInBackground(ExportParams... params) {
111111
e.printStackTrace();
112112
Log.e(TAG, e.getMessage());
113113
Toast.makeText(mContext, R.string.toast_export_error,
114-
Toast.LENGTH_LONG).show();
114+
Toast.LENGTH_SHORT).show();
115+
Toast.makeText(mContext, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
115116
return false;
116117
}
117118
return true;

0 commit comments

Comments
 (0)