databasepostgresqlgomigrate

Getting error 'source driver: unknown driver 'c' (forgotten import?)' when trying to use Golang Migrate


I am trying to use Golang Migrate but have been getting this error 'source driver: unknown driver 'c' (forgotten import?)' whenever I try to run my code.

My code:

main.go ->

package main

import (
    _ "github.com/golang-migrate/migrate/v4/source/file"
    _ "github.com/mattes/migrate/source/file"
    "log"
    "database/sql"
    "fmt"
    "my-migrate-project/db"
    "os"
)

func main() {
    dbURL := "postgres://postgres:password@localhost:5432/TestDb?sslmode=disable"

    // Open a connection using the database/sql package
    sqlDB, err := db.OpenDB(dbURL)
    if err != nil {
        log.Fatal("Error opening database connection:", err)
    }
    defer sqlDB.Close()

    // Before Migrate Operations
    if err := beforeMigrationTxns(sqlDB); err != nil {
        log.Fatal("Error during transactions before migration:", err)
    }

    // Migrate the database
    if err := db.Migrate(sqlDB); err != nil {
        fmt.Println("Error during migration:", err)

        // Rollback in case of migration error
        if rollbackErr := db.Rollback(sqlDB); rollbackErr != nil {
            fmt.Println("Error during rollback:", rollbackErr)
        }
    } else {
        fmt.Println("Migration successful")

        // After Migrate Operations
        if err := afterMigrationTxns(sqlDB); err != nil {
            log.Fatal("Error during transactions after migration:", err)
        }
    }
}

func beforeMigrationTxns(sqlDB *sql.DB) error {
    fmt.Println("Performing custom transactions before migration")

    // Read custom SQL queries from file
    queryFile := "db/migrations/custom_queries_1.sql"
    queries, err := os.ReadFile(queryFile)
    if err != nil {
        return err
    }

    // Execute custom queries
    _, err = sqlDB.Exec(string(queries))
    if err != nil {
        return err
    }

    return nil
}

func afterMigrationTxns(sqlDB *sql.DB) error {
    fmt.Println("Performing custom transactions after migration")

    // Read custom SQL queries from file
    queryFile := "db/migrations/custom_queries_2.sql"
    queries, err := os.ReadFile(queryFile)
    if err != nil {
        return err
    }

    // Execute custom queries
    _, err = sqlDB.Exec(string(queries))
    if err != nil {
        return err
    }

    return nil
}

db.go ->

package db

import (
    "github.com/golang-migrate/migrate/v4"
    _ "github.com/golang-migrate/migrate/v4/source/file"
    _ "github.com/mattes/migrate/source/file"
    "database/sql"
    "fmt"
    pgmigrate "github.com/golang-migrate/migrate/v4/database/postgres"
)

// OpenDB opens a PostgreSQL database connection using go-pg
func OpenDB(dbURL string) (*sql.DB, error) {
    db, err := sql.Open("postgres", dbURL)
    if err != nil {
        return nil, err
    }

    return db, nil
}

func Migrate(sqlDB *sql.DB) error {
    // Create a new migration driver instance for PostgreSQL
    driver, err := pgmigrate.WithInstance(sqlDB, &pgmigrate.Config{})
    if err != nil {
        return err
    }

    m, err := migrate.NewWithDatabaseInstance(
        "C:\\Users\\91790\\Documents\\Onito\\my-migrate-project\\db\\migrations",
        "postgres", driver)
    if err != nil {
        return err
    }

    // 'Up' method applies all migrations that have not been applied yet
    // Checks if there is any general error during the migration process
    // ErrNoChange is a specific error returned when there are no new migrations to apply.
    // In such a case, it doesn't indicate a failure but rather that there were no changes to be made.
    if err := m.Up(); err != nil && err != migrate.ErrNoChange {
        return err
    }

    fmt.Println("Migration successful")
    return nil
}

// Rollback rolls back the last PostgreSQL database migration
func Rollback(sqlDB *sql.DB) error {
    // Create a new migration driver instance for PostgreSQL
    driver, err := pgmigrate.WithInstance(sqlDB, &pgmigrate.Config{})
    if err != nil {
        return err
    }

    // Create a new migration instance with the PostgreSQL driver
    m, err := migrate.NewWithDatabaseInstance(
        "C:\\Users\\91790\\Documents\\Onito\\my-migrate-project\\db\\migrations",
        "postgres", driver)
    if err != nil {
        return err
    }

    //  Force method to set the version to 0, effectively rolling back to the initial version
    if err := m.Force(0); err != nil {
        return err
    }

    // Print a success message if the rollback is successful
    fmt.Println("Rollback successful")

    // Return nil to indicate success
    return nil
}

I tried all the solutions available online:

But still getting the same error.


Solution

  • github.com/golang-migrate/migrate determines the source driver from the schema of the source URL.

    In your code, the following source URL does not contain a valid schema:

    C:\\Users\\91790\\Documents\\Onito\\my-migrate-project\\db\\migrations
    

    To read the migration source from a filesystem, the source URL should start with file:// (the schema is file). And the separator character should be a slash (/) too. Try this source URL:

    file://C:/Users/91790/Documents/Onito/my-migrate-project/db/migrations
    

    BTW, github.com/golang-migrate/migrate is a fork of github.com/mattes/migrate. I don't think that you need github.com/mattes/migrate/source/file any more.

    References:

    1. Doesn't work on Windows as schemeFromUrl Incorrectly Uses net/url to check Scheme
    2. Migration sources