OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 129 LINES
 
[ HISTORY ]  [ UP ]
 

package database

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	sqlite3 "github.com/mattn/go-sqlite3"
)

func init() {
	sql.Register("sqlite3_ookstats", &sqlite3.SQLiteDriver{
		ConnectHook: func(conn *sqlite3.SQLiteConn) error {
			// cache_size has no DSN param in mattn/go-sqlite3; apply per connection
			_, err := conn.Exec("PRAGMA cache_size = -64000", nil)
			return err
		},
	})
}

var dbPathOverride string

// SetDBPath allows callers (CLI) to override the local SQLite filename
func SetDBPath(path string) {
	dbPathOverride = path
}

// DBConnString returns the DSN for the local SQLite file
func DBConnString() string {
	// Priority: explicit override -> env vars -> default
	if dbPathOverride != "" {
		if strings.HasPrefix(dbPathOverride, "file:") {
			return ensureDSNParams(dbPathOverride)
		}
		return ensureDSNParams("file:" + dbPathOverride)
	}
	if v := os.Getenv("OOKSTATS_DB"); v != "" {
		if strings.HasPrefix(v, "file:") {
			return ensureDSNParams(v)
		}
		return ensureDSNParams("file:" + v)
	}
	if v := os.Getenv("ASTRO_DATABASE_FILE"); v != "" {
		if strings.HasPrefix(v, "file:") {
			return ensureDSNParams(v)
		}
		return ensureDSNParams("file:" + v)
	}
	return ensureDSNParams("file:local.db")
}

func ensureDSNParams(base string) string {
	if !strings.HasPrefix(base, "file:") {
		return base
	}
	if strings.Contains(base, "?") {
		return base
	}
	return base + "?_journal_mode=WAL&_synchronous=NORMAL&_busy_timeout=5000"
}

// DBFilePath returns the plain filesystem path for the local DB (without file: pr
efix)
func DBFilePath() string {
	conn := DBConnString()
	if strings.HasPrefix(conn, "file:") {
		return strings.TrimPrefix(conn, "file:")
	}
	return conn
}

func Connect() (*sql.DB, error) {
	dsn := DBConnString()
	fmt.Printf("Using local SQLite database: %s\n", dsn)
	fmt.Printf("Opening database connection...\n")

	db, err := sql.Open("sqlite3_ookstats", dsn)
	if err != nil {
		return nil, fmt.Errorf("failed to open database: %w", err)
	}
	fmt.Printf("Testing database connection...\n")
	if err := db.Ping(); err != nil {
		db.Close()
		return nil, fmt.Errorf("failed to ping database: %w", err)
	}

	// configure database for optimal performance
	if err := configureDatabaseSettings(db, dsn); err != nil {
		db.Close()
		return nil, fmt.Errorf("failed to configure database: %w", err)
	}

	fmt.Printf("[OK] Local SQLite database connected\n")
	return db, nil
}

func getEnvOrFail(key string) string {
	value := os.Getenv(key)
	if value == "" {
		fmt.Fprintf(os.Stderr, "Error: %s environment variable is required\n", key)
		os.Exit(1)
	}
	return value
}

// ExecuteSQL executes SQL with error handling
func ExecuteSQL(db *sql.DB, query string, args ...any) error {
	_, err := db.Exec(query, args...)
	if err != nil {
		return fmt.Errorf("SQL execution failed: %w\nQuery: %s", err, query)
	}
	return nil
}

// QuerySQL executes query and returns rows
func QuerySQL(db *sql.DB, query string, args ...any) (*sql.Rows, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, fmt.Errorf("SQL query failed: %w\nQuery: %s", err, query)
	}
	return rows, nil
}

// configureDatabaseSettings optimizes database for performance
func configureDatabaseSettings(db *sql.DB, dsn string) error {
	fmt.Printf("[OK] Database configured\n")
	return nil
}

package database

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	sqlite3 "github.com/mattn/go-sqlite3"
)

func init() {
	sql.Register("sqlite3_ookstats", &sqlite3.S
QLiteDriver{
		ConnectHook: func(conn *sqlite3.SQLiteConn
) error {
			// cache_size has no DSN param in mattn/g
o-sqlite3; apply per connection
			_, err := conn.Exec("PRAGMA cache_size = 
-64000", nil)
			return err
		},
	})
}

var dbPathOverride string

// SetDBPath allows callers (CLI) to overrid
e the local SQLite filename
func SetDBPath(path string) {
	dbPathOverride = path
}

// DBConnString returns the DSN for the loca
l SQLite file
func DBConnString() string {
	// Priority: explicit override -> env vars 
-> default
	if dbPathOverride != "" {
		if strings.HasPrefix(dbPathOverride, "file
:") {
			return ensureDSNParams(dbPathOverride)
		}
		return ensureDSNParams("file:" + dbPathOve
rride)
	}
	if v := os.Getenv("OOKSTATS_DB"); v != "" {
		if strings.HasPrefix(v, "file:") {
			return ensureDSNParams(v)
		}
		return ensureDSNParams("file:" + v)
	}
	if v := os.Getenv("ASTRO_DATABASE_FILE"); v
 != "" {
		if strings.HasPrefix(v, "file:") {
			return ensureDSNParams(v)
		}
		return ensureDSNParams("file:" + v)
	}
	return ensureDSNParams("file:local.db")
}

func ensureDSNParams(base string) string {
	if !strings.HasPrefix(base, "file:") {
		return base
	}
	if strings.Contains(base, "?") {
		return base
	}
	return base + "?_journal_mode=WAL&_synchron
ous=NORMAL&_busy_timeout=5000"
}

// DBFilePath returns the plain filesystem p
ath for the local DB (without file: prefix)
func DBFilePath() string {
	conn := DBConnString()
	if strings.HasPrefix(conn, "file:") {
		return strings.TrimPrefix(conn, "file:")
	}
	return conn
}

func Connect() (*sql.DB, error) {
	dsn := DBConnString()
	fmt.Printf("Using local SQLite database: %s
\n", dsn)
	fmt.Printf("Opening database connection...\
n")

	db, err := sql.Open("sqlite3_ookstats", dsn
)
	if err != nil {
		return nil, fmt.Errorf("failed to open dat
abase: %w", err)
	}
	fmt.Printf("Testing database connection...\
n")
	if err := db.Ping(); err != nil {
		db.Close()
		return nil, fmt.Errorf("failed to ping dat
abase: %w", err)
	}

	// configure database for optimal performan
ce
	if err := configureDatabaseSettings(db, dsn
); err != nil {
		db.Close()
		return nil, fmt.Errorf("failed to configur
e database: %w", err)
	}

	fmt.Printf("[OK] Local SQLite database conn
ected\n")
	return db, nil
}

func getEnvOrFail(key string) string {
	value := os.Getenv(key)
	if value == "" {
		fmt.Fprintf(os.Stderr, "Error: %s environm
ent variable is required\n", key)
		os.Exit(1)
	}
	return value
}

// ExecuteSQL executes SQL with error handli
ng
func ExecuteSQL(db *sql.DB, query string, ar
gs ...any) error {
	_, err := db.Exec(query, args...)
	if err != nil {
		return fmt.Errorf("SQL execution failed: %
w\nQuery: %s", err, query)
	}
	return nil
}

// QuerySQL executes query and returns rows
func QuerySQL(db *sql.DB, query string, args
 ...any) (*sql.Rows, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, fmt.Errorf("SQL query failed: 
%w\nQuery: %s", err, query)
	}
	return rows, nil
}

// configureDatabaseSettings optimizes datab
ase for performance
func configureDatabaseSettings(db *sql.DB, d
sn string) error {
	fmt.Printf("[OK] Database configured\n")
	return nil
}
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET