Android Question B4XTable am I using it for the wrong purpose?

jimseng

Active Member
Licensed User
Longtime User
It seems that the B4XTable is more of a visual (view?) than an object to hold database data. I have had some success with it having only just tried it today but I wonder if I am over complicating things.
Here is a generic sql subroutine to populate a table so I can access the data in my app:

generic sql query:
private Sub do_sql(sq As String) As B4XTable
    Dim table As B4XTable
    Dim lst As List
    lst.Initialize
    Dim RS As SD_ResultSet  = MYSQL.ExecQuery(sq)
    Dim colcount As Int = RS.ColumnCount
    Dim colnames(colcount) As String
    table.Initialize("","")
    For i = 0 To colcount -1
        colnames(i) = RS.GetColumnName(i)
        table.AddColumn(colnames(i), table.COLUMN_TYPE_TEXT)
    Next
    Do While RS.NextRow
        Dim row(colcount) As Object
        For i = 0 To colcount -1
            row(i) = RS.getstring(colnames(i))
        Next
        lst.Add(row)
        Loop
        
    RS.Close
    table.SetData(lst)
    table.Tag = lst.size
    Return table
    
End Sub

And I am using it to populate a combobox like this:
B4X:
humantable = do_sql("Select * from Humans")
cmbHuman.cmbBox.Clear
For i = 1 To humantable.tag
      cmbHuman.cmbBox.Add(humantable.Getrow(i).Get("Name"))
Next
I have spent ages trying to work out how to get the number of rows in the table to no avail, hence me cheating by using putting the size of the list that is the table source in the table tag.
Is this a good use of B4Xtables if I am not going to actually show the data table?
Of the many things that confuse me, one is why is B4xTable.Getrow(0) always null, row(1) is the first result form my query. And another is how can I get the number of populated rows? (B4XTable.size returns 0)
Am I misusing B4xTables?
 

emexes

Expert
Licensed User
Longtime User
more of a visual (view?) than an object to hold database data

Correct. Yes, you can store data in a B4XTable, but it's a suboptimal way to do it.

Similar to storing numbers as strings: yes, you can do it, but there are usually better ways to do it (simpler, faster, smaller).

Depending on the size and use of your data, you'd either store it in an Array, a List, a Map, some combination of those (possibly as a Custom Type), or an SQL database file, or an in-memory SQL database (which is what B4XTable uses internally).

If you give an example of the data in humans, then we can analyse the advantages and disadvantages of each storage structure.
 
Last edited:
Upvote 0

aeric

Expert
Licensed User
Longtime User
Welcome to check this example to learn more about using B4XTable.

 
Upvote 0

aeric

Expert
Licensed User
Longtime User
how can I get the number of populated rows? (B4XTable.size returns 0)
1758343880298.png
 
Upvote 0

jimseng

Active Member
Licensed User
Longtime User
If you give an example of the data in humans, then we can analyse the advantages and disadvantages of each storage structure.
This is a very small database and this example of the humans table shows that there are only a few fields in the tables, mostly varchars and only a few tables. (Much of this is for my own education.)

SELECT * FROM `Humans` WHERE 1;​
ID Name Description Gender
2Matthew A handsome fellowBoy
3BellaA very naughty GreyhoundGirl
4PaulNever stops sneezingBoy

So I started off thinking that I would use global lists but on a different thread I posed the question as to whether one could bind data to a combo box like one can in .net and I have ended up down this rabbit hole and now I think maybe I need to climb back out and retreat.
Given that my "do_sql" populates a list, I guess sticking with lists might be more efficient, but I haven't found how to do access the list data .
Much of this is accessing the data via a combobox SelectedIndex, The idea being that the "ID" field in the tables matches the index of the combo box.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
This is a very small database and this example of the humans table shows that there are only a few fields in the tables, mostly varchars and only a few tables. (Much of this is for my own education.)

SELECT * FROM `Humans` WHERE 1;​
ID Name Description Gender
2Matthew A handsome fellowBoy
3BellaA very naughty GreyhoundGirl
4PaulNever stops sneezingBoy

So I started off thinking that I would use global lists but on a different thread I posed the question as to whether one could bind data to a combo box like one can in .net and I have ended up down this rabbit hole and now I think maybe I need to climb back out and retreat.
Given that my "do_sql" populates a list, I guess sticking with lists might be more efficient, but I haven't found how to do access the list data .
Much of this is accessing the data via a combobox SelectedIndex, The idea being that the "ID" field in the tables matches the index of the combo box.
https://www.b4x.com/android/forum/threads/b4x-lmb4xcombobox.116767/#content

???
 
Upvote 0

jimseng

Active Member
Licensed User
Longtime User
@lucasm Thanks. That is sort of it but I think for my purposes I need to store the data in some form of table or list.
One thing I clearly don't understand is lists, and I can't get the data out of it without using
B4X:
table.SetData(lst)
If I could understand that I would probably stick to storing the data in a list.
So for instance. If I put a break over the list, I can see the data results, but no reference to the column names:
1758361050592.png

And yet when a table is populated with the list data (table.setdata(list)) the column names are available for me to pull out. I have a fundamental gap in my understanding of how to use lists and so far I have only be able to retrieve the data by using B4Xtables, which is unlikely to be the most efficient way.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
for my purposes
Obviously, I don't know your purpose.
I'll try to give you some general information, hoping it'll be useful.

B4XTable manages an SQLite database internally. You can run queries against this database - search the site.
The list you see contains an array of objects in each of its items; there are no table field names.

If you want to use List instead of B4XTable, the best way is to create a custom type that represents the record in your table, create a variable of this type, initialize it, fill it with the record's data, and add it to the List. This way, you can also sort the List items by field (the custom type's field name, which should ideally be the same as the table field).

For example:
CLASS_GLOBALS:
Type tHuman(ID As Int, Name As String, Description As String, Gender As String)
Public lstHumans as List
SUB INITIALIZE:
lstHumans.Initialize
B4X:
'Here write code to read records. A "Do While RS.NextRow ..."

ID = RS.GetInt("ID")
Name = RS.GetString("Name")
Description = RS.GetString("Description")
Gender = RS.GetString("Gender")

Dim CurrHuman As tHuman
CurrHuman = CreatetHuman(ID, Name, Description, Gender)

lstHumans.Add(CurrHuman)

'RS.Close

B4X:
Public Sub CreatetHuman (ID As Int, Name As String, Description As String, Gender As String) As tHuman
    Dim t1 As tHuman
    t1.Initialize
    t1.ID = ID
    t1.Name = Name
    t1.Description = Description
    t1.Gender = Gender
    Return t1
End Sub

[
Sorting examples:
lstHumans.SortType("Name", True / False)
lstHumans.SortTypeCaseInsensitive("Gender", True / False)
]
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
If you want to use List instead of B4XTable
An alternative to the List is to use a Map (B4XOrderedMaps are better).
In the Map, you could write the ID as the key and a tHuman variable as the value.



I forgot a note: List with custom types is similar to:
Dim MyList As List Of(<some type>)
VB.Net.
 
Last edited:
Upvote 0

jimseng

Active Member
Licensed User
Longtime User
The list you see contains an array of objects in each of its items; there are no table field names.
Thanks LucasMs. I have used types before so I will go back over that.
So I think the bit I am not understanding is if the B4XTable contains field names after it is populated from the list, is it not possible to extract the data directly from the list, including the field names. If I understand you correctly, elements of the list are objects. Do they not contain the columns as well as the actual data?
So if the B4XTable is populated with
B4X:
B4XTable.SetData(list)
And then one can extract the data by column name:
B4X:
Dim hID As String  = b4XTable.GetRow(1).Get("ID")
Then is it not possible to get the ID directly from the list that was the source of the B4Xtable? The data must be in there somewhere, or have I missed the point (very likely).
In the past I used the old method of json arrays and
B4X:
Dim m as Map = list.get(index)
dim res as string = m.get("ID")
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
the bit I am not understanding
Sorry, I don't have time to read your post right now, but I'll give you a tip that I think is the best I can give for understanding B4XTable.

Get the B4XTable source code (it's a zip file), use it in your project instead of the library, add a few breakpoints, run the project step by step (press F8) and everything will be crystal clear.

;)
 
Upvote 0
Top