From b08636ba393055bb26343f694b0ef70c95358a71 Mon Sep 17 00:00:00 2001 From: Mason Payne Date: Wed, 16 Oct 2024 18:04:01 -0600 Subject: [PATCH] move-migrations-to-option (#1) Removes global variables and sets up migrations as optional. Reviewed-on: https://git.sa.vin/payne8/libsqldb/pulls/1 Co-authored-by: Mason Payne Co-committed-by: Mason Payne --- db.go | 27 +++++++++++++++++---------- embedded.go | 17 +++++++++-------- examples/basic-usage/main.go | 4 ++-- readme.md | 9 --------- remote-only.go | 21 ++++++++++++--------- 5 files changed, 40 insertions(+), 38 deletions(-) diff --git a/db.go b/db.go index 022cfbf..f221148 100644 --- a/db.go +++ b/db.go @@ -16,25 +16,20 @@ type Migrations struct { type Options func(*LibSqlDB) error -// use something like this in the user's code -> //go:embed migrations/*.sql -var _migrationFiles embed.FS - -var migrations []Migrations - // func NewLibSqlDB is defined in embedded.go and remote-only.go files // these files are used to define the LibSqlDB struct and the NewLibSqlDB function // they have different initializations based on the environment, embedded or remote-only // Windows does not currently support the embedded database, so the remote-only file is used // setupMigrations initializes the filesystem and reads the migration files into the migrations variable -func setupMigrations() error { +func (t *LibSqlDB) setupMigrations() error { // Walk through the embedded files and read their contents - err := fs.WalkDir(_migrationFiles, ".", func(path string, d fs.DirEntry, err error) error { + err := fs.WalkDir(t.migrationFiles, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if !d.IsDir() { - content, err := _migrationFiles.ReadFile(path) + content, err := t.migrationFiles.ReadFile(path) if err != nil { return err } @@ -43,7 +38,7 @@ func setupMigrations() error { name: filepath.Base(path), query: string(content), } - migrations = append(migrations, migration) + t.migrations = append(t.migrations, migration) } return nil }) @@ -55,6 +50,10 @@ func setupMigrations() error { // Migrate updates the connected LibSqlDB to the latest schema based on the given migrations func (t *LibSqlDB) Migrate() error { + if !t.useMigrations { + return fmt.Errorf("migrations not enabled") + } + // check if migration table exists var migrationsCheck string //goland:noinspection SqlResolve @@ -70,7 +69,7 @@ func (t *LibSqlDB) Migrate() error { } } - for _, migration := range migrations { + for _, migration := range t.migrations { var migrationInHistory string err = t.DB.QueryRow("SELECT name FROM migrations WHERE name = ?", migration.name).Scan(&migrationInHistory) if err != nil { @@ -138,3 +137,11 @@ func WithReadYourWrites(readYourWrites bool) Options { return nil } } + +func WithMigrationFiles(migrationFiles embed.FS) Options { + return func(l *LibSqlDB) error { + l.useMigrations = true + l.migrationFiles = migrationFiles + return nil + } +} diff --git a/embedded.go b/embedded.go index 3c5636a..6bb336c 100644 --- a/embedded.go +++ b/embedded.go @@ -22,15 +22,14 @@ type LibSqlDB struct { syncInterval time.Duration // only used for embedded replica encryptionKey string // only used for embedded replica readYourWrites *bool // only used for embedded replica + useMigrations bool + migrationFiles embed.FS + migrations []Migrations } -var syncInterval = 200 * time.Millisecond - -func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (*LibSqlDB, error) { +func NewLibSqlDB(primaryUrl string, opts ...Options) (*LibSqlDB, error) { l := libSqlDefaults() - _migrationFiles = migrationFiles - for _, option := range opts { err := option(l) if err != nil { @@ -74,9 +73,11 @@ func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (* db := sql.OpenDB(connector) - err = setupMigrations() - if err != nil { - return nil, fmt.Errorf("error setting up migrations | %w", err) + if l.useMigrations { + err = l.setupMigrations() + if err != nil { + return nil, fmt.Errorf("error setting up migrations | %w", err) + } } l.DB = db diff --git a/examples/basic-usage/main.go b/examples/basic-usage/main.go index f727360..92d5980 100644 --- a/examples/basic-usage/main.go +++ b/examples/basic-usage/main.go @@ -17,9 +17,9 @@ func main() { // Open the database tdb, err := libsqldb.NewLibSqlDB( primaryUrl, - migrationFiles, + libsqldb.WithMigrationFiles(migrationFiles), libsqldb.WithAuthToken(authToken), - libsqldb.WithLocalDBName("local.db"), + libsqldb.WithLocalDBName("local.db"), // will not be used for remote-only ) if err != nil { fmt.Fprintf(os.Stderr, "failed to open db %s: %s", primaryUrl, err) diff --git a/readme.md b/readme.md index 09a7d8c..f747bb7 100644 --- a/readme.md +++ b/readme.md @@ -32,15 +32,6 @@ tdb, err := libsqldb.NewLibSqlDB( ## Why Use This Library? I developed this library to streamline the process of setting up a database connection in Go, complete with built-in migration capabilities. During development, I encountered issues with using the embedded driver on Windows. As I researched, I discovered [others had similar issues](https://github.com/tursodatabase/go-libsql/issues/30). This wrapper solves that problem by automatically selecting the appropriate driver based on your operating system. -## How to Use -For a complete example, check out the examples/basic-usage directory in this repository. - -Before running your application, make sure to set the following environment variables: - -```bash -LIBSQL_AUTH_TOKEN -LIBSQL_DATABASE_URL -``` ### Special Note for Windows Users This library defaults to using the embedded driver for better performance and closer parity with production environments. However, due to the lack of support for embedded LibSQL on Windows, this library uses a remote driver when running on Windows. Special build tags are included to ensure seamless operation across platforms. diff --git a/remote-only.go b/remote-only.go index 8f1f21b..350d453 100644 --- a/remote-only.go +++ b/remote-only.go @@ -21,13 +21,14 @@ type LibSqlDB struct { syncInterval time.Duration // only used for embedded replica encryptionKey string // only used for embedded replica readYourWrites *bool // only used for embedded replica + useMigrations bool + migrationFiles embed.FS + migrations []Migrations } -func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (*LibSqlDB, error) { +func NewLibSqlDB(primaryUrl string, opts ...Options) (*LibSqlDB, error) { l := &LibSqlDB{} - _migrationFiles = migrationFiles - for _, option := range opts { err := option(l) if err != nil { @@ -45,14 +46,16 @@ func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (* return nil, fmt.Errorf("error setting up LibSQL db | %w", err) } - err = setupMigrations() - if err != nil { - return nil, fmt.Errorf("error setting up migrations | %w", err) + if l.useMigrations { + err = l.setupMigrations() + if err != nil { + return nil, fmt.Errorf("error setting up migrations | %w", err) + } } - return &LibSqlDB{ - DB: db, - }, nil + l.DB = db + + return l, nil } func (t *LibSqlDB) Close() error {