Consistent naming with zcat ecosystem (zcatui, zcatgui, zcatsql). All lowercase per Zig naming conventions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
153 lines
4.8 KiB
Zig
153 lines
4.8 KiB
Zig
//! Basic example demonstrating zcatsql usage
|
|
//!
|
|
//! This example shows:
|
|
//! - Opening a database
|
|
//! - Creating tables
|
|
//! - Inserting data with prepared statements
|
|
//! - Querying data
|
|
//! - Transactions
|
|
|
|
const std = @import("std");
|
|
const sqlite = @import("zcatsql");
|
|
|
|
pub fn main() !void {
|
|
std.debug.print("zcatsql basic example\n", .{});
|
|
std.debug.print("SQLite version: {s}\n\n", .{sqlite.version()});
|
|
|
|
// Open an in-memory database
|
|
var db = try sqlite.openMemory();
|
|
defer db.close();
|
|
|
|
// Enable foreign keys (recommended)
|
|
try db.setForeignKeys(true);
|
|
|
|
// Create tables
|
|
try db.exec(
|
|
\\CREATE TABLE users (
|
|
\\ id INTEGER PRIMARY KEY,
|
|
\\ name TEXT NOT NULL,
|
|
\\ email TEXT UNIQUE,
|
|
\\ created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
\\);
|
|
\\
|
|
\\CREATE TABLE posts (
|
|
\\ id INTEGER PRIMARY KEY,
|
|
\\ user_id INTEGER NOT NULL REFERENCES users(id),
|
|
\\ title TEXT NOT NULL,
|
|
\\ content TEXT
|
|
\\);
|
|
);
|
|
|
|
std.debug.print("Tables created successfully\n\n", .{});
|
|
|
|
// Insert users with prepared statement
|
|
{
|
|
var stmt = try db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
|
|
defer stmt.finalize();
|
|
|
|
const users = [_][2][]const u8{
|
|
.{ "Alice", "alice@example.com" },
|
|
.{ "Bob", "bob@example.com" },
|
|
.{ "Charlie", "charlie@example.com" },
|
|
};
|
|
|
|
for (users) |user| {
|
|
try stmt.bindText(1, user[0]);
|
|
try stmt.bindText(2, user[1]);
|
|
_ = try stmt.step();
|
|
try stmt.reset();
|
|
try stmt.clearBindings();
|
|
}
|
|
|
|
std.debug.print("Inserted {} users\n", .{db.totalChanges()});
|
|
}
|
|
|
|
// Insert posts
|
|
{
|
|
var stmt = try db.prepare("INSERT INTO posts (user_id, title, content) VALUES (?, ?, ?)");
|
|
defer stmt.finalize();
|
|
|
|
try stmt.bindInt(1, 1); // Alice
|
|
try stmt.bindText(2, "Hello World");
|
|
try stmt.bindText(3, "This is my first post!");
|
|
_ = try stmt.step();
|
|
try stmt.reset();
|
|
try stmt.clearBindings();
|
|
|
|
try stmt.bindInt(1, 1); // Alice
|
|
try stmt.bindText(2, "Zig is awesome");
|
|
try stmt.bindNull(3); // No content
|
|
_ = try stmt.step();
|
|
try stmt.reset();
|
|
try stmt.clearBindings();
|
|
|
|
try stmt.bindInt(1, 2); // Bob
|
|
try stmt.bindText(2, "SQLite rocks");
|
|
try stmt.bindText(3, "Zero dependencies!");
|
|
_ = try stmt.step();
|
|
}
|
|
|
|
std.debug.print("Inserted posts\n\n", .{});
|
|
|
|
// Query users
|
|
std.debug.print("All users:\n", .{});
|
|
std.debug.print("-" ** 50 ++ "\n", .{});
|
|
{
|
|
var stmt = try db.prepare("SELECT id, name, email FROM users ORDER BY name");
|
|
defer stmt.finalize();
|
|
|
|
while (try stmt.step()) {
|
|
const id = stmt.columnInt(0);
|
|
const name = stmt.columnText(1) orelse "(null)";
|
|
const email = stmt.columnText(2) orelse "(null)";
|
|
std.debug.print(" [{d}] {s} <{s}>\n", .{ id, name, email });
|
|
}
|
|
}
|
|
|
|
// Query posts with JOIN
|
|
std.debug.print("\nPosts with authors:\n", .{});
|
|
std.debug.print("-" ** 50 ++ "\n", .{});
|
|
{
|
|
var stmt = try db.prepare(
|
|
\\SELECT p.title, u.name, p.content
|
|
\\FROM posts p
|
|
\\JOIN users u ON p.user_id = u.id
|
|
\\ORDER BY p.id
|
|
);
|
|
defer stmt.finalize();
|
|
|
|
while (try stmt.step()) {
|
|
const title = stmt.columnText(0) orelse "(null)";
|
|
const author = stmt.columnText(1) orelse "(null)";
|
|
const content = stmt.columnText(2) orelse "(no content)";
|
|
std.debug.print(" \"{s}\" by {s}\n", .{ title, author });
|
|
std.debug.print(" {s}\n", .{content});
|
|
}
|
|
}
|
|
|
|
// Demonstrate transaction rollback
|
|
std.debug.print("\nTransaction demo:\n", .{});
|
|
std.debug.print("-" ** 50 ++ "\n", .{});
|
|
{
|
|
// Count before
|
|
var count_stmt = try db.prepare("SELECT COUNT(*) FROM users");
|
|
defer count_stmt.finalize();
|
|
_ = try count_stmt.step();
|
|
const count_before = count_stmt.columnInt(0);
|
|
std.debug.print(" Users before transaction: {d}\n", .{count_before});
|
|
|
|
// Start transaction and insert, then rollback
|
|
try db.begin();
|
|
try db.exec("INSERT INTO users (name, email) VALUES ('Temporary', 'temp@example.com')");
|
|
try db.rollback();
|
|
|
|
// Count after rollback
|
|
try count_stmt.reset();
|
|
_ = try count_stmt.step();
|
|
const count_after = count_stmt.columnInt(0);
|
|
std.debug.print(" Users after rollback: {d}\n", .{count_after});
|
|
std.debug.print(" Transaction was rolled back successfully!\n", .{});
|
|
}
|
|
|
|
std.debug.print("\nDone!\n", .{});
|
|
}
|