B4J Question jRDC2 Call new "DBCommand" from within JobDone

Declan

Well-Known Member
Licensed User
Longtime User
I am using the following code to get jRDC2 data from MySQL DB.
B4X:
Sub GetNotSent
   Dim req As DBRequestManager = CreateRequest
    Dim cmd As DBCommand = CreateCommand("select_notsent", Array())
   Wait For (req.ExecuteQuery(cmd, 0, Null)) JobDone(j As HttpJob)
   If j.Success Then
       req.HandleJobAsync(j, "req")
       Wait For (req) req_Result(res As DBResult)
       'work with result
        req.PrintTable(res)
        For Each row() As Object In res.Rows
            MyID = row(res.Columns.Get("id"))
            MyCity = row(res.Columns.Get("city"))
            MyProduct1 = row(res.Columns.Get("product1"))
            Log("ID: " & MyID)
            Log("City: " & MyCity)
            Log("Product: " & MyProduct1)
            'NOW Call another Query here for each row and wait before moving to next row()
        Next
   Else
       Log("ERROR: " & j.ErrorMessage)
   End If
    j.Release
End Sub
This works great (Thanks @Erel)
The Log is:
B4X:
Waiting for debugger to connect...
Program started.
Tag: null, Columns: 3, Rows: 3
id    city    product1   
35    Centurion    Life Policy   
36    Centurion    Life Policy   
37    Centurion    Life Policy   
ID: 35
City: Centurion
Product: Life Policy
ID: 36
City: Centurion
Product: Life Policy
ID: 37
City: Centurion
Product: Life Policy
Is it possible to call a new "DBCommand" from within the above code and Wait before moving onto the new row().
For instance:
B4X:
ID: 35
City: Centurion
Product: Life Policy
WAIT AND CALL NEW QUERY AND ACTION NEW QUERY / THEN MOVE TO NEXT ROW() IF ANY

ID: 36
City: Centurion
Product: Life Policy
WAIT AND CALL NEW QUERY AND ACTION NEW QUERY / THEN MOVE TO NEXT ROW() IF ANY

ID: 37
City: Centurion
Product: Life Policy
WAIT AND CALL NEW QUERY AND ACTION NEW QUERY / THEN MOVE TO NEXT ROW() IF ANY
 

Declan

Well-Known Member
Licensed User
Longtime User
Just change the variables names (req2, cmd2, ...)
Do I change the variables in the new "DBCommand" "GetTopic"?
As follows:
B4X:
Sub GetNotSent
   Dim req As DBRequestManager = CreateRequest
    Dim cmd As DBCommand = CreateCommand("get_notsent", Array())
   Wait For (req.ExecuteQuery(cmd, 0, Null)) JobDone(j As HttpJob)
   If j.Success Then
       req.HandleJobAsync(j, "req")
       Wait For (req) req_Result(res As DBResult)
       'work with result
        req.PrintTable(res)
        For Each row() As Object In res.Rows
            MyID = row(res.Columns.Get("id"))
            MyCity = row(res.Columns.Get("city"))
            MyProduct1 = row(res.Columns.Get("product1"))
            Log("ID: " & MyID)
            Log("City: " & MyCity)
            Log("Product: " & MyProduct1)
           
            'NOW Call another Query here for each row and wait before moving to next row()
            GetTopic(MyCity)
        Next
   Else
       Log("ERROR: " & j.ErrorMessage)
   End If
    j.Release
End Sub

Sub GetTopic (city As String)
   Dim req2 As DBRequestManager = CreateRequest
    Dim cmd2 As DBCommand = CreateCommand("get_fbtopic", Array(city))
   Wait For (req2.ExecuteQuery(cmd2, 0, Null)) JobDone(j As HttpJob)
   If j.Success Then
       req2.HandleJobAsync(j, "req2")
       Wait For (req2) req2_Result(res2 As DBResult)
        'work with result
        For Each row() As Object In res2.Rows
            MyTopic = row(res2.Columns.Get("username"))
           
            Log("Topic: " & MyTopic)

        Next
   Else
       Log("ERROR: " & j.ErrorMessage)
   End If
   j.Release
End Sub
In above, I should be calling "GetTopic(MyCity)" after each row in "For Each row() As Object In res.Rows".
But my Log:
B4X:
Waiting for debugger to connect...
Program started.
Tag: null, Columns: 3, Rows: 3
id    city    product1  
35    Centurion    Life Policy  
36    Centurion    Life Policy  
37    Centurion    Life Policy  
ID: 35
City: Centurion
Product: Life Policy
ID: 36
City: Centurion
Product: Life Policy
ID: 37
City: Centurion
Product: Life Policy
Topic: 0822206575
Topic: 0742355566
Topic: 0822206575
Topic: 0742355566
Topic: 0822206575
Topic: 0742355566
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
You're still calling GetTopic(MyCity) asynchronously. You should notice in the IDE that the GetTopic method became a resumable sub due to the fact that you use Wait For statements in the sub. So when you call GetTopic, as soon as a Wait For statement is reached, the GetTopic call returns to the calling method, which in your case is inside a loop. That loop will then gladly execute GetTopic(MyCity) again without waiting for the first GetTopic method to finish (that is how resumable subs work). What you are trying to accomplish needs a couple of modifications:

1) Declare your GetTopic As ResumableSub
B4X:
Sub GetTopic (city As String) As ResumableSub
2) At the end of GetTopic, return a dummy value
B4X:
   j.Release
   Return False ' Just some value. The type is important for the wait for statement though
End Sub
3) Change to call GetTopic(MyCity) to
B4X:
Wait For (GetTopic(MyCity)) Complete (aDummyReturn as Boolean) ' The return value type here must match the return value type of the sub. Boolean in this case

See if this helps.
Note: Watch https://www.b4x.com/etp.html?vimeography_gallery=1&vimeography_video=255570732
Note2: Link found here: https://www.b4x.com/etp.html
 
Upvote 0

Declan

Well-Known Member
Licensed User
Longtime User
@OliverA Many, Many Thanks.
I have changed my code and inserted the above edits.
Code:
B4X:
Sub GetNotSent As ResumableSub
   Dim req As DBRequestManager = CreateRequest
    Dim cmd As DBCommand = CreateCommand("get_notsent", Array())
   Wait For (req.ExecuteQuery(cmd, 0, Null)) JobDone(j As HttpJob)
   If j.Success Then
       req.HandleJobAsync(j, "req")
       Wait For (req) req_Result(res As DBResult)
       'work with result
        req.PrintTable(res)
        For Each row() As Object In res.Rows
            MyID = row(res.Columns.Get("id"))
            MyCity = row(res.Columns.Get("city"))
            MyProduct1 = row(res.Columns.Get("product1"))
            Log("ID: " & MyID)
            Log("City: " & MyCity)
            Log("Product: " & MyProduct1)
            
            'NOW Call another Query here for each row and wait before moving to next row()
            Wait For (GetTopic(MyCity)) Complete (aDummyReturn As Boolean) ' The return value type here must match the return value type of the sub. Boolean in this case
        Next
   Else
       Log("ERROR: " & j.ErrorMessage)
   End If
    j.Release
End Sub

Sub GetTopic (city As String) As ResumableSub
   Dim req2 As DBRequestManager = CreateRequest
    Dim cmd2 As DBCommand = CreateCommand("get_fbtopic", Array(city))
   Wait For (req2.ExecuteQuery(cmd2, 0, Null)) JobDone(j As HttpJob)
   If j.Success Then
       req2.HandleJobAsync(j, "req2")
       Wait For (req2) req2_Result(res2 As DBResult)
        'work with result
        For Each row() As Object In res2.Rows
            MyTopic = row(res2.Columns.Get("username"))
            
            Log("Topic: " & MyTopic)
        Next
   Else
       Log("ERROR: " & j.ErrorMessage)
   End If
    j.Release
    Return False ' Just some value. The type is important for the wait for statement though
End Sub
This is working GREAT
Logs:
B4X:
Waiting for debugger to connect...
Program started.
Tag: null, Columns: 3, Rows: 3
id    city    product1   
35    Centurion    Life Policy   
36    Centurion    Life Policy   
37    Centurion    Life Policy   
ID: 35
City: Centurion
Product: Life Policy
Topic: 0822206575
Topic: 0742355566
ID: 36
City: Centurion
Product: Life Policy
Topic: 0822206575
Topic: 0742355566
ID: 37
City: Centurion
Product: Life Policy
Topic: 0822206575
Topic: 0742355566

Now I am going to attempt to read each row in "For Each row() As Object In res2.Rows" and call another Sub after each row.
The Idea is that I send assemble a String ("MyTopic, MyID, MyCity, MyProduct)".
So, if there are two rows in "For Each row() As Object In res2.Rows", two Strings will be assembled each with a different "MyTopic".
 
Upvote 0
Top