migrate: Add example
This commit is contained in:
committed by
Michal Jan Matczuk
parent
9dd79fc620
commit
1b6e643584
2
Makefile
2
Makefile
@@ -40,7 +40,7 @@ bench:
|
|||||||
|
|
||||||
.PHONY: run-examples
|
.PHONY: run-examples
|
||||||
run-examples:
|
run-examples:
|
||||||
@go test -tags all -v -run=Example
|
@go test -tags all -v -run=Example ./...
|
||||||
|
|
||||||
.PHONY: run-scylla
|
.PHONY: run-scylla
|
||||||
run-scylla:
|
run-scylla:
|
||||||
|
|||||||
@@ -62,11 +62,42 @@ func CreateCluster() *gocql.ClusterConfig {
|
|||||||
return cluster
|
return cluster
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateKeyspace creates keyspace with SimpleStrategy and RF derived from flags.
|
||||||
|
func CreateKeyspace(cluster *gocql.ClusterConfig, keyspace string) error {
|
||||||
|
c := *cluster
|
||||||
|
c.Keyspace = "system"
|
||||||
|
c.Timeout = 30 * time.Second
|
||||||
|
|
||||||
|
session, err := gocqlx.WrapSession(c.CreateSession())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
{
|
||||||
|
err := session.ExecStmt(`DROP KEYSPACE IF EXISTS ` + keyspace)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("drop keyspace: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
err := session.ExecStmt(fmt.Sprintf(`CREATE KEYSPACE %s WITH replication = {'class' : 'SimpleStrategy', 'replication_factor' : %d}`, keyspace, *flagRF))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create keyspace: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func createSessionFromCluster(cluster *gocql.ClusterConfig, tb testing.TB) gocqlx.Session {
|
func createSessionFromCluster(cluster *gocql.ClusterConfig, tb testing.TB) gocqlx.Session {
|
||||||
// Drop and re-create the keyspace once. Different tests should use their own
|
// Drop and re-create the keyspace once. Different tests should use their own
|
||||||
// individual tables, but can assume that the table does not exist before.
|
// individual tables, but can assume that the table does not exist before.
|
||||||
initOnce.Do(func() {
|
initOnce.Do(func() {
|
||||||
createKeyspace(tb, cluster, "gocqlx_test")
|
if err := CreateKeyspace(cluster, "gocqlx_test"); err != nil {
|
||||||
|
tb.Fatal(err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
cluster.Keyspace = "gocqlx_test"
|
cluster.Keyspace = "gocqlx_test"
|
||||||
@@ -76,28 +107,3 @@ func createSessionFromCluster(cluster *gocql.ClusterConfig, tb testing.TB) gocql
|
|||||||
}
|
}
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func createKeyspace(tb testing.TB, cluster *gocql.ClusterConfig, keyspace string) {
|
|
||||||
c := *cluster
|
|
||||||
c.Keyspace = "system"
|
|
||||||
c.Timeout = 30 * time.Second
|
|
||||||
session, err := gocqlx.WrapSession(c.CreateSession())
|
|
||||||
if err != nil {
|
|
||||||
tb.Fatal(err)
|
|
||||||
}
|
|
||||||
defer session.Close()
|
|
||||||
|
|
||||||
err = session.ExecStmt(`DROP KEYSPACE IF EXISTS ` + keyspace)
|
|
||||||
if err != nil {
|
|
||||||
tb.Fatalf("unable to drop keyspace: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = session.ExecStmt(fmt.Sprintf(`CREATE KEYSPACE %s
|
|
||||||
WITH replication = {
|
|
||||||
'class' : 'SimpleStrategy',
|
|
||||||
'replication_factor' : %d
|
|
||||||
}`, keyspace, *flagRF))
|
|
||||||
if err != nil {
|
|
||||||
tb.Fatalf("unable to create keyspace: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,35 +1,8 @@
|
|||||||
# GoCQLX Migrations
|
# 🚀 GocqlX Migrations
|
||||||
|
|
||||||
Package `migrate` provides simple and flexible CQL migrations.
|
`migrate` reads migrations from a flat directory containing CQL files.
|
||||||
Migrations can be read from a flat directory containing cql files.
|
There is no imposed naming schema. Migration name is file name.
|
||||||
There is no imposed naming schema, migration name is file name and the migrations are processed in lexicographical order.
|
The order of migrations is the lexicographical order of file names in the directory.
|
||||||
Caller provides a `gocqlx.Session`, the session must use a desired keyspace as migrate would try to create migrations table.
|
You can inject execution of Go code before processing of a migration file, after processing of a migration file, or between statements in a migration file.
|
||||||
|
|
||||||
## Features
|
For details see [example](example) migration.
|
||||||
|
|
||||||
* Each CQL statement will run once
|
|
||||||
* Go code migrations using callbacks
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/scylladb/gocqlx/v2/migrate"
|
|
||||||
)
|
|
||||||
|
|
||||||
const dir = "./cql"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
session := CreateSession()
|
|
||||||
defer session.Close()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
if err := migrate.Migrate(ctx, session, dir); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a ALv2-style
|
// Use of this source code is governed by a ALv2-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package migrate provides simple and flexible CLQ migrations.
|
// Package migrate reads migrations from a flat directory containing CQL files.
|
||||||
// Migrations can be read from a flat directory containing cql files.
|
// There is no imposed naming schema. Migration name is file name.
|
||||||
// There is no imposed naming schema, migration name is file name and the migrations are processed in lexicographical order.
|
// The order of migrations is the lexicographical order of file names in the directory.
|
||||||
// Caller provides a gocqlx.Session, the session must use a desired keyspace as migrate would try to create migrations table.
|
// You can inject execution of Go code before processing of a migration file, after processing of a migration file, or between statements in a migration file.
|
||||||
package migrate
|
package migrate
|
||||||
|
|||||||
60
migrate/example/example_test.go
Normal file
60
migrate/example/example_test.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (C) 2017 ScyllaDB
|
||||||
|
// Use of this source code is governed by a ALv2-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build all integration
|
||||||
|
|
||||||
|
package example
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/scylladb/gocqlx/v2"
|
||||||
|
"github.com/scylladb/gocqlx/v2/gocqlxtest"
|
||||||
|
"github.com/scylladb/gocqlx/v2/migrate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Running examples locally:
|
||||||
|
// make run-scylla
|
||||||
|
// make run-examples
|
||||||
|
func TestExample(t *testing.T) {
|
||||||
|
const ks = "migrate_example"
|
||||||
|
|
||||||
|
cluster := gocqlxtest.CreateCluster()
|
||||||
|
cluster.Keyspace = ks
|
||||||
|
|
||||||
|
if err := gocqlxtest.CreateKeyspace(cluster, ks); err != nil {
|
||||||
|
t.Fatal("CreateKeyspace:", err)
|
||||||
|
}
|
||||||
|
session, err := gocqlx.WrapSession(cluster.CreateSession())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("CreateSession:", err)
|
||||||
|
}
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
// Add callback prints
|
||||||
|
printEvent := func(ctx context.Context, session gocqlx.Session, ev migrate.CallbackEvent, name string) error {
|
||||||
|
t.Log(ev, name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
reg := migrate.CallbackRegister{}
|
||||||
|
reg.Add(migrate.BeforeMigration, "m1.cql", printEvent)
|
||||||
|
reg.Add(migrate.AfterMigration, "m1.cql", printEvent)
|
||||||
|
reg.Add(migrate.CallComment, "1", printEvent)
|
||||||
|
reg.Add(migrate.CallComment, "2", printEvent)
|
||||||
|
reg.Add(migrate.CallComment, "3", printEvent)
|
||||||
|
|
||||||
|
migrate.Callback = reg.Callback
|
||||||
|
|
||||||
|
// First run prints data
|
||||||
|
if err := migrate.Migrate(context.Background(), session, "migrations"); err != nil {
|
||||||
|
t.Fatal("Migrate:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second run skips the processed files
|
||||||
|
if err := migrate.Migrate(context.Background(), session, "migrations"); err != nil {
|
||||||
|
t.Fatal("Migrate:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
migrate/example/migrations/m1.cql
Normal file
15
migrate/example/migrations/m1.cql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- Comment
|
||||||
|
|
||||||
|
CREATE TABLE bar ( id int PRIMARY KEY);
|
||||||
|
|
||||||
|
INSERT INTO bar (id) VALUES (1);
|
||||||
|
|
||||||
|
-- CALL 1;
|
||||||
|
|
||||||
|
INSERT INTO bar (id) VALUES (2);
|
||||||
|
|
||||||
|
-- CALL 2;
|
||||||
|
|
||||||
|
INSERT INTO bar (id) VALUES (3);
|
||||||
|
|
||||||
|
-- CALL 3;
|
||||||
Reference in New Issue
Block a user