Bug (Counter of DB)??????

wheretheidivides

Active Member
Licensed User
Longtime User
OK, I have a routine that calls a subroutine. There are 2 global variables (string and integer). I go to sub to see if these exist. I check the combo to see if these both exist on a single record. if not, I go to next record. If this combo exists, then true is returned, if not then false. This is using margets DB class, but the problem is weird.

So here's the thing, it increments the integer on every pass of the loop. I did not ask it to do so, but it does.

Here is code with logs. This is workaround. I had to save off integer (TestTrans = ExpTransactionID) and use TestTrans(If ExpEventID2 = db.GetField("DB1_ExpEventID") AND TestTrans = db.GetField("DB1_ExpTransactionID").

So this code works.

B4X:
Sub LookForEventIDMatch
   Dim xx As String
   Dim yy As String
   xx = db.GetField("DB1_ExpEventID")
   yy = db.GetField("DB1_ExpTransactionID")
'-----------------------
'save all vars cause first record will erase them
   XFromMainVars 'SR
   Dim TestTrans As Int
   TestTrans = ExpTransactionID
'-------------------------
'save pointer
   Dim OldPointer As Int
   OldPointer = db.Record_Pointer   
'------------------------------------------------------
   db.FirstRecord   
   Dim Scount As Int
'------------------------------------------------------
    For Scount = 0 To db.Record_Count -1
      Log("......................")
         Log(Scount)
         xx = db.GetField("DB1_ExpEventID")
         yy = db.GetField("DB1_ExpTransactionID")
         Log ("ExpEventID2=" &  ExpEventID2 & " - DB1_ExpEventID=" & xx)
         Log ("TestTrans=" & TestTrans & " - DB1_ExpTransactionID=" & yy)
        '-----WA1
      If ExpEventID2 = db.GetField("DB1_ExpEventID") AND TestTrans = db.GetField("DB1_ExpTransactionID") Then
         FoundEIDMatch = True
         Exit
        Else
         FoundEIDMatch = False
         db.NextRecord
      End If
      '-----
   Next
Log("......................")
'------------------------
'bring pointer back
   db.Set_Pointer(OldPointer)
   
'--------------------------
'return all vars to original areas
   XToMainVars 'SR

'----------------------------------------------------
End Sub

Now here is log of working code
......................
0
ExpEventID2=hpt - DB1_ExpEventID=hpt
TestTrans=2 - DB1_ExpTransactionID=1
......................
1
ExpEventID2=hpt - DB1_ExpEventID=wpt
TestTrans=2 - DB1_ExpTransactionID=2
......................
2
ExpEventID2=hpt - DB1_ExpEventID=hpt
TestTrans=2 - DB1_ExpTransactionID=3
......................

Ok, so no let's go back and take out the TestTrans and you'll see that the variable ExpTransactionID gets increments 1 count on every pass.

B4X:
Sub LookForEventIDMatch
   Dim xx As String
   Dim yy As String
   xx = db.GetField("DB1_ExpEventID")
   yy = db.GetField("DB1_ExpTransactionID")
'-----------------------
'save all vars cause first record will erase them
   XFromMainVars 'SR
   Dim TestTrans As Int
   'TestTrans = ExpTransactionID
'-------------------------
'save pointer
   Dim OldPointer As Int
   OldPointer = db.Record_Pointer   
'------------------------------------------------------
   db.FirstRecord   
   Dim Scount As Int
'------------------------------------------------------
    For Scount = 0 To db.Record_Count -1
      Log("......................")
         Log(Scount)
         xx = db.GetField("DB1_ExpEventID")
         yy = db.GetField("DB1_ExpTransactionID")
         Log ("ExpEventID2=" &  ExpEventID2 & " - DB1_ExpEventID=" & xx)
         Log ("ExpTransactionID=" & ExpTransactionID & " - DB1_ExpTransactionID=" & yy)
        '-----WA1
      If ExpEventID2 = db.GetField("DB1_ExpEventID") AND ExpTransactionID = db.GetField("DB1_ExpTransactionID") Then
         FoundEIDMatch = True
         Exit
        Else
         FoundEIDMatch = False
         db.NextRecord
      End If
      '-----
   Next
Log("......................")
'------------------------
'bring pointer back
   db.Set_Pointer(OldPointer)
   
'--------------------------
'return all vars to original areas
   XToMainVars 'SR

'----------------------------------------------------
End Sub

and now the log. The only thing that changed was the testtrans variable.
Look at the log lines:
ExpTransactionID=1
ExpTransactionID=2
ExpTransactionID=3
......................
0
ExpEventID2=wsop - DB1_ExpEventID=hpt
ExpTransactionID=1 - DB1_ExpTransactionID=1
......................
1
ExpEventID2=wsop - DB1_ExpEventID=hpt
ExpTransactionID=2 - DB1_ExpTransactionID=2
......................
2
ExpEventID2=wsop - DB1_ExpEventID=hpt
ExpTransactionID=3 - DB1_ExpTransactionID=3
......................

See what I mean? Is it me or is ExpTransactionID not supposed to increment each time??? This has been killing me for a week and I finally found the problem. Now I need someone to tell me it's not me.
 
Last edited:

wheretheidivides

Active Member
Licensed User
Longtime User
Where is the code that updates ExpTransactionID?

Can you upload your project?

This is not supposed to update it. It is just using these 2 variables looking at database records. And that's my point. Nowhere in that subroutine do I tell it to increment the variable. Using the log I prove that there is a bug in margets DB class or in B4A somehow. These are global variables so that may have something to do with it. They are set in 1 subroutine and used in another. I noticed this months ago, but thought it was just me. Usually it is, but looking at the subroutine there is nowehere where I increment that variable. It just increments the counter to go to the next record in the database.

B4X:
sub globals

Dim ExpTransactionID, XExpTransactionID, ExpTransactionIDold, BackupExpTransactionID As Int 

Sub Label6005b_Click
'Event ID
'-----------------------------
Dim BackupExpEventID As String
   BackupExpEventID = ExpEventID
   
ExpEventID2 = ""
   
'-------------------------------------------
   If File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbExpenses.dat") = True AND File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbEventID.dat") = True Then      
      If db.Record_Count < 1 Then
         ToastMessageShow("There are no records in the 'Expense ID' database to LIST.", True)

      Else If db.Record_Count >= 1 Then
         Dim OldPointer2 As Int
            OldPointer2 = db.Record_Pointer
         XFromMainVars 'SR database 1 expense vars
         db.SelectWorkArea(3) '(0-Income, 1-Expenses, 2-String Tracker, 3-Event ID, 4-Cat for Expenses)

         db.ListRecords("Select a new 'Event ID'.", Array As String ("DB3_GlobalEventID")) 'WA3

         ExpEventID2 = db.GetField("DB3_GlobalEventID") 'WA3
         
         db.SelectWorkArea(1) '(0-Income, 1-Expenses, 2-String Tracker, 3-Event ID, 4-Cat for Expenses)
         db.Set_Pointer(OldPointer2)
         
         XToMainVars 'SR x to vars
         PutAllFields_1 'SR vars to DB1
         '###############################
         If ExpEventID2 = "" Then
            
            ToastMessageShow("Nothing selected.", True)
         Else
            '-------------------------
            If File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbExpenses.dat") = True Then
               LookForEventIDMatch 'SR
               PutAllFields_1 'SR
            Else
               FoundEIDMatch = False
            End If
            '----------------------
            If FoundEIDMatch = True Then
                Msgbox("There is already a '" & ExpEventID2 & "-" & ExpTransactionID & "'.", "Invalid IDs")
            Else            
               ExpEventID = ExpEventID2
               Label6005b.Text = ExpEventID
               
               PutAllFields_1 'Put all variables into all fields of 1 records 'SR
               RenamePic6000 'SR
               db.UpdateRecord
               Label6000RecordNum.Text = (db.Record_Pointer +1) & " of " & db.Record_Count
               
               Msgbox("Saved.  'Event ID' was changed." & CRLF & CRLF & "From: " & BackupExpEventID & CRLF & CRLF & "To: " & ExpEventID,"")
            End If
            '-------------------------------------
         End If
         '###############################
      Else
         ToastMessageShow("There are no 'Event ID' records.", True)
      End If
      '---------------------------------------------
   
   Else If File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbExpenses.dat") = True AND File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbEventID.dat") = False Then
      'no database
         ToastMessageShow("There is an 'Expense' database, but you also need an 'Event ID' database as well to change 'Event ID'.", True)
         
   Else If File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbExpenses.dat") = False AND File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbEventID.dat") = True Then
      'no database
         ToastMessageShow("There is an 'Event ID' database, but you also need an 'Expense' database as well to change 'Event ID'.", True)
         
   Else If File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbExpenses.dat") = False AND File.Exists(File.DirRootExternal, "/Saved/PDTK/Databases/dbEventID.dat") = False Then
      'no database
         ToastMessageShow("There is no 'Expense' database and no 'Event ID' database.  You need both databases to change 'Event ID'.", True)
   Else
      'nothing
   End If

'-----------------------------------------
End Sub

Sub LookForEventIDMatch
'-----------------------
'save all vars cause first record will erase them
   XFromMainVars 'SR
   Dim TestTrans As Int
   
   TestTrans = ExpTransactionID
'-------------------------
'save pointer
   Dim OldPointer As Int
   OldPointer = db.Record_Pointer   
'------------------------------------------------------
   db.FirstRecord   
   Dim Scount As Int
'------------------------------------------------------
    For Scount = 0 To db.Record_Count -1

        '-----WA1
      If ExpEventID2 = db.GetField("DB1_ExpEventID") AND TestTrans = db.GetField("DB1_ExpTransactionID") Then
         FoundEIDMatch = True
         Exit
        Else
         FoundEIDMatch = False
         db.NextRecord
      End If
      '-----
   Next
'------------------------
'bring pointer back
   db.Set_Pointer(OldPointer)
   
'--------------------------
'return all vars to original areas
   XToMainVars 'SR

'----------------------------------------------------
End Sub
 

wheretheidivides

Active Member
Licensed User
Longtime User
So here's the code again. The log is inside this loop. The log shouws 3 passes as it's looking for a match. I highly doubt you are going to debug 400 pages of code for me. The last time you asked for me to upload a project was when I mentioned bugs in the abstract designer/script. You never got back to me. As far as this bug goes, it's fairly obvious. Maybe the for/next loop has issues and messes up with global variables. I thought maybe it was the DB, but the more I look at this the more it seems to be B4A. I mean, what else could it be. This code is very straightforward. ExpTransactionID is never asked to change it's value. It is an integer just like Scount. When Scount is incremented, B4A incements ExpTransactionID. Seems like an issue there. I mean, what else could it be?

B4X:
   For Scount = 0 To db.Record_Count -1
        If ExpEventID2 = db.GetField("DB1_ExpEventID") AND ExpTransactionID = db.GetField("DB1_ExpTransactionID") Then
            FoundEIDMatch = True
            Exit
        Else
            FoundEIDMatch = False
            db.NextRecord
        End If
        '-----
    Next
 

wheretheidivides

Active Member
Licensed User
Longtime User
I have done a little more testing and here are my thoughts. It is either 1 of 3 things.

1) my code changes the variable
2) Margets DB class
3) B4A bug

1) Using the log, we know the variable gets changed inside the loop. This rules out my suckey coding.
2) The DB class does not know what the variable name is, so we can rule that out
3) Because this is in a loop that is incrented (for/next) and the affected variable is a global integer, then I think it is the for/next loop also incrementing the variable.


In the next few days I'll see if I can do more tests.
1) I want to see if it does this to a local variable
2) I want to ad logs to see if it changes at the top or bottom of the loop
3) I want to set this up in a new project. Maybe there is some variable leak issue by having a lot of variables or something.

My best guess is the for/next loop. BTW, I don't think it affects variables that are not integers, but need to test that theory.
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
I still don't see any code showing ExpTransactionID getting set. The only place I even see an equals by it is in an IF statement and TestTran getting assigned the value of ExpTransactionID. I never use the class of hers, but it appears to just wrap a cursor. The DB object I see acted on in multiple areas, so I'm guessing it is a Global? When scanning for the value in the For loop you are navigating a cursor that is possibly shared with whatever code you set ExpTransactionID with. Each iteration of the For loop goes to a new Row in the Database, so you may want to look for all your GetFields and see if it is possible that your cursor isn't pointing to a new row.

In my libraries that get passed a cursor I always get the current position and restore it when done scanning just to prevent issues since during scanning I change the current row. Having Global databases causes issues in my code often too since they tend to close themselves. I usually call a function locally to see if it is still active and if not I reconnect to the DB. Then I create local cursors too that I close when done so no possible issues with shared cursors.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…