123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- package dbmanager
- import (
- "fmt"
- "os"
- "gorm.io/driver/sqlite"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
- )
- // SQLiteManager implements the DbManager interface for SQLite using GORM
- type SQLiteManager struct {
- db *gorm.DB
- dsn string
- }
- // NewSQLiteManager initializes a new SQLiteManager
- func NewSQLiteManager(dataSourceName string) (*SQLiteManager, error) {
- // First check if the database file exists
- isNewDb := !fileExists(dataSourceName)
- if isNewDb {
- // Create the database file if it doesn't exist
- file, err := os.Create(dataSourceName)
- if err != nil {
- return nil, fmt.Errorf("failed to create SQLite database file: %w", err)
- }
- defer file.Close()
- }
- // Open SQLite database with GORM and SQLite-specific configuration
- db, err := gorm.Open(sqlite.Open(dataSourceName), &gorm.Config{
- Logger: logger.Default.LogMode(logger.Silent),
- // Set DisableForeignKeyConstraintWhenMigrating to true to avoid foreign key issues during migration
- DisableForeignKeyConstraintWhenMigrating: true,
- })
- if err != nil {
- return nil, fmt.Errorf("failed to connect to SQLite database: %w", err)
- }
- // Enable foreign keys in SQLite after migrations
- db.Exec("PRAGMA foreign_keys = ON")
- return &SQLiteManager{
- db: db,
- dsn: dataSourceName,
- }, nil
- }
- // fileExists checks if a file exists
- func fileExists(filename string) bool {
- _, err := os.Stat(filename)
- return !os.IsNotExist(err)
- }
- // GetDB returns the GORM database instance
- func (m *SQLiteManager) GetDB() *gorm.DB {
- return m.db
- }
- // Connect establishes a connection to the SQLite database
- func (m *SQLiteManager) Connect() error {
- // Connection is already established in NewSQLiteManager
- return nil
- }
- // Disconnect closes the connection to the SQLite database
- func (m *SQLiteManager) Disconnect() error {
- sqlDB, err := m.db.DB()
- if err != nil {
- return err
- }
- return sqlDB.Close()
- }
- // Migrate runs auto migration for the provided models
- func (m *SQLiteManager) Migrate(models ...interface{}) error {
- // Check if database file exists before
- isNewDb := !fileExists(m.dsn)
- // SQLite has limitations with ALTER TABLE for adding NOT NULL columns
- // For a new database, we can just create tables directly
- if isNewDb {
- return m.db.AutoMigrate(models...)
- }
- // For existing database, we need a more careful approach to avoid NOT NULL errors
- // Try to create tables that don't exist
- migrator := m.db.Migrator()
- for _, model := range models {
- // Check if the table exists
- if !migrator.HasTable(model) {
- // If table doesn't exist, create it
- if err := migrator.CreateTable(model); err != nil {
- return fmt.Errorf("failed to create table for %T: %w", model, err)
- }
- }
- }
- // Re-enable foreign key constraints
- m.db.Exec("PRAGMA foreign_keys = ON")
- return nil
- }
|