Android Question How to write a function with a return value when there is a ResumableSub call inside

beelze69

Active Member
Licensed User
Longtime User
Hi,

I have a User-Defined Function which returns a String type value..

Inside the function, I am invoking the SQL Query using WAIT

A broad template of the code is shown below:
Code Template:
Public Sub myfunc(pid As Long) As String
    Dim SenderFilter As Object
        dim mySqlQuery as String
        mySQLQuery="SELECT ..."

    SenderFilter=Starter.SQL.ExecQueryAsync("SQL", mySQLQuery,Null)

    Wait For (SenderFilter) SQL_QueryComplete (Success As Boolean, RS As ResultSet)
    If Success Then

        Return(RS.GetString(<Field Name>))
    Else
        Log(LastException)
    End If


End Sub

However, the IDE gives compile error saying that

'Error description: Resumable subs return type must be ResumableSub (or none)'



My Doubt:

How to write a user-defined-function returning a datatype but which is a resumable sub in it...

Thanks
 

agraham

Expert
Licensed User
Longtime User
Change the return type to ResumableSub, return the value as normal with 'Return whatever' and call it using Wait For. You can nest ResumableSubs as follows.
B4X:
Sub Button1_Click
    Wait For (test1) Complete (val As String)
    Log(val)   
End Sub

Private Sub test1 As ResumableSub
    Wait For (test2) Complete (val As String)
    Return val
End Sub

Private Sub test2 As ResumableSub
    Sleep(0)
    Return "Result"
End Sub
See this tutorial
 
Upvote 2

beelze69

Active Member
Licensed User
Longtime User
Change the return type to ResumableSub, return the value as normal with 'Return whatever' and call it using Wait For. You can nest ResumableSubs as follows.
B4X:
Sub Button1_Click
    Wait For (test1) Complete (val As String)
    Log(val)
End Sub

Private Sub test1 As ResumableSub
    Wait For (test2) Complete (val As String)
    Return val
End Sub

Private Sub test2 As ResumableSub
    Sleep(0)
    Return "Result"
End Sub
See this tutorial
Hi Agraham,

Thanks for pointing to that link!

Some more issues:

1) I get the warning 'Not all code paths return a value'

How can that be removed ?


2) I got a CursorIndexOutOfBoundsException error in SQLLITE when I did not use Do While Rs.Nextrow ... Loop ...

This is despite the fact that you know there will be only 1 record match (For example, you want the employee name given an employee id and you know there will be only one record match. You are the database designer and you have ensured primary key validation on the employee id and so you know that there will be only one unique entry for every employee_id) and there was no need to have a loop...

Is this the right way to FIRE EVERY SQLLITE query (even if the database designer knows fully well that there will be only 1 record match) ?


Please clarify..

Thanks..
 
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
1) I get the warning 'Not all code paths return a value'
Not from that code fragment you quoted above. If you mean your original fragment in the first post you have a Sub with a Return statement in a conditional block but not also at the end of the Sub if the conditional isn't met.
B4X:
Public Sub myfunc(pid As Long) As String
    '... some code
    If Success Then
        Return(RS.GetString(<Field Name>))
    Else
        Log(LastException)
        ' Need a Return something here'
    End If
    ' or here
End Sub

Is this the right way to FIRE EVERY SQLLITE query
Looks fine to me but I don't use SQL so I might be wrong
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Inside the function, I am invoking the SQL Query using WAIT
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I got a CursorIndexOutOfBoundsException error in SQLLITE when I did not use Do While Rs.Nextrow ... Loop ...
The "do while" is not important. Calling rs.NextRow is a must.

Correct code:
B4X:
 Wait For (SenderFilter) SQL_QueryComplete (Success As Boolean, RS As ResultSet)
    If Success Then
         rs.NextRow 'must be at least one record
         Dim res As SAtring = RS.GetString(<Field Name>)
         rs.Close '<------
         Return res
    Else
        Log(LastException)
    End If
   Return "" 'or any other value that you like to represent an error
 
Last edited:
Upvote 0

beelze69

Active Member
Licensed User
Longtime User
Not from that code fragment you quoted above. If you mean your original fragment in the first post you have a Sub with a Return statement in a conditional block but not also at the end of the Sub if the conditional isn't met.
B4X:
Public Sub myfunc(pid As Long) As String
    '... some code
    If Success Then
        Return(RS.GetString(<Field Name>))
    Else
        Log(LastException)
        ' Need a Return something here'
    End If
    ' or here
End Sub


Looks fine to me but I don't use SQL so I might be wrong
Thanks Agraham,

I got it ... Erel's example shows the right way to do it.. Thanks for the help...
 
Upvote 0

beelze69

Active Member
Licensed User
Longtime User
The "do while" is not important. Calling rs.NextRow is a must.

Correct code:
B4X:
 Wait For (SenderFilter) SQL_QueryComplete (Success As Boolean, RS As ResultSet)
    If Success Then
         rs.NextRow 'must be at least one record
         Dim res As SAtring = RS.GetString(<Field Name>)
         rs.Close '<------
         Return res
    Else
        Log(LastException)
    End If
   Return "" 'or any other value that you like to represent an error
Thanks Erel for giving this example..
 
Upvote 0
Top