oliexdev / openScale

Open-source weight and body metrics tracker, with support for Bluetooth scales
GNU General Public License v3.0
1.66k stars 290 forks source link

Deleting entry, then modifying another causes SQLiteConstraintException #1007

Closed diamant-x closed 4 months ago

diamant-x commented 9 months ago

Describe the bug I've been using for long the app (over 2-3 years of data). Today, I synced several measurements. I deleted one of them because it was the same person measuring twice in 3 minutes timespan so it was not needed. then modified the other entry user to change to the correct one. Attempting this last step fails. Kindly look into this. Thanks1

To Reproduce Steps to reproduce the behavior:

  1. Sync several sessions entries through bluetooth
  2. Delete one of them (eg. among 5, delete the third).
  3. Try to reassign the original fourth entry (a more recent entry compared to the deleted one) to another user.
  4. See error occurs.

Workaround? Seems the erro to be related to two measurements from the same minute (not same second). However, such thing can happen in a scale. I was successful able to modify the minute of the measurement to +1, and could save it, then could modify the user without issues.

Expected behavior User modification should work fine.

Additional context I'm using a xiaomi scale v1. Seems similar to https://github.com/oliexdev/openScale/issues/987 and https://github.com/oliexdev/openScale/issues/695#issuecomment-778761314

Debug log Build version: 2.5.1 Build date: 1981-01-01 01:01:02 Current date: 2023-10-24 12:26:04 Device: OnePlus LE2123 OS version: Android 13 (SDK 33)

Stack trace:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: scaleMeasurements.userId, scaleMeasurements.datetime (code 2067 SQLITE_CONSTRAINT_UNIQUE) at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method) at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:919) at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:756) at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:67) at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:46) at androidx.room.EntityDeletionOrUpdateAdapter.handle(EntityDeletionOrUpdateAdapter.java:70) at com.health.openscale.core.database.ScaleMeasurementDAO_Impl.update(ScaleMeasurementDAO_Impl.java:172) at com.health.openscale.core.OpenScale.updateScaleMeasurement(OpenScale.java:416) at com.health.openscale.gui.measurement.MeasurementEntryFragment.saveScaleData(MeasurementEntryFragment.java:346) at com.health.openscale.gui.measurement.MeasurementEntryFragment.onOptionsItemSelected(MeasurementEntryFragment.java:200) at androidx.fragment.app.Fragment.performOptionsItemSelected(Fragment.java:3259) at androidx.fragment.app.FragmentManager.dispatchOptionsItemSelected(FragmentManager.java:3111) at androidx.fragment.app.Fragment.performOptionsItemSelected(Fragment.java:3263) at androidx.fragment.app.FragmentManager.dispatchOptionsItemSelected(FragmentManager.java:3111) at androidx.fragment.app.FragmentManager$2.onMenuItemSelected(FragmentManager.java:485) at androidx.core.view.MenuHostHelper.onMenuItemSelected(MenuHostHelper.java:107) at androidx.activity.ComponentActivity.onMenuItemSelected(ComponentActivity.java:533) at androidx.fragment.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:265) at androidx.appcompat.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:269) at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:110) at androidx.appcompat.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:66) at androidx.appcompat.widget.Toolbar$1.onMenuItemClick(Toolbar.java:225) at androidx.appcompat.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:781) at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:836) at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:159) at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:987) at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:977) at androidx.appcompat.widget.ActionMenuView.invokeItem(ActionMenuView.java:625) at androidx.appcompat.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:156) at android.view.View.performClick(View.java:7570) at android.view.View.performClickInternal(View.java:7540) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:29710) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:240) at android.os.Looper.loop(Looper.java:351) at android.app.ActivityThread.main(ActivityThread.java:8422) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013)

oliexdev commented 4 months ago

It is not really deleted in openScale if you delete it. It will only marked as deleted as some scales will send you everytime ALL measurements if you sync with the scale. Modify slightly the time then it should work.

diamant-x commented 4 months ago

Any chance to store the time with seconds so it doesn't error with SQLITE_CONSTRAINT_UNIQUE measurements taken in the same minute?