import "sqlite" for Database
import "io" for File
// This class provides a hook back into the C host to terminate the application.
foreign class Host {
foreign static signalDone()
}
// All database operations are asynchronous. We chain them together using
// callbacks to ensure they execute in the correct order.
var mainFiber = Fiber.new {
var db = Database.new()
var dbPath = "test.db"
var isDone = false // Flag to keep the fiber alive.
// Clean up database file from previous runs, if it exists.
if (File.exists(dbPath)) {
File.delete(dbPath)
}
System.print("--- Starting SQLite CRUD Example ---")
// 1. Open the database connection.
db.open(dbPath) { |err|
if (err) {
System.print("Error opening database: %(err)")
isDone = true // Signal completion on error.
return
}
System.print("Database opened successfully at '%(dbPath)'.")
// 2. CREATE: Create a new table.
var createSql = "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT);"
db.exec(createSql) { |err|
if (err) {
System.print("Error creating table: %(err)")
isDone = true
return
}
System.print("Table 'users' created.")
// 3. CREATE: Insert a new user.
var insertSql = "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');"
db.exec(insertSql) { |err|
if (err) {
System.print("Error inserting user: %(err)")
isDone = true
return
}
System.print("Inserted user 'Alice'.")
// 4. READ: Query all users.
db.query("SELECT * FROM users;") { |err, rows|
if (err) {
System.print("Error querying users: %(err)")
isDone = true
return
}
System.print("\n--- Current Users (after insert): ---")
for (row in rows) {
System.print(" ID: %(row["id"]), Name: %(row["name"]), Email: %(row["email"])")
}
// 5. UPDATE: Change Alice's email.
var updateSql = "UPDATE users SET email = 'alice.smith@example.com' WHERE name = 'Alice';"
db.exec(updateSql) { |err|
if (err) {
System.print("Error updating user: %(err)")
isDone = true
return
}
System.print("\nUpdated Alice's email.")
// 6. READ: Query again to see the update.
db.query("SELECT * FROM users;") { |err, rows|
if (err) {
System.print("Error querying users: %(err)")
isDone = true
return
}
System.print("\n--- Current Users (after update): ---")
for (row in rows) {
System.print(" ID: %(row["id"]), Name: %(row["name"]), Email: %(row["email"])")
}
// 7. DELETE: Remove Alice from the database.
var deleteSql = "DELETE FROM users WHERE name = 'Alice';"
db.exec(deleteSql) { |err|
if (err) {
System.print("Error deleting user: %(err)")
isDone = true
return
}
System.print("\nDeleted Alice.")
// 8. READ: Query one last time to confirm deletion.
db.query("SELECT * FROM users;") { |err, rows|
if (err) {
System.print("Error querying users: %(err)")
isDone = true
return
}
System.print("\n--- Current Users (after delete): ---")
if (rows.isEmpty) {
System.print(" (No users found)")
} else {
for (row in rows) {
System.print(" ID: %(row["id"]), Name: %(row["name"]), Email: %(row["email"])")
}
}
// 9. Close the database connection.
db.close() { |err|
if (err) {
System.print("Error closing database: %(err)")
} else {
System.print("\nDatabase closed successfully.")
}
System.print("\n--- SQLite CRUD Example Finished ---")
isDone = true // This is the final step, signal completion.
}
}
}
}
}
}
}
}
}
// Keep the fiber alive by yielding until the 'isDone' flag is set.
while (!isDone) {
Fiber.yield()
}
// All asynchronous operations are complete, now we can safely exit.
Host.signalDone()
}