Android Question Solved - SQLite - DB rolls back after exiting the program

Bogdan_Popa

Member
Licensed User
Hi all,

I have some issues with inserting and updateing values with the SQL library on SQLite database.
To sum it up, the user Scans a barcode, i check on the database to see if the barcode is present, then i save the information in the database useing:
UpdateOrInsert_Map:
Public Sub UpdateOrInsert_Map(TableName As String, MapToSave As Map, ID As String, IDField As String)
    Try
        If ID = Globals.SQLDataProvider.SQL_GetScalar("SELECT ID FROM " & TableName & " WHERE " & IDField & " = " & ID) Then'UPDATE DB ROW
            Log("Update item")
            Globals.SQLDataProvider.Update_Map(TableName,MapToSave,ID,IDField)
        Else
            Log("Insert item")
            'INSERT ROW INTO DB
            Globals.SQLDataProvider.Insert_Map(TableName,MapToSave)
        End If
    Catch
        Log(LastException)
    End Try
End Sub

depending on the situation , I'll go to one of two:
UpdateMapByID:
public Sub UpdateMapByID(SQL As SQL, TableName As String, Map1 As Map, IDField As String, IDValue As String)
    Dim sb, set As StringBuilder
    SQL.BeginTransaction
    Try
        sb.Initialize
        set.Initialize
        
        Dim listOfValues As List
        listOfValues.Initialize
        
        For Each col As String In Map1.Keys
            Dim value As Object = Map1.Get(col)
            
            If set.ToString <> "" Then
                set.Append (", ")
            End If
            set.Append (EscapeField(col) & " = '" & value & "'" & CRLF)
        Next
        
        sb.Append("UPDATE [" & TableName & "] " & CRLF)
        sb.Append(" SET "  & CRLF)
        sb.Append(set)
        sb.Append("WHERE " & IDField & " = " & IDValue )
        
        SQL.ExecNonQuery(sb)
            
        SQL.TransactionSuccessful
    Catch
        Log(LastException)
        #If B4i OR B4J
            SQL.Rollback
        #End If
    End Try
#If B4A
    SQL.EndTransaction
#End If
End Sub
or
InsertMap:
public Sub InsertMap(SQL As SQL, TableName As String, Map1 As Map)
    Dim sb, columns, values As StringBuilder
    SQL.BeginTransaction
    Try
        sb.Initialize
        columns.Initialize
        values.Initialize
        Dim listOfValues As List
        listOfValues.Initialize
        sb.Append("INSERT INTO [" & TableName & "] (")
        'Dim m As Map = ListOfMaps.Get(i1)
        For Each col As String In Map1.Keys
            Dim value As Object = Map1.Get(col)
            If listOfValues.Size > 0 Then
                columns.Append(", ")
                values.Append(", ")
            End If
            columns.Append(EscapeField(col))
            values.Append("?")
            listOfValues.Add(value)
        Next
        sb.Append(columns.ToString).Append(") VALUES (").Append(values.ToString).Append(");").Append(" COMMIT;")   
        
        SQL.ExecNonQuery2(sb.ToString, listOfValues)

        SQL.TransactionSuccessful
    Catch
        Log(LastException)
        Log("error insert map")
        #If B4i OR B4J
            SQL.Rollback
        #End If
    End Try
#If B4A
    SQL.EndTransaction
    Log("insert map ok")
#End If
End Sub

After inserting a few lines, i'll send the data to the main database, via a web service, all is good there, the web service returns an ID that needs to be updated on the local database.
The id is returned, i check with 2 sql put in "Log()" if the records are on the local databes(on android), and only the one not updated is, i update the value, and check again if the old id is on the database, and it is not, and if the new one is, and it is.
The problems start if I shut down the app and reopen it. All data, except the first the record, from my las scans/inserts are missing.
Also i tryed to transfer the local database via TeamViewer, and ended up with the same result, only the first value i inserted is present and with the id not updated with the value received, value that i have updated and confirmed before the restart of the app.

Thanks,
Bogdan
 

Bogdan_Popa

Member
Licensed User
Hi @aeric , thanks for the response,
the code for SQL_GetScalar:
B4X:
Public Sub SQL_GetScalar(sQuery As String) As String
    Try        'Log (sQuery)
        Dim Result As String
        Result = SQL.ExecQuerySingleResult(sQuery)
        Return Result
    Catch
        Globals.TextLogger.LogError(moduleName,"SQL_GetScalar",LastException.Message,"")
        Return Null
    End Try
End Sub

I should add that i store in the ID, wich is a PK, -Now, until i upload the row and get the new id from the main database via my web service.
 
Upvote 0

Bogdan_Popa

Member
Licensed User
No. I left that part out because I do not need autoincrement, I assing the ID on inserting new data, then update that ID after uploading.
 
Upvote 0

Bogdan_Popa

Member
Licensed User
How can i check if the SQL.TransactionSuccessful really does a commit?
From what i can see, only the first insert is commited. While in debug, i get to that line every time and no error apears.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Why aren't you using DBUtils? The methods in DBUtils are implemented correctly.
 
Upvote 0

Lucas Siqueira

Active Member
Licensed User
Longtime User


is the sub name correct?
the sequence of parameters are also?
 

Attachments

  • erro.PNG
    41.9 KB · Views: 234
Upvote 0

Bogdan_Popa

Member
Licensed User
@Lucas Siqueira, no the problem is not from the sequence of parameters.
I call Globals.SQLDataProvider.Update_Map, the Update_Map calls DBUtils.UpdateMapByID and the swich is made there.
B4X:
' Update one row
Public Sub Update_Map(TableName As String, MapToInsert As Map, IDValue As String, IDField As String)
    Try
        'DBUtils.UpdateMapByID(SQL, TableName, MapToInsert, IDField, IDValue) 'old code that used DBUtils class
        Dim lMap As List
        lMap.Initialize
        lMap.Add(CreateMap(IDField:IDValue))
        DBUtils.UpdateRecord2(SQL, TableName, MapToInsert, lMap)
    Catch
        Globals.TextLogger.LogError(moduleName,"Insert_Map; TableName:" & TableName,LastException.Message,"")
    End Try
End Sub

@Erel , i also think error is somewhere in the code, but everythink woks fine until i close the app, then all the inserts and updates i made on the database are gone.
Since yesterday i've implemented the DBUtils lib. and i'm not using the class anymore.

I had the database in 2 diferent locations: Runtime_Permissions.GetSafeDirDefaultExternal("database") and File.DirInternal.
the table
B4X:
CreateTable: CREATE TABLE IF NOT EXISTS [TR_INVENTORYS] ([ID] INTEGER PRIMARY KEY, [INVENTORYH_ID] INTEGER, [AREA] TEXT, [BARCODE] TEXT, [ITEM_ID] INTEGER, [QTY] REAL, [VALID] TEXT, [Locked] TEXT, [SCANNER] TEXT, [DEFECT] TEXT, [COMMENT] TEXT, [SCAN_DATE] TEXT, [IMPORT_DATE] TEXT, [USER_SCAN] TEXT)

The Values i inserted
B4X:
(MyMap) {ID=-1584007558818, INVENTORYH_ID=2059, AREA=g, BARCODE=672808, ITEM_ID=2361955, QTY=1.0, VALID=true, LOCKED=false, SCANNER=0, SCAN_DATE=2020-03-12 12:05:58.818, USER_SCAN=1, DEFECT=false}
InsertMaps (first query out of 1): INSERT INTO [TR_INVENTORYS] ([ID], [INVENTORYH_ID], [AREA], [BARCODE], [ITEM_ID], [QTY], [VALID], [LOCKED], [SCANNER], [SCAN_DATE], [USER_SCAN], [DEFECT]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
(MyMap) {ID=-1584007559290, INVENTORYH_ID=2059, AREA=g, BARCODE=672808, ITEM_ID=2361955, QTY=1.0, VALID=true, LOCKED=false, SCANNER=0, SCAN_DATE=2020-03-12 12:05:59.290, USER_SCAN=1, DEFECT=false}
InsertMaps (first query out of 1): INSERT INTO [TR_INVENTORYS] ([ID], [INVENTORYH_ID], [AREA], [BARCODE], [ITEM_ID], [QTY], [VALID], [LOCKED], [SCANNER], [SCAN_DATE], [USER_SCAN], [DEFECT]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
(MyMap) {ID=-1584007560007, INVENTORYH_ID=2059, AREA=g, BARCODE=672808, ITEM_ID=2361955, QTY=1.0, VALID=true, LOCKED=false, SCANNER=0, SCAN_DATE=2020-03-12 12:06:00.007, USER_SCAN=1, DEFECT=false}
InsertMaps (first query out of 1): INSERT INTO [TR_INVENTORYS] ([ID], [INVENTORYH_ID], [AREA], [BARCODE], [ITEM_ID], [QTY], [VALID], [LOCKED], [SCANNER], [SCAN_DATE], [USER_SCAN], [DEFECT]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Before sending and after i test to see if the values are still in the table, and they are
LOG:
FIRST 
No of records for -1584007558818:1
ID            -1584007558818
INVENTORYH_ID 2059
AREA        g
BARCODE        672808
ITEM_ID        2361955
QTY            1
VALID        true
LOCKED        false
SCANNER        0
SCAN_DATE    2020-03-12 12:05:58.818
USER_SCAN    1
DEFECT        false
I: 12:07:22:276 | dtgSync_UploadRecords | UploadData | Uploading record -1584007558818 on table TR_INVENTORYS
NewID:14281750
No of records for -1584007558818:0
No of records for 14281750:1
ID            14281750
INVENTORYH_ID 2059
AREA        g
BARCODE        672808
ITEM_ID        2361955
QTY            1
VALID        true
LOCKED        false
SCANNER        0
SCAN_DATE    2020-03-12 12:05:58.818
USER_SCAN    1
DEFECT        false

SECOND 
No of records for -1584007559290:1
ID            -1584007559290
INVENTORYH_ID 2059
AREA        g
BARCODE        672808
ITEM_ID        2361955
QTY            1
VALID        true
LOCKED        false
SCANNER        0
SCAN_DATE    2020-03-12 12:05:59.290
USER_SCAN    1
DEFECT        false
I: 12:08:55:752 | dtgSync_UploadRecords | UploadData | Uploading record -1584007559290 on table TR_INVENTORYS
NewID:14281751
No of records for -1584007559290:0
No of records for 14281751:1
ID            14281751
INVENTORYH_ID 2059
AREA        g
BARCODE        672808
ITEM_ID        2361955
QTY            1
VALID        true
LOCKED        false
SCANNER        0
SCAN_DATE    2020-03-12 12:05:59.290
USER_SCAN    1
DEFECT        false

THIRD
No of records for -1584007560007:1
ID            -1584007560007
INVENTORYH_ID 2059
AREA        g
BARCODE        672808
ITEM_ID        2361955
QTY            1
VALID        true
LOCKED        false
SCANNER        0
SCAN_DATE    2020-03-12 12:06:00.007
USER_SCAN    1
DEFECT        false
I: 12:09:37:942 | dtgSync_UploadRecords | UploadData | Uploading record -1584007560007 on table TR_INVENTORYS
NewID:14281752
No of records for -1584007560007:0
No of records for 14281752:1
ID            14281752
INVENTORYH_ID 2059
AREA        g
BARCODE        672808
ITEM_ID        2361955
QTY            1
VALID        true
LOCKED        false
SCANNER        0
SCAN_DATE    2020-03-12 12:06:00.007
USER_SCAN    1
DEFECT        false

After I close the app, all but the first values are no more, but they were present in the database because i could select and log them inside B4A and send them to my main database.
Does anyone have any idea?
 
Upvote 0

Lucas Siqueira

Active Member
Licensed User
Longtime User


1) how are you starting both of the database application?

2) your database that is in DirInternal and DirDefaultExternal are clean before you start recording the data?

3) do a test, go to the application settings, and access permissions, disable and enable storage permissions again (very important)

I once had a similar problem, it was only the permission that was giving an error, I had permission to read but not to write.
 
Upvote 0

Bogdan_Popa

Member
Licensed User
@Lucas Siqueira, i have only one local database, but i tryd to keep it in a diferent location, thinking that it may be a problem with the DirDefaultExternal.
1. For the database i have 1 standard class: SQLDataProvider,
In starter i Initialize it: Globals.SQLDataProvider.Initialize()
B4X:
Public Sub Initialize 
    Try
        Dim rtp As RuntimePermissions
        dbPath = rtp.GetSafeDirDefaultExternal("database")
        'dbPath = File.DirInternal
        Log("dbPath: " & dbPath)
      
        SQL.Initialize(dbPath,"xGateLocalDB.db",True)
        CheckSyncTables
    Catch
        End Try
End Sub
Then I call the class when i need to interact with the local DB. I use it in the front end and in a service that comunicates with an web service.

2. Yes, It was clean each time I tested the code. No lines in the table.
The database is created and populated initialy by the web service, then the user only cand "write" in specific tables on the database, depending on the activity he is doing.

3. Just done it. No luck
To add some info, maybe someting is not ok here....
Manifest:
AddManifestText(
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="28" />
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true" />
)
'<uses-permission android:name="com.symbol.emdk.permission.EMDK" /> from https://techdocs.zebra.com/emdk-for-android/6-9/tutorial/tutBasicScanningAPI/

SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")

AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)
AddPermission(android.permission.READ_EXTERNAL_STORAGE)
AddPermission(android.permission.ACCESS_COARSE_LOCATION)
AddPermission(android.permission.BLUETOOTH)
AddPermission(android.permission.BLUETOOTH_ADMIN)
AddPermission(android.permission.VIBRATE)
AddPermission(android.permission.INTERNET)
AddPermission(android.permission.WAKE_LOCK)
AddPermission(android.permission.FOREGROUND_SERVICE)
AddPermission(android.permission.READ_PHONE_STATE)

AddManifestText(<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
)
 
Upvote 0

Bogdan_Popa

Member
Licensed User
Hi guys, thanks for all the support you given've me.
I managed to sort out the problem with the database.
As Erel said, the problem was from my code, an ResultSet that wasn't closed after the first insert. This meant that the DB rolled back with no error or message because of this unclosed transaction.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…