-
Notifications
You must be signed in to change notification settings - Fork 0
Language Reference Collections
**PAGE UNDER CONSTRUCTION **
In FBASIC, collections are fundamental data structures used to manage lists of values and result sets from data sources. While traditional single variables hold one value, collections allow a program to store and iterate over multiple related items efficiently. The two primary collection types referenced in the language are SDATA (or Static) and CURSOR (or Fetchable).
FBASIC is an extensible computer programming language whose core interpreter provides fundamental structures common to all modern languages, facilitating the easy, statement-by-statement translation to other programming environments. Within FBASIC, data management is distinguished by two primary collection types: static collections, which are typically one-dimensional arrays of data stored directly and contiguously in memory for fast access, and fetchable collections, which are designed for sequential, row-by-row access and do not support direct, indexed lookup of individual rows.
| Characteristic | Static | Fetchable |
|---|---|---|
| In memory | Yes | No |
| Access row by index | Yes | No |
| Access row by fetch | Yes | Yes |
| Need reset | Yes | Yes |
| Foreach loop | Yes | Yes |
| Known number of items | Yes | No |
| Multi field support | No | Yes |
| Dynamic field naming | No | Yes |
| Need data source | No | Yes |
| Data from the program (via SDATA) | Yes | No |
| Statement SSET | Yes | No |
An SDATA collection is a dynamic, in-memory structure primarily designed to store and manage lists of primitive values (like strings or numbers) generated or manipulated within the FBASIC program's execution flow. It serves a similar role to an array or list in other languages, allowing for flexible data aggregation.
The SDATA collection is created and populated using the SDATA statement.
| Statement / Element | Purpose | Example |
|---|---|---|
| SDATA collection value | Appends a single value to the end of the collection. | sdata names "John" |
| SSET collection index identifier | Change the item that the index points to the value or variable | SSET names 1 "Jim" |
| SCNT("collection") | Function returns the total number of elements (count) currently stored in the SDATA collection. | print SCNT("names") |
| SCI("collection", index) | Function returns the value of the item at the specified 1-based index in the SDATA collection. | print SCI("names",1) |
| [collection.Item] | An identifier with a special syntax used to reference the current fetched item's value. Need FETCH or FOREACH loop before use it. | [names.Item] |
| RESET collection | Reset a collection and move the underlyning cursor to the first item | RESET names |
| FOREACH collection | Move the underlyning cursor to the next row of a collection. | FOREACH names ..... ENDFOREACH |
Special attention:
- Function names for collections use capital (uppercase) letters (e.g., SCNT), which contradicts the convention for most other functions in FBASIC. Remember that statements are case-insensitive, but functions are case-sensitive.
- The collection name passed to these functions is treated as a string value or variable, not an identifier. Therefore, a literal collection name must be enclosed in quotes.
The following example demonstrates initializing an SDATA collection and populating it within a loop:
inputLoop:
input nameInput
If nameInput \= "." Then
GoTo endInput
EndIf
REM Store the name into the SDATA collection
sdata names \[nameInput\]
GoTo inputLoop
endInput:The standard way to access all items in an SDATA collection is using the FOREACH...ENDFOREACH loop structure.
| Statement | Purpose |
|---|---|
| FOREACH collection | Move the underlyning cursor to the next row of a collection. |
| [collection.Field_Name] | An identifier with a special syntax used inside a FOREACH loop to reference the current item's value. |
| ENDFOREACH collection | Closes the loop structure. |
Example of Iteration:
Foreach customers
print \[names.FirstName\]
EndForeach customersFBASIC provides dedicated statements and functions for advanced management of SDATA collections, granting array-like control.
| Statement/Function | Syntax | Type | Description |
|---|---|---|---|
| SSET | SSET collectionName, index, value | Statement | Sets/updates the value of an item at a specific, 1-based index in the SDATA collection. |
| SCNT() | SCNT(collectionName) | Function | Returns the total number of elements (count) currently stored in the SDATA collection. |
| SCI() | SCI(collectionName, index) | Function | Returns the value of the item at the specified 1-based index in the SDATA collection. |
Example using SSET and SCNT():
sdata scores ""
sdata scores \[95\] REM stores 95 at index 1
sdata scores \[88\] REM stores 88 at index 2
let total \= SCNT(scores)
print "Total items: " \+ total REM Prints 2
SSET scores, 2, 90 REM Change value at index 2 from 88 to 90
let newScore \= SCI(scores, 2\)
print "New score at index 2: " \+ newScore REM Prints 90The CURSOR collection is a special type of collection that acts as a wrapper for external data sources, specifically SQL results. It is designed for efficient, record-by-record retrieval of data without loading the entire dataset into memory at once.
The CURSOR collection is created using the CURSOR statement, which typically executes a SQL query against a configured data provider.
Syntax: Cursor collectionName, "SQL Statement"
Example:
Cursor DATA1, "select top 20 id,name where type='S' from sysobjects order by name"| Statement/Function | Syntax | Type | Description |
|---|---|---|---|
| FETCH | FETCH collectionName | Statement | Reads the next record from the cursor's result set, making its fields accessible for use. |
| RESET | RESET collectionName | Statement | Resets the cursor position back to the beginning of the result set, allowing the program to iterate over the data again. |
| EOD() | EOD("collectionName") | Function | Returns a boolean value (true/false) indicating if the End Of Data has been reached for the specified cursor. |
| Field Access | [collectionName.FieldName] | Syntax | Accesses the value of a field from the currently fetched record. |
This is the most common and robust method for processing all records in the result set.
Foreach DATA1
sdata names \[DATA1.name\]
EndForeach DATA1This method offers fine-grained control over reading records, often used with conditional branching using EOD().
dataloop1:
fetch DATA1
If EOD("DATA1") Then
GoTo exitloop
EndIf
let msg= "ID: " \+ sql(\[DATA1.id\]) \+ ", Name: " \+ sql(\[DATA1.name\])
print msg
GoTo dataloop1
exitloop:The Data Provider is a crucial component that extends FBASIC's core functionality, serving as the bridge between the program's execution environment and external data sources, typically relational databases accessible via SQL.
The Data Provider is an external adapter, configured at the interpreter level, that executes the following responsibilities:
- Connection Management: It establishes and maintains the necessary connection to the external database (e.g., SQL Server, Oracle, or a file-based database).
- SQL Execution: It receives the raw SQL query string passed through the CURSOR statement. It executes this query against the configured database.
- Result Set Wrapping: Instead of returning the raw data, the Data Provider wraps the query results into a CURSOR collection. This design ensures that FBASIC can efficiently process large datasets record-by-record without loading the entire result into memory, facilitating data streaming.
The CURSOR collection is entirely dependent on a correctly configured Data Provider being available to the FBASIC environment. If the Data Provider is not configured or fails to execute the SQL, the CURSOR statement will result in a runtime exception.