Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DB: drop before import & handle errors #1343

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 51 additions & 33 deletions app/src/main/java/protect/card_locker/DBHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ public class DBHelper extends SQLiteOpenHelper {
public static final int ORIGINAL_DATABASE_VERSION = 1;
public static final int DATABASE_VERSION = 16;

public static class DBException extends Exception {
public DBException(String message) {
super(message);
}

public DBException(String message, Exception rootCause) {
super(message, rootCause);
}
}

public static class LoyaltyCardDbGroups {
public static final String TABLE = "groups";
public static final String ID = "_id";
Expand Down Expand Up @@ -323,6 +333,12 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

public static void clearDatabase(final SQLiteDatabase db) {
db.execSQL("DELETE FROM " + LoyaltyCardDbGroups.TABLE);
db.execSQL("DELETE FROM " + LoyaltyCardDbIds.TABLE);
db.execSQL("DELETE FROM " + LoyaltyCardDbIdsGroups.TABLE);
}

private static ContentValues generateFTSContentValues(final int id, final String store, final String note) {
// FTS on Android is severely limited and can only search for word starting with a certain string
// So for each word, we grab every single substring
Expand Down Expand Up @@ -368,7 +384,7 @@ public static long insertLoyaltyCard(
final SQLiteDatabase database, final String store, final String note, final Date validFrom,
final Date expiry, final BigDecimal balance, final Currency balanceType, final String cardId,
final String barcodeId, final CatimaBarcode barcodeType, final Integer headerColor,
final int starStatus, final Long lastUsed, final int archiveStatus) {
final int starStatus, final Long lastUsed, final int archiveStatus) throws DBException {
database.beginTransaction();

// Card
Expand All @@ -388,6 +404,8 @@ public static long insertLoyaltyCard(
contentValues.put(LoyaltyCardDbIds.ARCHIVE_STATUS, archiveStatus);
long id = database.insert(LoyaltyCardDbIds.TABLE, null, contentValues);

if (id == -1) throw new DBException("Failed to insert card");

// FTS
insertFTS(database, (int) id, store, note);

Expand All @@ -402,7 +420,7 @@ public static long insertLoyaltyCard(
final Date validFrom, final Date expiry, final BigDecimal balance,
final Currency balanceType, final String cardId, final String barcodeId,
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
final Long lastUsed, final int archiveStatus) {
final Long lastUsed, final int archiveStatus) throws DBException {
database.beginTransaction();

// Card
Expand All @@ -421,7 +439,9 @@ public static long insertLoyaltyCard(
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
contentValues.put(LoyaltyCardDbIds.ARCHIVE_STATUS, archiveStatus);
database.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
long rowid = database.insert(LoyaltyCardDbIds.TABLE, null, contentValues);

if (rowid == -1) throw new DBException("Failed to insert card with ID " + id);

// FTS
insertFTS(database, id, store, note);
Expand All @@ -432,12 +452,12 @@ public static long insertLoyaltyCard(
return id;
}

public static boolean updateLoyaltyCard(
public static void updateLoyaltyCard(
SQLiteDatabase database, final int id, final String store, final String note,
final Date validFrom, final Date expiry, final BigDecimal balance,
final Currency balanceType, final String cardId, final String barcodeId,
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
final Long lastUsed, final int archiveStatus) {
final Long lastUsed, final int archiveStatus) throws DBException {
database.beginTransaction();

// Card
Expand Down Expand Up @@ -465,45 +485,45 @@ public static boolean updateLoyaltyCard(
database.setTransactionSuccessful();
database.endTransaction();

return (rowsUpdated == 1);
if (rowsUpdated != 1) throw new DBException("Failed to update card with ID " + id + ": " + rowsUpdated + " rows updated");
}

public static boolean updateLoyaltyCardArchiveStatus(SQLiteDatabase database, final int id, final int archiveStatus) {
public static void updateLoyaltyCardArchiveStatus(SQLiteDatabase database, final int id, final int archiveStatus) throws DBException {
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.ARCHIVE_STATUS, archiveStatus);
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(id));
return (rowsUpdated == 1);
if (rowsUpdated != 1) throw new DBException("Failed to (un)archive card with ID " + id + ": " + rowsUpdated + " rows updated");
}

public static boolean updateLoyaltyCardStarStatus(SQLiteDatabase database, final int id, final int starStatus) {
public static void updateLoyaltyCardStarStatus(SQLiteDatabase database, final int id, final int starStatus) throws DBException {
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(id));
return (rowsUpdated == 1);
if (rowsUpdated != 1) throw new DBException("Failed to (un)star card with ID " + id + ": " + rowsUpdated + " rows updated");
}

public static boolean updateLoyaltyCardLastUsed(SQLiteDatabase database, final int id) {
public static void updateLoyaltyCardLastUsed(SQLiteDatabase database, final int id) throws DBException {
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.LAST_USED, System.currentTimeMillis() / 1000);
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(id));
return (rowsUpdated == 1);
if (rowsUpdated != 1) throw new DBException("Failed to update last used for card with ID " + id + ": " + rowsUpdated + " rows updated");
}

public static boolean updateLoyaltyCardZoomLevel(SQLiteDatabase database, int loyaltyCardId, int zoomLevel) {
public static void updateLoyaltyCardZoomLevel(SQLiteDatabase database, int loyaltyCardId, int zoomLevel) throws DBException {
ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbIds.ZOOM_LEVEL, zoomLevel);
Log.d("updateLoyaltyCardZLevel", "Card Id = " + loyaltyCardId + " Zoom level= " + zoomLevel);
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
whereAttrs(LoyaltyCardDbIds.ID),
withArgs(loyaltyCardId));
Log.d("updateLoyaltyCardZLevel", "Rows changed = " + rowsUpdated);
return (rowsUpdated == 1);
if (rowsUpdated != 1) throw new DBException("Failed to update zoom level for card with ID " + loyaltyCardId + ": " + rowsUpdated + " rows updated");
}

public static boolean updateLoyaltyCardBalance(SQLiteDatabase database, final int id, final BigDecimal newBalance) {
Expand Down Expand Up @@ -569,7 +589,7 @@ public static void setLoyaltyCardGroups(SQLiteDatabase database, final int id, L
}
}

public static boolean deleteLoyaltyCard(SQLiteDatabase database, Context context, final int id) {
public static void deleteLoyaltyCard(SQLiteDatabase database, Context context, final int id) throws DBException {
// Delete card
int rowsDeleted = database.delete(LoyaltyCardDbIds.TABLE,
whereAttrs(LoyaltyCardDbIds.ID),
Expand All @@ -594,7 +614,7 @@ public static boolean deleteLoyaltyCard(SQLiteDatabase database, Context context
}
}

return (rowsDeleted == 1);
if (rowsDeleted != 1) throw new DBException("Failed to delete card with ID " + id + ": " + rowsDeleted + " rows deleted");
}

public static int getArchivedCardsCount(SQLiteDatabase database) {
Expand Down Expand Up @@ -792,19 +812,20 @@ public static List<Integer> getGroupCardIds(SQLiteDatabase database, final Strin
return cardIds;
}

public static long insertGroup(SQLiteDatabase database, final String name) {
if (name.isEmpty()) return -1;
public static void insertGroup(SQLiteDatabase database, final String name) throws DBException {
if (name.isEmpty()) throw new DBException("Failed to insert group with empty name");

ContentValues contentValues = new ContentValues();
contentValues.put(LoyaltyCardDbGroups.ID, name);
contentValues.put(LoyaltyCardDbGroups.ORDER, getGroupCount(database));
return database.insert(LoyaltyCardDbGroups.TABLE, null, contentValues);
}
long rowid = database.insert(LoyaltyCardDbGroups.TABLE, null, contentValues);

public static boolean updateGroup(SQLiteDatabase database, final String groupName, final String newName) {
if (newName.isEmpty()) return false;
if (rowid == -1) throw new DBException("Failed to insert group with name " + name);
}

boolean success = false;
public static void updateGroup(SQLiteDatabase database, final String groupName, final String newName) throws DBException {
if (groupName.isEmpty()) throw new DBException("Failed to update group: empty old name");
if (newName.isEmpty()) throw new DBException("Failed to update group: empty new name");

ContentValues groupContentValues = new ContentValues();
groupContentValues.put(LoyaltyCardDbGroups.ID, newName);
Expand All @@ -826,19 +847,17 @@ public static boolean updateGroup(SQLiteDatabase database, final String groupNam

if (groupsChanged == 1) {
database.setTransactionSuccessful();
success = true;
return;
}
} catch (SQLiteException ignored) {
} finally {
database.endTransaction();
}

return success;
throw new DBException("Failed to update group");
}

public static boolean deleteGroup(SQLiteDatabase database, final String groupName) {
boolean success = false;

public static void deleteGroup(SQLiteDatabase database, final String groupName) throws DBException {
database.beginTransaction();
try {
// Delete group
Expand All @@ -853,16 +872,15 @@ public static boolean deleteGroup(SQLiteDatabase database, final String groupNam

if (groupsDeleted == 1) {
database.setTransactionSuccessful();
success = true;
// Reorder after delete to ensure no bad order IDs
reorderGroups(database, getGroups(database));
return;
}
} finally {
database.endTransaction();
}

// Reorder after delete to ensure no bad order IDs
reorderGroups(database, getGroups(database));

return success;
throw new DBException("Failed to delete group");
}

public static int getGroupCardCount(SQLiteDatabase database, final String groupName) {
Expand Down
16 changes: 14 additions & 2 deletions app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -1437,9 +1437,21 @@ private void doSave() {
// This makes the DBHelper set it to the current date
// So that new and edited card are always on top when sorting by recently used
if (updateLoyaltyCard) {
DBHelper.updateLoyaltyCard(mDatabase, loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, tempLoyaltyCard.starStatus, null, tempLoyaltyCard.archiveStatus);
try {
DBHelper.updateLoyaltyCard(mDatabase, loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, tempLoyaltyCard.starStatus, null, tempLoyaltyCard.archiveStatus);
} catch (DBHelper.DBException e) {
Log.w(TAG, "Could not update loyalty card " + loyaltyCardId);
Toast.makeText(this, "Could not update loyalty card", Toast.LENGTH_LONG).show(); // FIXME
return;
}
} else {
loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, null, 0);
try {
loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, null, 0);
} catch (DBHelper.DBException e) {
Log.w(TAG, "Could not insert loyalty card");
Toast.makeText(this, "Could not insert loyalty card", Toast.LENGTH_LONG).show(); // FIXME
return;
}
}

try {
Expand Down
41 changes: 35 additions & 6 deletions app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,12 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
Log.d(TAG, "Scaling to " + scale);

loyaltyCard.zoomLevel = progress;
DBHelper.updateLoyaltyCardZoomLevel(database, loyaltyCardId, loyaltyCard.zoomLevel);

try {
DBHelper.updateLoyaltyCardZoomLevel(database, loyaltyCardId, loyaltyCard.zoomLevel);
} catch (DBHelper.DBException e) {
Log.d(TAG, "Could not update zoom level for card " + loyaltyCardId);
}

setScalerGuideline(loyaltyCard.zoomLevel);

Expand Down Expand Up @@ -669,7 +674,11 @@ public void onResume() {

setFullscreen(isFullscreen);

DBHelper.updateLoyaltyCardLastUsed(database, loyaltyCard.id);
try {
DBHelper.updateLoyaltyCardLastUsed(database, loyaltyCard.id);
} catch (DBHelper.DBException e) {
Log.w(TAG, "Could not update last used for card " + loyaltyCardId);
}

invalidateOptionsMenu();
}
Expand Down Expand Up @@ -770,15 +779,25 @@ public boolean onOptionsItemSelected(MenuItem item) {

return true;
} else if (id == R.id.action_star_unstar) {
DBHelper.updateLoyaltyCardStarStatus(database, loyaltyCardId, loyaltyCard.starStatus == 0 ? 1 : 0);
try {
DBHelper.updateLoyaltyCardStarStatus(database, loyaltyCardId, loyaltyCard.starStatus == 0 ? 1 : 0);
} catch (DBHelper.DBException e) {
Log.w(TAG, "Could not (un)star card " + loyaltyCardId);
Toast.makeText(LoyaltyCardViewActivity.this, "Failed to (un)star card", Toast.LENGTH_LONG).show(); // FIXME
}

// Re-init loyaltyCard with new data from DB
onResume();
invalidateOptionsMenu();

return true;
} else if (id == R.id.action_archive) {
DBHelper.updateLoyaltyCardArchiveStatus(database, loyaltyCardId, 1);
try {
DBHelper.updateLoyaltyCardArchiveStatus(database, loyaltyCardId, 1);
} catch (DBHelper.DBException e) {
Log.w(TAG, "Could not archive card " + loyaltyCardId);
Toast.makeText(LoyaltyCardViewActivity.this, "Failed to archive card", Toast.LENGTH_LONG).show(); // FIXME
}
Toast.makeText(LoyaltyCardViewActivity.this, R.string.archived, Toast.LENGTH_LONG).show();

// Re-init loyaltyCard with new data from DB
Expand All @@ -787,7 +806,12 @@ public boolean onOptionsItemSelected(MenuItem item) {

return true;
} else if (id == R.id.action_unarchive) {
DBHelper.updateLoyaltyCardArchiveStatus(database, loyaltyCardId, 0);
try {
DBHelper.updateLoyaltyCardArchiveStatus(database, loyaltyCardId, 0);
} catch (DBHelper.DBException e) {
Log.w(TAG, "Could not unarchive card " + loyaltyCardId);
Toast.makeText(LoyaltyCardViewActivity.this, "Failed to unarchive card", Toast.LENGTH_LONG).show(); // FIXME
}
Toast.makeText(LoyaltyCardViewActivity.this, R.string.unarchived, Toast.LENGTH_LONG).show();

// Re-init loyaltyCard with new data from DB
Expand All @@ -802,7 +826,12 @@ public boolean onOptionsItemSelected(MenuItem item) {
builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
Log.e(TAG, "Deleting card: " + loyaltyCardId);

DBHelper.deleteLoyaltyCard(database, LoyaltyCardViewActivity.this, loyaltyCardId);
try {
DBHelper.deleteLoyaltyCard(database, LoyaltyCardViewActivity.this, loyaltyCardId);
} catch (DBHelper.DBException e) {
Log.e(TAG, "Could not delete card " + loyaltyCardId);
Toast.makeText(LoyaltyCardViewActivity.this, "Failed to delete card", Toast.LENGTH_LONG).show(); // FIXME
}

ShortcutHelper.removeShortcut(LoyaltyCardViewActivity.this, loyaltyCardId);

Expand Down
Loading