package db
import (
"context"
"database/sql"
"fmt"
_ "github.com/duckdb/duckdb-go/v2" )
func OpenReadOnlyDB(dbPath string) (*sql.DB, error) {
connStr := dbPath + "?access_mode=read_only"
db, err := sql.Open("duckdb", connStr)
if err != nil {
return nil, fmt.Errorf("failed to open database: %w", err)
}
if err = db.Ping(); err != nil {
closeErr := db.Close()
if closeErr != nil {
return nil, fmt.Errorf("failed to ping database: %w (close error: %v)", err, closeErr)
}
return nil, fmt.Errorf("failed to ping database: %w", err)
}
return db, nil
}
func WithReadDB(dbPath string, fn func(*sql.DB) error) error {
database, err := OpenReadOnlyDB(dbPath)
if err != nil {
return fmt.Errorf("database connection failed: %w", err)
}
defer database.Close()
return fn(database)
}
func WithWriteTx(ctx context.Context, dbPath, toolName string, fn func(*sql.DB, *LoggedTx) error) error {
database, err := OpenWriteableDB(dbPath)
if err != nil {
return fmt.Errorf("database connection failed: %w", err)
}
defer database.Close()
tx, err := BeginLoggedTx(ctx, database, toolName)
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
if err := fn(database, tx); err != nil {
return err
}
return tx.Commit()
}
func OpenWriteableDB(dbPath string) (*sql.DB, error) {
connStr := dbPath + "?access_mode=read_write"
db, err := sql.Open("duckdb", connStr)
if err != nil {
return nil, fmt.Errorf("failed to open database: %w", err)
}
if err = db.Ping(); err != nil {
closeErr := db.Close()
if closeErr != nil {
return nil, fmt.Errorf("failed to ping database: %w (close error: %v)", err, closeErr)
}
return nil, fmt.Errorf("failed to ping database: %w", err)
}
return db, nil
}