From 5d480f2a45b91339eb5b6bbc3eea05706e33aefa Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Thu, 6 Apr 2023 23:06:51 +0300 Subject: [PATCH 01/34] Added query params for cluster + tests --- pkg/driver/clickhouse/clickhouse.go | 46 +++++++++++ pkg/driver/clickhouse/clickhouse_test.go | 98 +++++++++++++++++++++++- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 28935d71..1e2a060f 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -16,6 +16,13 @@ import ( "github.com/ClickHouse/clickhouse-go/v2" ) +const ( + OnClusterQueryParam = "on_cluster" + ZooPathQueryParam = "zoo_path" + ClusterMacroQueryParam = "cluster_macro" + ReplicaMacroQueryParam = "replica_macro" +) + func init() { dbmate.RegisterDriver(NewDriver, "clickhouse") } @@ -95,6 +102,45 @@ func (drv *Driver) openClickHouseDB() (*sql.DB, error) { return sql.Open("clickhouse", clickhouseURL.String()) } +func (drv *Driver) onCluster() bool { + v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() + hasOnCluster := v.Has(OnClusterQueryParam) + onClusterValue := v.Get(OnClusterQueryParam) + onCluster := hasOnCluster && (onClusterValue == "" || onClusterValue == "true") + return onCluster +} + + +func (drv *Driver) clusterMacro() string { + v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() + clusterMacro := v.Get(ClusterMacroQueryParam) + if clusterMacro == "" { + clusterMacro = "{cluster}" + } + return clusterMacro +} + + +func (drv *Driver) replicaMacro() string { + v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() + replicaMacro := v.Get(ReplicaMacroQueryParam) + if replicaMacro == "" { + replicaMacro = "{replica}" + } + return replicaMacro +} + + +func (drv *Driver) zookeeperPath() string { + v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() + clusterMacro := drv.clusterMacro() + zookeeperPath := v.Get(ZooPathQueryParam) + if zookeeperPath == "" { + zookeeperPath = fmt.Sprintf("/clickhouse/tables/%s/{table}", clusterMacro) + } + return zookeeperPath +} + func (drv *Driver) databaseName() string { name := strings.TrimLeft(dbutil.MustParseURL(connectionString(drv.databaseURL)).Path, "/") if name == "" { diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index ffd7ee03..ba4a4c07 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -12,14 +12,18 @@ import ( "github.com/stretchr/testify/require" ) -func testClickHouseDriver(t *testing.T) *Driver { - u := dbutil.MustParseURL(os.Getenv("CLICKHOUSE_TEST_URL")) +func testClickHouseDriverUrl(t *testing.T, url string) *Driver { + u := dbutil.MustParseURL(url) drv, err := dbmate.New(u).Driver() require.NoError(t, err) return drv.(*Driver) } +func testClickHouseDriver(t *testing.T) *Driver { + return testClickHouseDriverUrl(t, os.Getenv("CLICKHOUSE_TEST_URL")) +} + func prepTestClickHouseDB(t *testing.T) *sql.DB { drv := testClickHouseDriver(t) @@ -69,6 +73,8 @@ func TestConnectionString(t *testing.T) { {"clickhouse://aaa:111@myhost/mydb?username=bbb&password=222", "clickhouse://bbb:222@myhost:9000/mydb"}, // custom parameters {"clickhouse://myhost/mydb?dial_timeout=200ms", "clickhouse://myhost:9000/mydb?dial_timeout=200ms"}, + // on_cluster parameter + {"clickhouse://myhost/mydb?on_cluster=true", "clickhouse://myhost:9000/mydb?on_cluster=true"}, } for _, c := range cases { @@ -82,6 +88,94 @@ func TestConnectionString(t *testing.T) { } } +func TestOnCluster(t *testing.T) { + cases := []struct { + input string + expected bool + }{ + // param not supplied + {"clickhouse://myhost:9000", false}, + // empty on_cluster parameter + {"clickhouse://myhost:9000?on_cluster", true}, + // true on_cluster parameter + {"clickhouse://myhost:9000?on_cluster=true", true}, + // any other value on_cluster parameter + {"clickhouse://myhost:9000?on_cluster=falsy", false}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriverUrl(t, c.input) + + actual := drv.onCluster() + require.Equal(t, c.expected, actual) + }) + } +} + +func TestClusterMacro(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // cluster_macro not supplied + {"clickhouse://myhost:9000", "{cluster}"}, + // cluster_macro supplied + {"clickhouse://myhost:9000?cluster_macro={cluster2}", "{cluster2}"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriverUrl(t, c.input) + + actual := drv.clusterMacro() + require.Equal(t, c.expected, actual) + }) + } +} + +func TestReplicaMacro(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // replica_macro not supplied + {"clickhouse://myhost:9000", "{replica}"}, + // replica_macro supplied + {"clickhouse://myhost:9000?replica_macro={replica2}", "{replica2}"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriverUrl(t, c.input) + + actual := drv.replicaMacro() + require.Equal(t, c.expected, actual) + }) + } +} + +func TestZookeeperPath(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // zoo_path not supplied + {"clickhouse://myhost:9000", "/clickhouse/tables/{cluster}/{table}"}, + // zoo_path supplied + {"clickhouse://myhost:9000?zoo_path=/zk/path/tables", "/zk/path/tables"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriverUrl(t, c.input) + + actual := drv.zookeeperPath() + require.Equal(t, c.expected, actual) + }) + } +} + func TestClickHouseCreateDropDatabase(t *testing.T) { drv := testClickHouseDriver(t) From e9ecbfec68a4525242aefc2e2b28166d120b5122 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Thu, 6 Apr 2023 23:12:35 +0300 Subject: [PATCH 02/34] ran golangci --- pkg/driver/clickhouse/clickhouse.go | 11 ++++------- pkg/driver/clickhouse/clickhouse_test.go | 12 ++++++------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 1e2a060f..b2968727 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -17,8 +17,8 @@ import ( ) const ( - OnClusterQueryParam = "on_cluster" - ZooPathQueryParam = "zoo_path" + OnClusterQueryParam = "on_cluster" + ZooPathQueryParam = "zoo_path" ClusterMacroQueryParam = "cluster_macro" ReplicaMacroQueryParam = "replica_macro" ) @@ -104,13 +104,12 @@ func (drv *Driver) openClickHouseDB() (*sql.DB, error) { func (drv *Driver) onCluster() bool { v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() - hasOnCluster := v.Has(OnClusterQueryParam) - onClusterValue := v.Get(OnClusterQueryParam) + hasOnCluster := v.Has(OnClusterQueryParam) + onClusterValue := v.Get(OnClusterQueryParam) onCluster := hasOnCluster && (onClusterValue == "" || onClusterValue == "true") return onCluster } - func (drv *Driver) clusterMacro() string { v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() clusterMacro := v.Get(ClusterMacroQueryParam) @@ -120,7 +119,6 @@ func (drv *Driver) clusterMacro() string { return clusterMacro } - func (drv *Driver) replicaMacro() string { v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() replicaMacro := v.Get(ReplicaMacroQueryParam) @@ -130,7 +128,6 @@ func (drv *Driver) replicaMacro() string { return replicaMacro } - func (drv *Driver) zookeeperPath() string { v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() clusterMacro := drv.clusterMacro() diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index ba4a4c07..445ded01 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -func testClickHouseDriverUrl(t *testing.T, url string) *Driver { +func testClickHouseDriverURL(t *testing.T, url string) *Driver { u := dbutil.MustParseURL(url) drv, err := dbmate.New(u).Driver() require.NoError(t, err) @@ -21,7 +21,7 @@ func testClickHouseDriverUrl(t *testing.T, url string) *Driver { } func testClickHouseDriver(t *testing.T) *Driver { - return testClickHouseDriverUrl(t, os.Getenv("CLICKHOUSE_TEST_URL")) + return testClickHouseDriverURL(t, os.Getenv("CLICKHOUSE_TEST_URL")) } func prepTestClickHouseDB(t *testing.T) *sql.DB { @@ -105,7 +105,7 @@ func TestOnCluster(t *testing.T) { for _, c := range cases { t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverUrl(t, c.input) + drv := testClickHouseDriverURL(t, c.input) actual := drv.onCluster() require.Equal(t, c.expected, actual) @@ -126,7 +126,7 @@ func TestClusterMacro(t *testing.T) { for _, c := range cases { t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverUrl(t, c.input) + drv := testClickHouseDriverURL(t, c.input) actual := drv.clusterMacro() require.Equal(t, c.expected, actual) @@ -147,7 +147,7 @@ func TestReplicaMacro(t *testing.T) { for _, c := range cases { t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverUrl(t, c.input) + drv := testClickHouseDriverURL(t, c.input) actual := drv.replicaMacro() require.Equal(t, c.expected, actual) @@ -168,7 +168,7 @@ func TestZookeeperPath(t *testing.T) { for _, c := range cases { t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverUrl(t, c.input) + drv := testClickHouseDriverURL(t, c.input) actual := drv.zookeeperPath() require.Equal(t, c.expected, actual) From 6183cd3b0b3eec732d18a1f69176cd0f252a89b6 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Thu, 6 Apr 2023 23:29:36 +0300 Subject: [PATCH 03/34] Added onClusterClause and used it on create and drop database --- pkg/driver/clickhouse/clickhouse.go | 16 ++++++++++++++-- pkg/driver/clickhouse/clickhouse_test.go | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index b2968727..c3a01dda 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -138,6 +138,14 @@ func (drv *Driver) zookeeperPath() string { return zookeeperPath } +func (drv *Driver) onClusterClause() string{ + clusterClause := "" + if drv.onCluster() { + clusterClause = fmt.Sprintf(" ON CLUSTER '%s'", drv.clusterMacro()) + } + return clusterClause +} + func (drv *Driver) databaseName() string { name := strings.TrimLeft(dbutil.MustParseURL(connectionString(drv.databaseURL)).Path, "/") if name == "" { @@ -169,7 +177,9 @@ func (drv *Driver) CreateDatabase() error { } defer dbutil.MustClose(db) - _, err = db.Exec("create database " + drv.quoteIdentifier(name)) + q := fmt.Sprintf("CREATE DATABASE %s%s", drv.quoteIdentifier(name), drv.onClusterClause()) + + _, err = db.Exec(q) return err } @@ -185,7 +195,9 @@ func (drv *Driver) DropDatabase() error { } defer dbutil.MustClose(db) - _, err = db.Exec("drop database if exists " + drv.quoteIdentifier(name)) + q := fmt.Sprintf("DROP DATABASE IF EXISTS %s%s", drv.quoteIdentifier(name), drv.onClusterClause()) + + _, err = db.Exec(q) return err } diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index 445ded01..78155abe 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -176,6 +176,29 @@ func TestZookeeperPath(t *testing.T) { } } +func TestOnClusterClause(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // not on cluster + {"clickhouse://myhost:9000", ""}, + // on_cluster supplied + {"clickhouse://myhost:9000?on_cluster", " ON CLUSTER '{cluster}'"}, + // on_cluster with supplied macro + {"clickhouse://myhost:9000?on_cluster&cluster_macro={cluster2}", " ON CLUSTER '{cluster2}'"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriverURL(t, c.input) + + actual := drv.onClusterClause() + require.Equal(t, c.expected, actual) + }) + } +} + func TestClickHouseCreateDropDatabase(t *testing.T) { drv := testClickHouseDriver(t) From 5b9f219d81fb1f576b3db359f0c97e40db48b42c Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Fri, 7 Apr 2023 00:36:34 +0300 Subject: [PATCH 04/34] Refactored the cluster params to a new file --- pkg/driver/clickhouse/clickhouse.go | 50 +-------- pkg/driver/clickhouse/clickhouse_test.go | 133 ++++++++--------------- 2 files changed, 49 insertions(+), 134 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index c3a01dda..248118d8 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -16,13 +16,6 @@ import ( "github.com/ClickHouse/clickhouse-go/v2" ) -const ( - OnClusterQueryParam = "on_cluster" - ZooPathQueryParam = "zoo_path" - ClusterMacroQueryParam = "cluster_macro" - ReplicaMacroQueryParam = "replica_macro" -) - func init() { dbmate.RegisterDriver(NewDriver, "clickhouse") } @@ -32,6 +25,7 @@ type Driver struct { migrationsTableName string databaseURL *url.URL log io.Writer + clusterParameters *ClusterParameters } // NewDriver initializes the driver @@ -40,9 +34,11 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver { migrationsTableName: config.MigrationsTableName, databaseURL: config.DatabaseURL, log: config.Log, + clusterParameters: ClusterParametersFromURL(config.DatabaseURL), } } + func connectionString(initialURL *url.URL) string { // clone url u := dbutil.MustParseURL(initialURL.String()) @@ -102,46 +98,10 @@ func (drv *Driver) openClickHouseDB() (*sql.DB, error) { return sql.Open("clickhouse", clickhouseURL.String()) } -func (drv *Driver) onCluster() bool { - v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() - hasOnCluster := v.Has(OnClusterQueryParam) - onClusterValue := v.Get(OnClusterQueryParam) - onCluster := hasOnCluster && (onClusterValue == "" || onClusterValue == "true") - return onCluster -} - -func (drv *Driver) clusterMacro() string { - v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() - clusterMacro := v.Get(ClusterMacroQueryParam) - if clusterMacro == "" { - clusterMacro = "{cluster}" - } - return clusterMacro -} - -func (drv *Driver) replicaMacro() string { - v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() - replicaMacro := v.Get(ReplicaMacroQueryParam) - if replicaMacro == "" { - replicaMacro = "{replica}" - } - return replicaMacro -} - -func (drv *Driver) zookeeperPath() string { - v := dbutil.MustParseURL(connectionString(drv.databaseURL)).Query() - clusterMacro := drv.clusterMacro() - zookeeperPath := v.Get(ZooPathQueryParam) - if zookeeperPath == "" { - zookeeperPath = fmt.Sprintf("/clickhouse/tables/%s/{table}", clusterMacro) - } - return zookeeperPath -} - func (drv *Driver) onClusterClause() string{ clusterClause := "" - if drv.onCluster() { - clusterClause = fmt.Sprintf(" ON CLUSTER '%s'", drv.clusterMacro()) + if drv.clusterParameters.OnCluster { + clusterClause = fmt.Sprintf(" ON CLUSTER '%s'", drv.clusterParameters.ClusterMacro) } return clusterClause } diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index 78155abe..7da0aa7e 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -2,6 +2,7 @@ package clickhouse import ( "database/sql" + "fmt" "net/url" "os" "testing" @@ -24,6 +25,12 @@ func testClickHouseDriver(t *testing.T) *Driver { return testClickHouseDriverURL(t, os.Getenv("CLICKHOUSE_TEST_URL")) } +func testClickHouseDriverOnCluster(t *testing.T) *Driver { + os.Setenv("CLICKHOUSE_TEST_URL", "clickhouse://localhost:9000/dbmate_test") + u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_TEST_URL")) + return testClickHouseDriverURL(t, u) +} + func prepTestClickHouseDB(t *testing.T) *sql.DB { drv := testClickHouseDriver(t) @@ -88,119 +95,67 @@ func TestConnectionString(t *testing.T) { } } -func TestOnCluster(t *testing.T) { - cases := []struct { - input string - expected bool - }{ - // param not supplied - {"clickhouse://myhost:9000", false}, - // empty on_cluster parameter - {"clickhouse://myhost:9000?on_cluster", true}, - // true on_cluster parameter - {"clickhouse://myhost:9000?on_cluster=true", true}, - // any other value on_cluster parameter - {"clickhouse://myhost:9000?on_cluster=falsy", false}, - } - - for _, c := range cases { - t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverURL(t, c.input) - - actual := drv.onCluster() - require.Equal(t, c.expected, actual) - }) - } -} - -func TestClusterMacro(t *testing.T) { +func TestOnClusterClause(t *testing.T) { cases := []struct { input string expected string }{ - // cluster_macro not supplied - {"clickhouse://myhost:9000", "{cluster}"}, - // cluster_macro supplied - {"clickhouse://myhost:9000?cluster_macro={cluster2}", "{cluster2}"}, + // not on cluster + {"clickhouse://myhost:9000", ""}, + // on_cluster supplied + {"clickhouse://myhost:9000?on_cluster", " ON CLUSTER '{cluster}'"}, + // on_cluster with supplied macro + {"clickhouse://myhost:9000?on_cluster&cluster_macro={cluster2}", " ON CLUSTER '{cluster2}'"}, } for _, c := range cases { t.Run(c.input, func(t *testing.T) { drv := testClickHouseDriverURL(t, c.input) - actual := drv.clusterMacro() + actual := drv.onClusterClause() require.Equal(t, c.expected, actual) }) } } -func TestReplicaMacro(t *testing.T) { - cases := []struct { - input string - expected string - }{ - // replica_macro not supplied - {"clickhouse://myhost:9000", "{replica}"}, - // replica_macro supplied - {"clickhouse://myhost:9000?replica_macro={replica2}", "{replica2}"}, - } - - for _, c := range cases { - t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverURL(t, c.input) +func TestClickHouseCreateDropDatabase(t *testing.T) { + drv := testClickHouseDriver(t) - actual := drv.replicaMacro() - require.Equal(t, c.expected, actual) - }) - } -} + // drop any existing database + err := drv.DropDatabase() + require.NoError(t, err) -func TestZookeeperPath(t *testing.T) { - cases := []struct { - input string - expected string - }{ - // zoo_path not supplied - {"clickhouse://myhost:9000", "/clickhouse/tables/{cluster}/{table}"}, - // zoo_path supplied - {"clickhouse://myhost:9000?zoo_path=/zk/path/tables", "/zk/path/tables"}, - } + // create database + err = drv.CreateDatabase() + require.NoError(t, err) - for _, c := range cases { - t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverURL(t, c.input) + // check that database exists and we can connect to it + func() { + db, err := sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + defer dbutil.MustClose(db) - actual := drv.zookeeperPath() - require.Equal(t, c.expected, actual) - }) - } -} + err = db.Ping() + require.NoError(t, err) + }() -func TestOnClusterClause(t *testing.T) { - cases := []struct { - input string - expected string - }{ - // not on cluster - {"clickhouse://myhost:9000", ""}, - // on_cluster supplied - {"clickhouse://myhost:9000?on_cluster", " ON CLUSTER '{cluster}'"}, - // on_cluster with supplied macro - {"clickhouse://myhost:9000?on_cluster&cluster_macro={cluster2}", " ON CLUSTER '{cluster2}'"}, - } + // drop the database + err = drv.DropDatabase() + require.NoError(t, err) - for _, c := range cases { - t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverURL(t, c.input) + // check that database no longer exists + func() { + db, err := sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + defer dbutil.MustClose(db) - actual := drv.onClusterClause() - require.Equal(t, c.expected, actual) - }) - } + err = db.Ping() + require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") + }() } -func TestClickHouseCreateDropDatabase(t *testing.T) { - drv := testClickHouseDriver(t) +func TestClickHouseCreateDropDatabaseOnCluster(t *testing.T) { + drv := testClickHouseDriverOnCluster(t) // drop any existing database err := drv.DropDatabase() From 81e90d20881149891e6b0f0e90157ceac15bff42 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Fri, 7 Apr 2023 12:00:55 +0300 Subject: [PATCH 05/34] Refactored the cluster params to a new file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 09835820..a653472a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /vendor dist node_modules +.vscode From 47d29ca051ababb5b7c518cfd921db317f17a94b Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Fri, 7 Apr 2023 12:01:21 +0300 Subject: [PATCH 06/34] Refactored the cluster params to a new file --- pkg/driver/clickhouse/cluster_parameters.go | 78 +++++++++++++++ .../clickhouse/cluster_parameters_test.go | 99 +++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 pkg/driver/clickhouse/cluster_parameters.go create mode 100644 pkg/driver/clickhouse/cluster_parameters_test.go diff --git a/pkg/driver/clickhouse/cluster_parameters.go b/pkg/driver/clickhouse/cluster_parameters.go new file mode 100644 index 00000000..6c1dfa33 --- /dev/null +++ b/pkg/driver/clickhouse/cluster_parameters.go @@ -0,0 +1,78 @@ +package clickhouse + +import ( + "fmt" + "net/url" +) + +const ( + OnClusterQueryParam = "on_cluster" + ZooPathQueryParam = "zoo_path" + ClusterMacroQueryParam = "cluster_macro" + ReplicaMacroQueryParam = "replica_macro" +) + +type ClusterParameters struct { + OnCluster bool + ZooPath string + ClusterMacro string + ReplicaMacro string +} + +func ClusterParametersFromURL(u *url.URL) *ClusterParameters { + onCluster := extractOnCluster(u) + clusterMacro := extractClusterMacro(u) + replicaMacro := extractReplicaMacro(u) + zookeeperPath := extractZookeeperPath(u) + + r := &ClusterParameters{ + OnCluster: onCluster, + ZooPath: clusterMacro, + ClusterMacro: replicaMacro, + ReplicaMacro: zookeeperPath, + } + + v := u.Query() + v.Del(OnClusterQueryParam) + v.Del(ClusterMacroQueryParam) + v.Del(ReplicaMacroQueryParam) + v.Del(ZooPathQueryParam) + + return r +} + +func extractOnCluster(u *url.URL) bool { + v := u.Query() + hasOnCluster := v.Has(OnClusterQueryParam) + onClusterValue := v.Get(OnClusterQueryParam) + onCluster := hasOnCluster && (onClusterValue == "" || onClusterValue == "true") + return onCluster +} + +func extractClusterMacro(u *url.URL) string { + v := u.Query() + clusterMacro := v.Get(ClusterMacroQueryParam) + if clusterMacro == "" { + clusterMacro = "{cluster}" + } + return clusterMacro +} + +func extractReplicaMacro(u *url.URL) string { + v := u.Query() + replicaMacro := v.Get(ReplicaMacroQueryParam) + if replicaMacro == "" { + replicaMacro = "{replica}" + } + return replicaMacro +} + +func extractZookeeperPath(u *url.URL) string { + v := u.Query() + clusterMacro := extractClusterMacro(u) + zookeeperPath := v.Get(ZooPathQueryParam) + if zookeeperPath == "" { + zookeeperPath = fmt.Sprintf("/clickhouse/tables/%s/{table}", clusterMacro) + } + return zookeeperPath +} diff --git a/pkg/driver/clickhouse/cluster_parameters_test.go b/pkg/driver/clickhouse/cluster_parameters_test.go new file mode 100644 index 00000000..577fc439 --- /dev/null +++ b/pkg/driver/clickhouse/cluster_parameters_test.go @@ -0,0 +1,99 @@ +package clickhouse + +import ( + + "testing" + + "github.com/amacneil/dbmate/v2/pkg/dbutil" + "github.com/stretchr/testify/require" +) + + +func TestOnCluster(t *testing.T) { + cases := []struct { + input string + expected bool + }{ + // param not supplied + {"clickhouse://myhost:9000", false}, + // empty on_cluster parameter + {"clickhouse://myhost:9000?on_cluster", true}, + // true on_cluster parameter + {"clickhouse://myhost:9000?on_cluster=true", true}, + // any other value on_cluster parameter + {"clickhouse://myhost:9000?on_cluster=falsy", false}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + u := dbutil.MustParseURL(c.input) + + actual := extractOnCluster(u) + require.Equal(t, c.expected, actual) + }) + } +} + + +func TestClusterMacro(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // cluster_macro not supplied + {"clickhouse://myhost:9000", "{cluster}"}, + // cluster_macro supplied + {"clickhouse://myhost:9000?cluster_macro={cluster2}", "{cluster2}"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + u := dbutil.MustParseURL(c.input) + + actual := extractClusterMacro(u) + require.Equal(t, c.expected, actual) + }) + } +} + +func TestReplicaMacro(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // replica_macro not supplied + {"clickhouse://myhost:9000", "{replica}"}, + // replica_macro supplied + {"clickhouse://myhost:9000?replica_macro={replica2}", "{replica2}"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + u := dbutil.MustParseURL(c.input) + + actual := extractReplicaMacro(u) + require.Equal(t, c.expected, actual) + }) + } +} + +func TestZookeeperPath(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // zoo_path not supplied + {"clickhouse://myhost:9000", "/clickhouse/tables/{cluster}/{table}"}, + // zoo_path supplied + {"clickhouse://myhost:9000?zoo_path=/zk/path/tables", "/zk/path/tables"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + u := dbutil.MustParseURL(c.input) + + actual := extractZookeeperPath(u) + require.Equal(t, c.expected, actual) + }) + } +} From 5148c9eb701ac76cdcf0ea210407a428746db827 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Fri, 7 Apr 2023 12:34:07 +0300 Subject: [PATCH 07/34] fix cluster params set + create separate test file for cluster set up --- pkg/driver/clickhouse/clickhouse_test.go | 58 --------------------- pkg/driver/clickhouse/cluster_parameters.go | 6 +-- 2 files changed, 3 insertions(+), 61 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index 7da0aa7e..9da23fbf 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -95,29 +95,6 @@ func TestConnectionString(t *testing.T) { } } -func TestOnClusterClause(t *testing.T) { - cases := []struct { - input string - expected string - }{ - // not on cluster - {"clickhouse://myhost:9000", ""}, - // on_cluster supplied - {"clickhouse://myhost:9000?on_cluster", " ON CLUSTER '{cluster}'"}, - // on_cluster with supplied macro - {"clickhouse://myhost:9000?on_cluster&cluster_macro={cluster2}", " ON CLUSTER '{cluster2}'"}, - } - - for _, c := range cases { - t.Run(c.input, func(t *testing.T) { - drv := testClickHouseDriverURL(t, c.input) - - actual := drv.onClusterClause() - require.Equal(t, c.expected, actual) - }) - } -} - func TestClickHouseCreateDropDatabase(t *testing.T) { drv := testClickHouseDriver(t) @@ -154,41 +131,6 @@ func TestClickHouseCreateDropDatabase(t *testing.T) { }() } -func TestClickHouseCreateDropDatabaseOnCluster(t *testing.T) { - drv := testClickHouseDriverOnCluster(t) - - // drop any existing database - err := drv.DropDatabase() - require.NoError(t, err) - - // create database - err = drv.CreateDatabase() - require.NoError(t, err) - - // check that database exists and we can connect to it - func() { - db, err := sql.Open("clickhouse", drv.databaseURL.String()) - require.NoError(t, err) - defer dbutil.MustClose(db) - - err = db.Ping() - require.NoError(t, err) - }() - - // drop the database - err = drv.DropDatabase() - require.NoError(t, err) - - // check that database no longer exists - func() { - db, err := sql.Open("clickhouse", drv.databaseURL.String()) - require.NoError(t, err) - defer dbutil.MustClose(db) - - err = db.Ping() - require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") - }() -} func TestClickHouseDumpSchema(t *testing.T) { drv := testClickHouseDriver(t) diff --git a/pkg/driver/clickhouse/cluster_parameters.go b/pkg/driver/clickhouse/cluster_parameters.go index 6c1dfa33..ef4ce3e9 100644 --- a/pkg/driver/clickhouse/cluster_parameters.go +++ b/pkg/driver/clickhouse/cluster_parameters.go @@ -27,9 +27,9 @@ func ClusterParametersFromURL(u *url.URL) *ClusterParameters { r := &ClusterParameters{ OnCluster: onCluster, - ZooPath: clusterMacro, - ClusterMacro: replicaMacro, - ReplicaMacro: zookeeperPath, + ZooPath: zookeeperPath, + ClusterMacro: clusterMacro, + ReplicaMacro: replicaMacro, } v := u.Query() From a9b6e6d38075bb18567e2f97a42f1acc487cf207 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Fri, 7 Apr 2023 12:34:22 +0300 Subject: [PATCH 08/34] fix cluster params set + create separate test file for cluster set up --- .../clickhouse/clickhouse_cluster_test.go | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 pkg/driver/clickhouse/clickhouse_cluster_test.go diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go new file mode 100644 index 00000000..e63fd314 --- /dev/null +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -0,0 +1,69 @@ +package clickhouse + +import ( + "database/sql" + "testing" + + "github.com/amacneil/dbmate/v2/pkg/dbutil" + + "github.com/stretchr/testify/require" +) + +func TestOnClusterClause(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // not on cluster + {"clickhouse://myhost:9000", ""}, + // on_cluster supplied + {"clickhouse://myhost:9000?on_cluster", " ON CLUSTER '{cluster}'"}, + // on_cluster with supplied macro + {"clickhouse://myhost:9000?on_cluster&cluster_macro={cluster2}", " ON CLUSTER '{cluster2}'"}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriverURL(t, c.input) + + actual := drv.onClusterClause() + require.Equal(t, c.expected, actual) + }) + } +} + +func TestClickHouseCreateDropDatabaseOnCluster(t *testing.T) { + drv := testClickHouseDriverOnCluster(t) + + // drop any existing database + err := drv.DropDatabase() + require.NoError(t, err) + + // create database + err = drv.CreateDatabase() + require.NoError(t, err) + + // check that database exists and we can connect to it + func() { + db, err := sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + defer dbutil.MustClose(db) + + err = db.Ping() + require.NoError(t, err) + }() + + // drop the database + err = drv.DropDatabase() + require.NoError(t, err) + + // check that database no longer exists + func() { + db, err := sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + defer dbutil.MustClose(db) + + err = db.Ping() + require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") + }() +} From 046adde58b59d2807f8376fabed8cbff4de617d0 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 00:25:00 +0300 Subject: [PATCH 09/34] Added containers and configs for cluster --- docker-compose.yml | 28 + .../cluster_config/ch-cluster-01/config.xml | 1289 +++++++++++++++++ .../cluster_config/ch-cluster-02/config.xml | 1289 +++++++++++++++++ 3 files changed, 2606 insertions(+) create mode 100644 pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml create mode 100644 pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml diff --git a/docker-compose.yml b/docker-compose.yml index ef80af87..bbff229a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,8 +10,12 @@ services: - mysql - postgres - clickhouse + - clickhouse-cluster-01 + - clickhouse-cluster-02 environment: CLICKHOUSE_TEST_URL: clickhouse://clickhouse:9000/dbmate_test + CLICKHOUSE_CLUSTER_01_TEST_URL: clickhouse://ch-cluster-01:9000/dbmate_test + CLICKHOUSE_CLUSTER_02_TEST_URL: clickhouse://ch-cluster-02:9000/dbmate_test MYSQL_TEST_URL: mysql://root:root@mysql/dbmate_test POSTGRES_TEST_URL: postgres://postgres:postgres@postgres/dbmate_test?sslmode=disable SQLITE_TEST_URL: sqlite3:/tmp/dbmate_test.sqlite3 @@ -35,3 +39,27 @@ services: clickhouse: image: clickhouse/clickhouse-server:22.8 + + zookeeper: + image: zookeeper + hostname: zookeeper + + clickhouse-cluster-01: + image: clickhouse/clickhouse-server:22.8 + hostname: ch-cluster-01 + environment: + - CLICKHOUSE_CONFIG=/etc/clickhouse-server/config.xml + depends_on: + - zookeeper + volumes: + - ./pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml:/etc/clickhouse-server/config.xml + + clickhouse-cluster-02: + image: clickhouse/clickhouse-server:22.8 + hostname: ch-cluster-02 + environment: + - CLICKHOUSE_CONFIG=/etc/clickhouse-server/config.xml + depends_on: + - zookeeper + volumes: + - ./pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml:/etc/clickhouse-server/config.xml diff --git a/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml b/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml new file mode 100644 index 00000000..36a7965f --- /dev/null +++ b/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml @@ -0,0 +1,1289 @@ + + + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + + 1000M + 10 + + + + + + + + + + + + + + + + + + + + 8123 + + + 9000 + + + 9004 + + + 9005 + + + + + + + + + + + + 9009 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4096 + + + 3 + + + + + false + + + /path/to/ssl_cert_file + /path/to/ssl_key_file + + + false + + + /path/to/ssl_ca_cert_file + + + none + + + 0 + + + -1 + -1 + + + false + + + + + + + + + + none + true + true + sslv2,sslv3 + true + + + + true + true + sslv2,sslv3 + true + + + + RejectCertificateHandler + + + + + + + + + 0 + + + 100 + + + 0 + + + + 10000 + + + + + + 0.9 + + + 4194304 + + + 0 + + + + + + 8589934592 + + + 5368709120 + + + + 1000 + + + 134217728 + + + 10000 + + + /var/lib/clickhouse/ + + + + + + + /var/lib/clickhouse/tmp/ + + + + ` + + + + + + /var/lib/clickhouse/user_files/ + + + + + + + + + + + + + users.xml + + + + /var/lib/clickhouse/access/ + + + + + + + + false + + + false + + + false + + + false + + + + default + + + + + + + + + + + + default + + + + + + + + + true + + + false + + ' | sed -e 's|.*>\(.*\)<.*|\1|') + wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge_$PKG_VER-1_all.deb + apt install --no-install-recommends -f ./clickhouse-jdbc-bridge_$PKG_VER-1_all.deb + clickhouse-jdbc-bridge & + + * [CentOS/RHEL] + export MVN_URL=https://repo1.maven.org/maven2/com/clickhouse/clickhouse-jdbc-bridge/ + export PKG_VER=$(curl -sL $MVN_URL/maven-metadata.xml | grep '' | sed -e 's|.*>\(.*\)<.*|\1|') + wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm + yum localinstall -y clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm + clickhouse-jdbc-bridge & + + Please refer to https://github.com/ClickHouse/clickhouse-jdbc-bridge#usage for more information. + ]]> + + + + + + + + + + + true + + ch-cluster-01 + 9000 + + + + + + true + + ch-cluster-02 + 9000 + + + + + + + + + + + + + + + + + + + + zookeeper + 2181 + + + + + + + + cluster-01 + shard-01 + ch_cluster-01 + + + + + + 3600 + + + + 3600 + + + 60 + + + + + + + + + + + + + system + query_log
+ + toYYYYMM(event_date) + + + + + + 7500 +
+ + + + system + trace_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + system + query_thread_log
+ toYYYYMM(event_date) + 7500 +
+ + + + system + query_views_log
+ toYYYYMM(event_date) + 7500 +
+ + + + system + part_log
+ toYYYYMM(event_date) + 7500 +
+ + + + + + system + metric_log
+ 7500 + 1000 +
+ + + + system + asynchronous_metric_log
+ + 7000 +
+ + + + + + engine MergeTree + partition by toYYYYMM(finish_date) + order by (finish_date, finish_time_us, trace_id) + + system + opentelemetry_span_log
+ 7500 +
+ + + + + system + crash_log
+ + + 1000 +
+ + + + + + + system + processors_profile_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + + + + + + *_dictionary.xml + + + *_function.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /clickhouse/task_queue/ddl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + click_cost + any + + 0 + 3600 + + + 86400 + 60 + + + + max + + 0 + 60 + + + 3600 + 300 + + + 86400 + 3600 + + + + + + /var/lib/clickhouse/format_schemas/ + + + + + hide encrypt/decrypt arguments + ((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\) + + \1(???) + + + + + + + + + + false + + false + + + https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277 + + + + + + + + + + + + +
diff --git a/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml b/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml new file mode 100644 index 00000000..41c164ff --- /dev/null +++ b/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml @@ -0,0 +1,1289 @@ + + + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + + 1000M + 10 + + + + + + + + + + + + + + + + + + + + 8123 + + + 9000 + + + 9004 + + + 9005 + + + + + + + + + + + + 9009 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4096 + + + 3 + + + + + false + + + /path/to/ssl_cert_file + /path/to/ssl_key_file + + + false + + + /path/to/ssl_ca_cert_file + + + none + + + 0 + + + -1 + -1 + + + false + + + + + + + + + + none + true + true + sslv2,sslv3 + true + + + + true + true + sslv2,sslv3 + true + + + + RejectCertificateHandler + + + + + + + + + 0 + + + 100 + + + 0 + + + + 10000 + + + + + + 0.9 + + + 4194304 + + + 0 + + + + + + 8589934592 + + + 5368709120 + + + + 1000 + + + 134217728 + + + 10000 + + + /var/lib/clickhouse/ + + + + + + + /var/lib/clickhouse/tmp/ + + + + ` + + + + + + /var/lib/clickhouse/user_files/ + + + + + + + + + + + + + users.xml + + + + /var/lib/clickhouse/access/ + + + + + + + + false + + + false + + + false + + + false + + + + default + + + + + + + + + + + + default + + + + + + + + + true + + + false + + ' | sed -e 's|.*>\(.*\)<.*|\1|') + wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge_$PKG_VER-1_all.deb + apt install --no-install-recommends -f ./clickhouse-jdbc-bridge_$PKG_VER-1_all.deb + clickhouse-jdbc-bridge & + + * [CentOS/RHEL] + export MVN_URL=https://repo1.maven.org/maven2/com/clickhouse/clickhouse-jdbc-bridge/ + export PKG_VER=$(curl -sL $MVN_URL/maven-metadata.xml | grep '' | sed -e 's|.*>\(.*\)<.*|\1|') + wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm + yum localinstall -y clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm + clickhouse-jdbc-bridge & + + Please refer to https://github.com/ClickHouse/clickhouse-jdbc-bridge#usage for more information. + ]]> + + + + + + + + + + + true + + ch-cluster-01 + 9000 + + + + + + true + + ch-cluster-02 + 9000 + + + + + + + + + + + + + + + + + + + + zookeeper + 2181 + + + + + + + + cluster-01 + shard-02 + ch_cluster-02 + + + + + + 3600 + + + + 3600 + + + 60 + + + + + + + + + + + + + system + query_log
+ + toYYYYMM(event_date) + + + + + + 7500 +
+ + + + system + trace_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + system + query_thread_log
+ toYYYYMM(event_date) + 7500 +
+ + + + system + query_views_log
+ toYYYYMM(event_date) + 7500 +
+ + + + system + part_log
+ toYYYYMM(event_date) + 7500 +
+ + + + + + system + metric_log
+ 7500 + 1000 +
+ + + + system + asynchronous_metric_log
+ + 7000 +
+ + + + + + engine MergeTree + partition by toYYYYMM(finish_date) + order by (finish_date, finish_time_us, trace_id) + + system + opentelemetry_span_log
+ 7500 +
+ + + + + system + crash_log
+ + + 1000 +
+ + + + + + + system + processors_profile_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + + + + + + *_dictionary.xml + + + *_function.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /clickhouse/task_queue/ddl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + click_cost + any + + 0 + 3600 + + + 86400 + 60 + + + + max + + 0 + 60 + + + 3600 + 300 + + + 86400 + 3600 + + + + + + /var/lib/clickhouse/format_schemas/ + + + + + hide encrypt/decrypt arguments + ((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\) + + \1(???) + + + + + + + + + + false + + false + + + https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277 + + + + + + + + + + + + +
From 31754c25aa0ad110452c2e81b3fcbfb4567c998f Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 11:36:41 +0300 Subject: [PATCH 10/34] reduced config files --- .../cluster_config/ch-cluster-01/config.xml | 1162 ----------------- .../cluster_config/ch-cluster-02/config.xml | 1162 ----------------- 2 files changed, 2324 deletions(-) diff --git a/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml b/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml index 36a7965f..c08362ee 100644 --- a/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml +++ b/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml @@ -7,713 +7,56 @@ --> - trace /var/log/clickhouse-server/clickhouse-server.log /var/log/clickhouse-server/clickhouse-server.err.log - 1000M 10 - - - - - - - - - - - - - - - - - 8123 - - 9000 - - - 9004 - - - 9005 - - - - - - - - - - - 9009 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4096 - - 3 - - - - - false - - - /path/to/ssl_cert_file - /path/to/ssl_key_file - - - false - - - /path/to/ssl_ca_cert_file - - - none - - - 0 - - - -1 - -1 - - - false - - - - - - - - - - none - true - true - sslv2,sslv3 - true - - - - true - true - sslv2,sslv3 - true - - - - RejectCertificateHandler - - - - - - - - 0 - - 100 - - 0 - - - 10000 - - - - - 0.9 - - 4194304 - - 0 - - - - - 8589934592 - - 5368709120 - - - 1000 - - 134217728 - - 10000 - /var/lib/clickhouse/ - - - - - - /var/lib/clickhouse/tmp/ - - - - ` - - - - - /var/lib/clickhouse/user_files/ - - - - - - - - - users.xml - /var/lib/clickhouse/access/ - - - false - - false - - false - - false - default - - - - - - - - - - - default - - - - - - - - true - - false - - ' | sed -e 's|.*>\(.*\)<.*|\1|') - wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge_$PKG_VER-1_all.deb - apt install --no-install-recommends -f ./clickhouse-jdbc-bridge_$PKG_VER-1_all.deb - clickhouse-jdbc-bridge & - - * [CentOS/RHEL] - export MVN_URL=https://repo1.maven.org/maven2/com/clickhouse/clickhouse-jdbc-bridge/ - export PKG_VER=$(curl -sL $MVN_URL/maven-metadata.xml | grep '' | sed -e 's|.*>\(.*\)<.*|\1|') - wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm - yum localinstall -y clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm - clickhouse-jdbc-bridge & - - Please refer to https://github.com/ClickHouse/clickhouse-jdbc-bridge#usage for more information. - ]]> - - - - - - - - - - - - zookeeper @@ -783,13 +93,6 @@ - - - cluster-01 shard-01 @@ -797,493 +100,28 @@ - - 3600 - - - 3600 - - 60 - - - - - - - - - - system query_log
- toYYYYMM(event_date) - - - - 7500
- - - system - trace_log
- - toYYYYMM(event_date) - 7500 -
- - - - system - query_thread_log
- toYYYYMM(event_date) - 7500 -
- - - - system - query_views_log
- toYYYYMM(event_date) - 7500 -
- - - - system - part_log
- toYYYYMM(event_date) - 7500 -
- - - - - - system - metric_log
- 7500 - 1000 -
- - - - system - asynchronous_metric_log
- - 7000 -
- - - - - - engine MergeTree - partition by toYYYYMM(finish_date) - order by (finish_date, finish_time_us, trace_id) - - system - opentelemetry_span_log
- 7500 -
- - - - - system - crash_log
- - - 1000 -
- - - - - - - system - processors_profile_log
- - toYYYYMM(event_date) - 7500 -
- - - - - - - - *_dictionary.xml - - *_function.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - /clickhouse/task_queue/ddl - - - - - - - - - - - - - - - - - - - - - - - - - - - click_cost - any - - 0 - 3600 - - - 86400 - 60 - - - - max - - 0 - 60 - - - 3600 - 300 - - - 86400 - 3600 - - - - - /var/lib/clickhouse/format_schemas/ - - - - hide encrypt/decrypt arguments - ((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\) - - \1(???) - - - - - - - - - - false - - false - - - https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277 - - - - - - - - - - - -
diff --git a/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml b/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml index 41c164ff..281795e7 100644 --- a/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml +++ b/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml @@ -7,713 +7,56 @@ --> - trace /var/log/clickhouse-server/clickhouse-server.log /var/log/clickhouse-server/clickhouse-server.err.log - 1000M 10 - - - - - - - - - - - - - - - - - 8123 - - 9000 - - - 9004 - - - 9005 - - - - - - - - - - - 9009 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4096 - - 3 - - - - - false - - - /path/to/ssl_cert_file - /path/to/ssl_key_file - - - false - - - /path/to/ssl_ca_cert_file - - - none - - - 0 - - - -1 - -1 - - - false - - - - - - - - - - none - true - true - sslv2,sslv3 - true - - - - true - true - sslv2,sslv3 - true - - - - RejectCertificateHandler - - - - - - - - 0 - - 100 - - 0 - - - 10000 - - - - - 0.9 - - 4194304 - - 0 - - - - - 8589934592 - - 5368709120 - - - 1000 - - 134217728 - - 10000 - /var/lib/clickhouse/ - - - - - - /var/lib/clickhouse/tmp/ - - - - ` - - - - - /var/lib/clickhouse/user_files/ - - - - - - - - - users.xml - /var/lib/clickhouse/access/ - - - false - - false - - false - - false - default - - - - - - - - - - - default - - - - - - - - true - - false - - ' | sed -e 's|.*>\(.*\)<.*|\1|') - wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge_$PKG_VER-1_all.deb - apt install --no-install-recommends -f ./clickhouse-jdbc-bridge_$PKG_VER-1_all.deb - clickhouse-jdbc-bridge & - - * [CentOS/RHEL] - export MVN_URL=https://repo1.maven.org/maven2/com/clickhouse/clickhouse-jdbc-bridge/ - export PKG_VER=$(curl -sL $MVN_URL/maven-metadata.xml | grep '' | sed -e 's|.*>\(.*\)<.*|\1|') - wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm - yum localinstall -y clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm - clickhouse-jdbc-bridge & - - Please refer to https://github.com/ClickHouse/clickhouse-jdbc-bridge#usage for more information. - ]]> - - - - - - - - - - - - zookeeper @@ -783,13 +93,6 @@ - - - cluster-01 shard-02 @@ -797,493 +100,28 @@ - - 3600 - - - 3600 - - 60 - - - - - - - - - - system query_log
- toYYYYMM(event_date) - - - - 7500
- - - system - trace_log
- - toYYYYMM(event_date) - 7500 -
- - - - system - query_thread_log
- toYYYYMM(event_date) - 7500 -
- - - - system - query_views_log
- toYYYYMM(event_date) - 7500 -
- - - - system - part_log
- toYYYYMM(event_date) - 7500 -
- - - - - - system - metric_log
- 7500 - 1000 -
- - - - system - asynchronous_metric_log
- - 7000 -
- - - - - - engine MergeTree - partition by toYYYYMM(finish_date) - order by (finish_date, finish_time_us, trace_id) - - system - opentelemetry_span_log
- 7500 -
- - - - - system - crash_log
- - - 1000 -
- - - - - - - system - processors_profile_log
- - toYYYYMM(event_date) - 7500 -
- - - - - - - - *_dictionary.xml - - *_function.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - /clickhouse/task_queue/ddl - - - - - - - - - - - - - - - - - - - - - - - - - - - click_cost - any - - 0 - 3600 - - - 86400 - 60 - - - - max - - 0 - 60 - - - 3600 - 300 - - - 86400 - 3600 - - - - - /var/lib/clickhouse/format_schemas/ - - - - hide encrypt/decrypt arguments - ((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\) - - \1(???) - - - - - - - - - - false - - false - - - https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277 - - - - - - - - - - - -
From 0f5bb4f633d0c5369bb8b9bf8682cad4eb93f592 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 16:06:14 +0300 Subject: [PATCH 11/34] fix cluster params and separate cluster tests --- pkg/driver/clickhouse/clickhouse_cluster_test.go | 8 ++++++++ pkg/driver/clickhouse/clickhouse_test.go | 6 ------ pkg/driver/clickhouse/cluster_parameters.go | 12 +++++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index e63fd314..0418b33b 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -2,6 +2,8 @@ package clickhouse import ( "database/sql" + "fmt" + "os" "testing" "github.com/amacneil/dbmate/v2/pkg/dbutil" @@ -9,6 +11,12 @@ import ( "github.com/stretchr/testify/require" ) +func testClickHouseDriverOnCluster(t *testing.T) *Driver { + u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) + return testClickHouseDriverURL(t, u) +} + + func TestOnClusterClause(t *testing.T) { cases := []struct { input string diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index 9da23fbf..62745ffc 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -2,7 +2,6 @@ package clickhouse import ( "database/sql" - "fmt" "net/url" "os" "testing" @@ -25,11 +24,6 @@ func testClickHouseDriver(t *testing.T) *Driver { return testClickHouseDriverURL(t, os.Getenv("CLICKHOUSE_TEST_URL")) } -func testClickHouseDriverOnCluster(t *testing.T) *Driver { - os.Setenv("CLICKHOUSE_TEST_URL", "clickhouse://localhost:9000/dbmate_test") - u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_TEST_URL")) - return testClickHouseDriverURL(t, u) -} func prepTestClickHouseDB(t *testing.T) *sql.DB { drv := testClickHouseDriver(t) diff --git a/pkg/driver/clickhouse/cluster_parameters.go b/pkg/driver/clickhouse/cluster_parameters.go index ef4ce3e9..84a4552c 100644 --- a/pkg/driver/clickhouse/cluster_parameters.go +++ b/pkg/driver/clickhouse/cluster_parameters.go @@ -32,11 +32,13 @@ func ClusterParametersFromURL(u *url.URL) *ClusterParameters { ReplicaMacro: replicaMacro, } - v := u.Query() - v.Del(OnClusterQueryParam) - v.Del(ClusterMacroQueryParam) - v.Del(ReplicaMacroQueryParam) - v.Del(ZooPathQueryParam) + q := u.Query() + q.Del(OnClusterQueryParam) + q.Del(ClusterMacroQueryParam) + q.Del(ReplicaMacroQueryParam) + q.Del(ZooPathQueryParam) + + u.RawQuery = q.Encode() return r } From 909287b20498fac3f584d2caefcf6a624e8d672f Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 16:50:00 +0300 Subject: [PATCH 12/34] Set test to create and drop db on cluster --- .../clickhouse/clickhouse_cluster_test.go | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index 0418b33b..fe42c10d 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -11,11 +11,28 @@ import ( "github.com/stretchr/testify/require" ) -func testClickHouseDriverOnCluster(t *testing.T) *Driver { +func testClickHouseDriverCluster01(t *testing.T) *Driver { u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) return testClickHouseDriverURL(t, u) } +func testClickHouseDriverCluster02(t *testing.T) *Driver { + u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) + return testClickHouseDriverURL(t, u) +} + +func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool){ + db, err := sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + defer dbutil.MustClose(db) + + err = db.Ping() + if shouldExist{ + require.NoError(t, err) + } else { + require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") + } +} func TestOnClusterClause(t *testing.T) { cases := []struct { @@ -41,37 +58,28 @@ func TestOnClusterClause(t *testing.T) { } func TestClickHouseCreateDropDatabaseOnCluster(t *testing.T) { - drv := testClickHouseDriverOnCluster(t) + drv01 := testClickHouseDriverCluster01(t) + drv02 := testClickHouseDriverCluster02(t) // drop any existing database - err := drv.DropDatabase() + err := drv01.DropDatabase() require.NoError(t, err) // create database - err = drv.CreateDatabase() + err = drv01.CreateDatabase() require.NoError(t, err) // check that database exists and we can connect to it - func() { - db, err := sql.Open("clickhouse", drv.databaseURL.String()) - require.NoError(t, err) - defer dbutil.MustClose(db) - - err = db.Ping() - require.NoError(t, err) - }() + assertDatabaseExists(t, drv01, true) + // check that database exists on the other clickhouse node and we can connect to it + assertDatabaseExists(t, drv02, true) // drop the database - err = drv.DropDatabase() + err = drv01.DropDatabase() require.NoError(t, err) // check that database no longer exists - func() { - db, err := sql.Open("clickhouse", drv.databaseURL.String()) - require.NoError(t, err) - defer dbutil.MustClose(db) - - err = db.Ping() - require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") - }() + assertDatabaseExists(t, drv01, false) + // check that database no longer exists on the other clickhouse node + assertDatabaseExists(t, drv02, false) } From d9b8c4e53f780f95a359b1b97ce86371649d12e7 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 17:41:05 +0300 Subject: [PATCH 13/34] Added cluster logic to schema dump and migration table creation --- pkg/driver/clickhouse/clickhouse.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 248118d8..a2d657bd 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -164,7 +164,7 @@ func (drv *Driver) DropDatabase() error { func (drv *Driver) schemaDump(db *sql.DB, buf *bytes.Buffer, databaseName string) error { buf.WriteString("\n--\n-- Database schema\n--\n\n") - buf.WriteString("CREATE DATABASE IF NOT EXISTS " + drv.quoteIdentifier(databaseName) + ";\n\n") + buf.WriteString(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s%s;\n\n", drv.quoteIdentifier(databaseName), drv.onClusterClause())) tables, err := dbutil.QueryColumn(db, "show tables") if err != nil { @@ -265,15 +265,21 @@ func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) { // CreateMigrationsTable creates the schema migrations table func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { + + engineClause := "ReplacingMergeTree(ts)" + if drv.clusterParameters.OnCluster{ + engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree(%s, %s, ts)", drv.clusterParameters.ZooPath, drv.clusterParameters.ReplicaMacro) + } + _, err := db.Exec(fmt.Sprintf(` - create table if not exists %s ( + create table if not exists %s%s ( version String, ts DateTime default now(), applied UInt8 default 1 - ) engine = ReplacingMergeTree(ts) + ) engine = %s primary key version order by version - `, drv.quotedMigrationsTableName())) + `, drv.quotedMigrationsTableName(), drv.onClusterClause(), engineClause)) return err } From b80fbe2b7d613f600c295c4cfc8e592b0d1dbbe4 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 22:44:59 +0300 Subject: [PATCH 14/34] Created a utils file for common test functions --- .../clickhouse/clickhouse_cluster_test.go | 45 +++++++++++++++++++ pkg/driver/clickhouse/clickhouse_test.go | 44 +++--------------- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index fe42c10d..3c98f621 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -83,3 +83,48 @@ func TestClickHouseCreateDropDatabaseOnCluster(t *testing.T) { // check that database no longer exists on the other clickhouse node assertDatabaseExists(t, drv02, false) } + +func TestClickHouseDumpSchemaOnCluster(t *testing.T) { + drv := testClickHouseDriverCluster01(t) + drv.migrationsTableName = "test_migrations" + + // prepare database + db := prepTestClickHouseDB(t, drv) + defer dbutil.MustClose(db) + err := drv.CreateMigrationsTable(db) + require.NoError(t, err) + + // insert migration + tx, err := db.Begin() + require.NoError(t, err) + err = drv.InsertMigration(tx, "abc1") + require.NoError(t, err) + err = tx.Commit() + require.NoError(t, err) + tx, err = db.Begin() + require.NoError(t, err) + err = drv.InsertMigration(tx, "abc2") + require.NoError(t, err) + err = tx.Commit() + require.NoError(t, err) + + // DumpSchema should return schema + schema, err := drv.DumpSchema(db) + require.NoError(t, err) + require.Contains(t, string(schema), "CREATE TABLE "+drv.databaseName()+".test_migrations") + require.Contains(t, string(schema), "--\n"+ + "-- Dbmate schema migrations\n"+ + "--\n\n"+ + "INSERT INTO test_migrations (version) VALUES\n"+ + " ('abc1'),\n"+ + " ('abc2');\n") + + // DumpSchema should return error if command fails + drv.databaseURL.Path = "/fakedb" + db, err = sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + + schema, err = drv.DumpSchema(db) + require.Nil(t, schema) + require.EqualError(t, err, "code: 81, message: Database fakedb doesn't exist") +} diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index 62745ffc..c7d8e9cb 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -3,7 +3,6 @@ package clickhouse import ( "database/sql" "net/url" - "os" "testing" "github.com/amacneil/dbmate/v2/pkg/dbmate" @@ -12,37 +11,6 @@ import ( "github.com/stretchr/testify/require" ) -func testClickHouseDriverURL(t *testing.T, url string) *Driver { - u := dbutil.MustParseURL(url) - drv, err := dbmate.New(u).Driver() - require.NoError(t, err) - - return drv.(*Driver) -} - -func testClickHouseDriver(t *testing.T) *Driver { - return testClickHouseDriverURL(t, os.Getenv("CLICKHOUSE_TEST_URL")) -} - - -func prepTestClickHouseDB(t *testing.T) *sql.DB { - drv := testClickHouseDriver(t) - - // drop any existing database - err := drv.DropDatabase() - require.NoError(t, err) - - // create database - err = drv.CreateDatabase() - require.NoError(t, err) - - // connect database - db, err := sql.Open("clickhouse", drv.databaseURL.String()) - require.NoError(t, err) - - return db -} - func TestGetDriver(t *testing.T) { db := dbmate.New(dbutil.MustParseURL("clickhouse://")) drvInterface, err := db.Driver() @@ -131,7 +99,7 @@ func TestClickHouseDumpSchema(t *testing.T) { drv.migrationsTableName = "test_migrations" // prepare database - db := prepTestClickHouseDB(t) + db := prepTestClickHouseDB(t, drv) defer dbutil.MustClose(db) err := drv.CreateMigrationsTable(db) require.NoError(t, err) @@ -211,7 +179,7 @@ func TestClickHouseDatabaseExists_Error(t *testing.T) { func TestClickHouseCreateMigrationsTable(t *testing.T) { t.Run("default table", func(t *testing.T) { drv := testClickHouseDriver(t) - db := prepTestClickHouseDB(t) + db := prepTestClickHouseDB(t, drv) defer dbutil.MustClose(db) // migrations table should not exist @@ -250,7 +218,7 @@ func TestClickHouseCreateMigrationsTable(t *testing.T) { drv := testClickHouseDriver(t) drv.migrationsTableName = "testMigrations" - db := prepTestClickHouseDB(t) + db := prepTestClickHouseDB(t, drv) defer dbutil.MustClose(db) // migrations table should not exist @@ -290,7 +258,7 @@ func TestClickHouseSelectMigrations(t *testing.T) { drv := testClickHouseDriver(t) drv.migrationsTableName = "test_migrations" - db := prepTestClickHouseDB(t) + db := prepTestClickHouseDB(t, drv) defer dbutil.MustClose(db) err := drv.CreateMigrationsTable(db) @@ -327,7 +295,7 @@ func TestClickHouseInsertMigration(t *testing.T) { drv := testClickHouseDriver(t) drv.migrationsTableName = "test_migrations" - db := prepTestClickHouseDB(t) + db := prepTestClickHouseDB(t, drv) defer dbutil.MustClose(db) err := drv.CreateMigrationsTable(db) @@ -355,7 +323,7 @@ func TestClickHouseDeleteMigration(t *testing.T) { drv := testClickHouseDriver(t) drv.migrationsTableName = "test_migrations" - db := prepTestClickHouseDB(t) + db := prepTestClickHouseDB(t, drv) defer dbutil.MustClose(db) err := drv.CreateMigrationsTable(db) From 686f7726224be9f95cb26c00db8cec459f4e873b Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 22:49:02 +0300 Subject: [PATCH 15/34] Created a utils file for common test functions --- pkg/driver/clickhouse/clickhouse_testutils.go | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 pkg/driver/clickhouse/clickhouse_testutils.go diff --git a/pkg/driver/clickhouse/clickhouse_testutils.go b/pkg/driver/clickhouse/clickhouse_testutils.go new file mode 100644 index 00000000..16d033f1 --- /dev/null +++ b/pkg/driver/clickhouse/clickhouse_testutils.go @@ -0,0 +1,42 @@ +package clickhouse + +import ( + "database/sql" + "os" + "testing" + + "github.com/amacneil/dbmate/v2/pkg/dbmate" + "github.com/amacneil/dbmate/v2/pkg/dbutil" + + "github.com/stretchr/testify/require" +) + +func testClickHouseDriverURL(t *testing.T, url string) *Driver { + u := dbutil.MustParseURL(url) + drv, err := dbmate.New(u).Driver() + require.NoError(t, err) + + return drv.(*Driver) +} + +func testClickHouseDriver(t *testing.T) *Driver { + return testClickHouseDriverURL(t, os.Getenv("CLICKHOUSE_TEST_URL")) +} + + +func prepTestClickHouseDB(t *testing.T, drv *Driver) *sql.DB { + + // drop any existing database + err := drv.DropDatabase() + require.NoError(t, err) + + // create database + err = drv.CreateDatabase() + require.NoError(t, err) + + // connect database + db, err := sql.Open("clickhouse", drv.databaseURL.String()) + require.NoError(t, err) + + return db +} From 0e0328502e8d42f5ed191b8e373f267661f02d0c Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 22:50:46 +0300 Subject: [PATCH 16/34] Changed cluster config directory path --- docker-compose.yml | 4 ++-- .../{ => testdata}/cluster_config/ch-cluster-01/config.xml | 0 .../{ => testdata}/cluster_config/ch-cluster-02/config.xml | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename pkg/driver/clickhouse/{ => testdata}/cluster_config/ch-cluster-01/config.xml (100%) rename pkg/driver/clickhouse/{ => testdata}/cluster_config/ch-cluster-02/config.xml (100%) diff --git a/docker-compose.yml b/docker-compose.yml index bbff229a..f315af82 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,7 +52,7 @@ services: depends_on: - zookeeper volumes: - - ./pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml:/etc/clickhouse-server/config.xml + - ./pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml:/etc/clickhouse-server/config.xml clickhouse-cluster-02: image: clickhouse/clickhouse-server:22.8 @@ -62,4 +62,4 @@ services: depends_on: - zookeeper volumes: - - ./pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml:/etc/clickhouse-server/config.xml + - ./pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml:/etc/clickhouse-server/config.xml diff --git a/pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml similarity index 100% rename from pkg/driver/clickhouse/cluster_config/ch-cluster-01/config.xml rename to pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml diff --git a/pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml similarity index 100% rename from pkg/driver/clickhouse/cluster_config/ch-cluster-02/config.xml rename to pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml From 75d1441032a2912a5d58d8988d2a4247a9972f2a Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 22:52:18 +0300 Subject: [PATCH 17/34] Changed log size in cluster configs --- .../testdata/cluster_config/ch-cluster-01/config.xml | 4 ++-- .../testdata/cluster_config/ch-cluster-02/config.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml index c08362ee..23a7c8b4 100644 --- a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml @@ -10,8 +10,8 @@ trace /var/log/clickhouse-server/clickhouse-server.log /var/log/clickhouse-server/clickhouse-server.err.log - 1000M - 10 + 100M + 2 8123 diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml index 281795e7..b9a1e2cb 100644 --- a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml @@ -10,8 +10,8 @@ trace /var/log/clickhouse-server/clickhouse-server.log /var/log/clickhouse-server/clickhouse-server.err.log - 1000M - 10 + 100M + 2 8123 From 606daaedfdadcbbb5a09495d2740c05bc26c3b5a Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 8 Apr 2023 22:57:37 +0300 Subject: [PATCH 18/34] rename function of getting cluster parameters --- pkg/driver/clickhouse/clickhouse.go | 7 +++---- pkg/driver/clickhouse/cluster_parameters.go | 10 +++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index a2d657bd..b0dd2c30 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -34,11 +34,10 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver { migrationsTableName: config.MigrationsTableName, databaseURL: config.DatabaseURL, log: config.Log, - clusterParameters: ClusterParametersFromURL(config.DatabaseURL), + clusterParameters: ExtractClusterParametersFromURL(config.DatabaseURL), } } - func connectionString(initialURL *url.URL) string { // clone url u := dbutil.MustParseURL(initialURL.String()) @@ -98,7 +97,7 @@ func (drv *Driver) openClickHouseDB() (*sql.DB, error) { return sql.Open("clickhouse", clickhouseURL.String()) } -func (drv *Driver) onClusterClause() string{ +func (drv *Driver) onClusterClause() string { clusterClause := "" if drv.clusterParameters.OnCluster { clusterClause = fmt.Sprintf(" ON CLUSTER '%s'", drv.clusterParameters.ClusterMacro) @@ -267,7 +266,7 @@ func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) { func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { engineClause := "ReplacingMergeTree(ts)" - if drv.clusterParameters.OnCluster{ + if drv.clusterParameters.OnCluster { engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree(%s, %s, ts)", drv.clusterParameters.ZooPath, drv.clusterParameters.ReplicaMacro) } diff --git a/pkg/driver/clickhouse/cluster_parameters.go b/pkg/driver/clickhouse/cluster_parameters.go index 84a4552c..b390c846 100644 --- a/pkg/driver/clickhouse/cluster_parameters.go +++ b/pkg/driver/clickhouse/cluster_parameters.go @@ -13,21 +13,21 @@ const ( ) type ClusterParameters struct { - OnCluster bool - ZooPath string + OnCluster bool + ZooPath string ClusterMacro string ReplicaMacro string } -func ClusterParametersFromURL(u *url.URL) *ClusterParameters { +func ExtractClusterParametersFromURL(u *url.URL) *ClusterParameters { onCluster := extractOnCluster(u) clusterMacro := extractClusterMacro(u) replicaMacro := extractReplicaMacro(u) zookeeperPath := extractZookeeperPath(u) r := &ClusterParameters{ - OnCluster: onCluster, - ZooPath: zookeeperPath, + OnCluster: onCluster, + ZooPath: zookeeperPath, ClusterMacro: clusterMacro, ReplicaMacro: replicaMacro, } From 0a5519ebd7e9b66afa46221e80138fd39d0c412b Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Tue, 11 Apr 2023 13:47:40 +0300 Subject: [PATCH 19/34] Fixed cluster configs to be able to drop and recreate tables --- docker-compose.yml | 4 +- pkg/driver/clickhouse/clickhouse.go | 8 +- .../clickhouse/clickhouse_cluster_test.go | 2 +- .../config.d/database_atomic.xml | 3 + .../config.d/docker_related_config.xml | 12 ++ .../users.d/database_atomic_drop_sync.xml | 7 + .../cluster_config/ch-cluster-01/users.xml | 120 ++++++++++++++++++ .../config.d/database_atomic.xml | 3 + .../config.d/docker_related_config.xml | 12 ++ .../users.d/database_atomic_drop_sync.xml | 7 + .../cluster_config/ch-cluster-02/users.xml | 120 ++++++++++++++++++ 11 files changed, 291 insertions(+), 7 deletions(-) create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/database_atomic.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/docker_related_config.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/database_atomic_drop_sync.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/database_atomic.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/docker_related_config.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/database_atomic_drop_sync.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.xml diff --git a/docker-compose.yml b/docker-compose.yml index f315af82..70396bbc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,7 +52,7 @@ services: depends_on: - zookeeper volumes: - - ./pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.xml:/etc/clickhouse-server/config.xml + - ./pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01:/etc/clickhouse-server clickhouse-cluster-02: image: clickhouse/clickhouse-server:22.8 @@ -62,4 +62,4 @@ services: depends_on: - zookeeper volumes: - - ./pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.xml:/etc/clickhouse-server/config.xml + - ./pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02:/etc/clickhouse-server diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index b0dd2c30..8f4c97db 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -161,7 +161,7 @@ func (drv *Driver) DropDatabase() error { return err } -func (drv *Driver) schemaDump(db *sql.DB, buf *bytes.Buffer, databaseName string) error { +func (drv *Driver)schemaDump(db *sql.DB, buf *bytes.Buffer, databaseName string) error { buf.WriteString("\n--\n-- Database schema\n--\n\n") buf.WriteString(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s%s;\n\n", drv.quoteIdentifier(databaseName), drv.onClusterClause())) @@ -267,18 +267,18 @@ func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { engineClause := "ReplacingMergeTree(ts)" if drv.clusterParameters.OnCluster { - engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree(%s, %s, ts)", drv.clusterParameters.ZooPath, drv.clusterParameters.ReplicaMacro) + engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree('%s', '%s', ts)", drv.clusterParameters.ZooPath, drv.clusterParameters.ReplicaMacro) } _, err := db.Exec(fmt.Sprintf(` - create table if not exists %s%s ( + create table if not exists %s ( version String, ts DateTime default now(), applied UInt8 default 1 ) engine = %s primary key version order by version - `, drv.quotedMigrationsTableName(), drv.onClusterClause(), engineClause)) + `, drv.quotedMigrationsTableName(), engineClause)) return err } diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index 3c98f621..c41ec81f 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -17,7 +17,7 @@ func testClickHouseDriverCluster01(t *testing.T) *Driver { } func testClickHouseDriverCluster02(t *testing.T) *Driver { - u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) + u := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_02_TEST_URL")) return testClickHouseDriverURL(t, u) } diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/database_atomic.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/database_atomic.xml new file mode 100644 index 00000000..f0a41568 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/database_atomic.xml @@ -0,0 +1,3 @@ + + 0 + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/docker_related_config.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/docker_related_config.xml new file mode 100644 index 00000000..3025dc26 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/config.d/docker_related_config.xml @@ -0,0 +1,12 @@ + + + :: + 0.0.0.0 + 1 + + + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/database_atomic_drop_sync.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/database_atomic_drop_sync.xml new file mode 100644 index 00000000..386fce01 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/database_atomic_drop_sync.xml @@ -0,0 +1,7 @@ + + + + 1 + + + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.xml new file mode 100644 index 00000000..96067d01 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.xml @@ -0,0 +1,120 @@ + + + + + + + + + + random + + + + + 1 + + + + + + + + + + + + + ::/0 + + + + default + + + default + + + + + + + + + + + + + + 3600 + + + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/database_atomic.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/database_atomic.xml new file mode 100644 index 00000000..f0a41568 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/database_atomic.xml @@ -0,0 +1,3 @@ + + 0 + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/docker_related_config.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/docker_related_config.xml new file mode 100644 index 00000000..3025dc26 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/config.d/docker_related_config.xml @@ -0,0 +1,12 @@ + + + :: + 0.0.0.0 + 1 + + + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/database_atomic_drop_sync.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/database_atomic_drop_sync.xml new file mode 100644 index 00000000..386fce01 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/database_atomic_drop_sync.xml @@ -0,0 +1,7 @@ + + + + 1 + + + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.xml new file mode 100644 index 00000000..96067d01 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.xml @@ -0,0 +1,120 @@ + + + + + + + + + + random + + + + + 1 + + + + + + + + + + + + + ::/0 + + + + default + + + default + + + + + + + + + + + + + + 3600 + + + 0 + 0 + 0 + 0 + 0 + + + + From 72487ed3e9f8eb740a1a4de5ed012ae55fb60e12 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Tue, 11 Apr 2023 17:02:27 +0300 Subject: [PATCH 20/34] Completed tests for cluster --- pkg/driver/clickhouse/clickhouse.go | 4 +- .../clickhouse/clickhouse_cluster_test.go | 218 ++++++++++++++++++ ...tutils.go => clickhouse_testutils_test.go} | 1 - 3 files changed, 220 insertions(+), 3 deletions(-) rename pkg/driver/clickhouse/{clickhouse_testutils.go => clickhouse_testutils_test.go} (99%) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 8f4c97db..3c263e2e 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -271,14 +271,14 @@ func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { } _, err := db.Exec(fmt.Sprintf(` - create table if not exists %s ( + create table if not exists %s%s ( version String, ts DateTime default now(), applied UInt8 default 1 ) engine = %s primary key version order by version - `, drv.quotedMigrationsTableName(), engineClause)) + `, drv.quotedMigrationsTableName(), drv.onClusterClause(), engineClause)) return err } diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index c41ec81f..58fa174d 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "testing" + "time" "github.com/amacneil/dbmate/v2/pkg/dbutil" @@ -34,6 +35,11 @@ func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool){ } } +// To make sure data insertion is synced on both nodes +func waitForNodesToSync(){ + time.Sleep(25 * time.Millisecond) +} + func TestOnClusterClause(t *testing.T) { cases := []struct { input string @@ -128,3 +134,215 @@ func TestClickHouseDumpSchemaOnCluster(t *testing.T) { require.Nil(t, schema) require.EqualError(t, err, "code: 81, message: Database fakedb doesn't exist") } + +func TestClickHouseCreateMigrationsTableOnCluster(t *testing.T) { + testCases := []struct { + name string + migrationsTable string + expectedTableName string + }{ + { + name: "default table", + migrationsTable: "", + expectedTableName: "schema_migrations", + }, + { + name: "custom table", + migrationsTable: "testMigrations", + expectedTableName: "\"testMigrations\"", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + drv01 := testClickHouseDriverCluster01(t) + drv02 := testClickHouseDriverCluster02(t) + if tc.migrationsTable != "" { + drv01.migrationsTableName = tc.migrationsTable + drv02.migrationsTableName = tc.migrationsTable + } + + db01 := prepTestClickHouseDB(t, drv01) + defer dbutil.MustClose(db01) + + db02 := prepTestClickHouseDB(t, drv02) + defer dbutil.MustClose(db02) + + // migrations table should not exist + exists, err := drv01.MigrationsTableExists(db01) + require.NoError(t, err) + require.Equal(t, false, exists) + + // migrations table should not exist on the other node + exists, err = drv02.MigrationsTableExists(db02) + require.NoError(t, err) + require.Equal(t, false, exists) + + // create table + err = drv01.CreateMigrationsTable(db01) + require.NoError(t, err) + + // migrations table should exist + exists, err = drv01.MigrationsTableExists(db01) + require.NoError(t, err) + require.Equal(t, true, exists) + + // migrations table should exist on other node + exists, err = drv02.MigrationsTableExists(db02) + require.NoError(t, err) + require.Equal(t, true, exists) + + // create table should be idempotent + err = drv01.CreateMigrationsTable(db01) + require.NoError(t, err) + }) + } +} + +func TestClickHouseSelectMigrationsOnCluster(t *testing.T) { + drv01 := testClickHouseDriverCluster01(t) + drv02 := testClickHouseDriverCluster02(t) + drv01.migrationsTableName = "test_migrations" + drv02.migrationsTableName = "test_migrations" + + db01 := prepTestClickHouseDB(t, drv01) + defer dbutil.MustClose(db01) + + db02 := prepTestClickHouseDB(t, drv02) + defer dbutil.MustClose(db02) + + err := drv01.CreateMigrationsTable(db01) + require.NoError(t, err) + + tx, err := db01.Begin() + require.NoError(t, err) + stmt, err := tx.Prepare("insert into test_migrations (version) values (?)") + require.NoError(t, err) + _, err = stmt.Exec("abc2") + require.NoError(t, err) + _, err = stmt.Exec("abc1") + require.NoError(t, err) + _, err = stmt.Exec("abc3") + require.NoError(t, err) + err = tx.Commit() + require.NoError(t, err) + + waitForNodesToSync() + + migrations01, err := drv01.SelectMigrations(db01, -1) + require.NoError(t, err) + require.Equal(t, true, migrations01["abc1"]) + require.Equal(t, true, migrations01["abc2"]) + require.Equal(t, true, migrations01["abc3"]) + + // Assert select on other node + migrations02, err := drv02.SelectMigrations(db02, -1) + require.NoError(t, err) + require.Equal(t, true, migrations02["abc1"]) + require.Equal(t, true, migrations02["abc2"]) + require.Equal(t, true, migrations02["abc3"]) + + // test limit param + migrations01, err = drv01.SelectMigrations(db01, 1) + require.NoError(t, err) + require.Equal(t, true, migrations01["abc3"]) + require.Equal(t, false, migrations01["abc1"]) + require.Equal(t, false, migrations01["abc2"]) + + // test limit param on other node + migrations02, err = drv02.SelectMigrations(db02, 1) + require.NoError(t, err) + require.Equal(t, true, migrations02["abc3"]) + require.Equal(t, false, migrations02["abc1"]) + require.Equal(t, false, migrations02["abc2"]) +} + +func TestClickHouseInsertMigrationOnCluster(t *testing.T) { + drv01 := testClickHouseDriverCluster01(t) + drv02 := testClickHouseDriverCluster02(t) + drv01.migrationsTableName = "test_migrations" + drv02.migrationsTableName = "test_migrations" + + db01 := prepTestClickHouseDB(t, drv01) + defer dbutil.MustClose(db01) + + db02 := prepTestClickHouseDB(t, drv02) + defer dbutil.MustClose(db02) + + err := drv01.CreateMigrationsTable(db01) + require.NoError(t, err) + + count01 := 0 + err = db01.QueryRow("select count(*) from test_migrations").Scan(&count01) + require.NoError(t, err) + require.Equal(t, 0, count01) + + count02 := 0 + err = db02.QueryRow("select count(*) from test_migrations").Scan(&count02) + require.NoError(t, err) + require.Equal(t, 0, count02) + + // insert migration + tx, err := db01.Begin() + require.NoError(t, err) + err = drv01.InsertMigration(tx, "abc1") + require.NoError(t, err) + err = tx.Commit() + require.NoError(t, err) + + waitForNodesToSync() + + err = db01.QueryRow("select count(*) from test_migrations where version = 'abc1'").Scan(&count01) + require.NoError(t, err) + require.Equal(t, 1, count01) + + err = db02.QueryRow("select count(*) from test_migrations where version = 'abc1'").Scan(&count02) + require.NoError(t, err) + require.Equal(t, 1, count02) +} + +func TestClickHouseDeleteMigrationOnCluster(t *testing.T) { + drv01 := testClickHouseDriverCluster01(t) + drv02 := testClickHouseDriverCluster02(t) + drv01.migrationsTableName = "test_migrations" + drv02.migrationsTableName = "test_migrations" + + db01 := prepTestClickHouseDB(t, drv01) + defer dbutil.MustClose(db01) + + db02 := prepTestClickHouseDB(t, drv02) + defer dbutil.MustClose(db02) + + err := drv01.CreateMigrationsTable(db01) + require.NoError(t, err) + + tx, err := db01.Begin() + require.NoError(t, err) + stmt, err := tx.Prepare("insert into test_migrations (version) values (?)") + require.NoError(t, err) + _, err = stmt.Exec("abc2") + require.NoError(t, err) + _, err = stmt.Exec("abc1") + require.NoError(t, err) + err = tx.Commit() + require.NoError(t, err) + + tx, err = db01.Begin() + require.NoError(t, err) + err = drv01.DeleteMigration(tx, "abc2") + require.NoError(t, err) + err = tx.Commit() + require.NoError(t, err) + + waitForNodesToSync() + + count01 := 0 + err = db01.QueryRow("select count(*) from test_migrations final where applied").Scan(&count01) + require.NoError(t, err) + require.Equal(t, 1, count01) + + count02 := 0 + err = db02.QueryRow("select count(*) from test_migrations final where applied").Scan(&count02) + require.NoError(t, err) + require.Equal(t, 1, count02) +} diff --git a/pkg/driver/clickhouse/clickhouse_testutils.go b/pkg/driver/clickhouse/clickhouse_testutils_test.go similarity index 99% rename from pkg/driver/clickhouse/clickhouse_testutils.go rename to pkg/driver/clickhouse/clickhouse_testutils_test.go index 16d033f1..a780e082 100644 --- a/pkg/driver/clickhouse/clickhouse_testutils.go +++ b/pkg/driver/clickhouse/clickhouse_testutils_test.go @@ -23,7 +23,6 @@ func testClickHouseDriver(t *testing.T) *Driver { return testClickHouseDriverURL(t, os.Getenv("CLICKHOUSE_TEST_URL")) } - func prepTestClickHouseDB(t *testing.T, drv *Driver) *sql.DB { // drop any existing database From 801dc8267edf6af9e22111ffe4f958ab0830c1db Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Tue, 11 Apr 2023 17:09:39 +0300 Subject: [PATCH 21/34] Ran golangci --- pkg/driver/clickhouse/clickhouse.go | 3 +-- .../clickhouse/clickhouse_cluster_test.go | 20 +++++++++---------- pkg/driver/clickhouse/clickhouse_test.go | 1 - .../clickhouse/clickhouse_testutils_test.go | 1 - .../clickhouse/cluster_parameters_test.go | 6 ++---- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 3c263e2e..6296797c 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -161,7 +161,7 @@ func (drv *Driver) DropDatabase() error { return err } -func (drv *Driver)schemaDump(db *sql.DB, buf *bytes.Buffer, databaseName string) error { +func (drv *Driver) schemaDump(db *sql.DB, buf *bytes.Buffer, databaseName string) error { buf.WriteString("\n--\n-- Database schema\n--\n\n") buf.WriteString(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s%s;\n\n", drv.quoteIdentifier(databaseName), drv.onClusterClause())) @@ -264,7 +264,6 @@ func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) { // CreateMigrationsTable creates the schema migrations table func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { - engineClause := "ReplacingMergeTree(ts)" if drv.clusterParameters.OnCluster { engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree('%s', '%s', ts)", drv.clusterParameters.ZooPath, drv.clusterParameters.ReplicaMacro) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index 58fa174d..ecd14a65 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -22,21 +22,21 @@ func testClickHouseDriverCluster02(t *testing.T) *Driver { return testClickHouseDriverURL(t, u) } -func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool){ +func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool) { db, err := sql.Open("clickhouse", drv.databaseURL.String()) - require.NoError(t, err) - defer dbutil.MustClose(db) + require.NoError(t, err) + defer dbutil.MustClose(db) - err = db.Ping() - if shouldExist{ - require.NoError(t, err) - } else { - require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") - } + err = db.Ping() + if shouldExist { + require.NoError(t, err) + } else { + require.EqualError(t, err, "code: 81, message: Database dbmate_test doesn't exist") + } } // To make sure data insertion is synced on both nodes -func waitForNodesToSync(){ +func waitForNodesToSync() { time.Sleep(25 * time.Millisecond) } diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index c7d8e9cb..53705700 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -93,7 +93,6 @@ func TestClickHouseCreateDropDatabase(t *testing.T) { }() } - func TestClickHouseDumpSchema(t *testing.T) { drv := testClickHouseDriver(t) drv.migrationsTableName = "test_migrations" diff --git a/pkg/driver/clickhouse/clickhouse_testutils_test.go b/pkg/driver/clickhouse/clickhouse_testutils_test.go index a780e082..8ddfeab4 100644 --- a/pkg/driver/clickhouse/clickhouse_testutils_test.go +++ b/pkg/driver/clickhouse/clickhouse_testutils_test.go @@ -24,7 +24,6 @@ func testClickHouseDriver(t *testing.T) *Driver { } func prepTestClickHouseDB(t *testing.T, drv *Driver) *sql.DB { - // drop any existing database err := drv.DropDatabase() require.NoError(t, err) diff --git a/pkg/driver/clickhouse/cluster_parameters_test.go b/pkg/driver/clickhouse/cluster_parameters_test.go index 577fc439..fb8c29f7 100644 --- a/pkg/driver/clickhouse/cluster_parameters_test.go +++ b/pkg/driver/clickhouse/cluster_parameters_test.go @@ -1,13 +1,12 @@ package clickhouse import ( - "testing" - "github.com/amacneil/dbmate/v2/pkg/dbutil" "github.com/stretchr/testify/require" -) + "github.com/amacneil/dbmate/v2/pkg/dbutil" +) func TestOnCluster(t *testing.T) { cases := []struct { @@ -34,7 +33,6 @@ func TestOnCluster(t *testing.T) { } } - func TestClusterMacro(t *testing.T) { cases := []struct { input string From 74143651e52d97d5ac3898a232285a3b0c61db58 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 18:08:05 +0300 Subject: [PATCH 22/34] Remove cluster query params on connection string --- pkg/driver/clickhouse/cluster_parameters.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pkg/driver/clickhouse/cluster_parameters.go b/pkg/driver/clickhouse/cluster_parameters.go index b390c846..6565914e 100644 --- a/pkg/driver/clickhouse/cluster_parameters.go +++ b/pkg/driver/clickhouse/cluster_parameters.go @@ -19,6 +19,17 @@ type ClusterParameters struct { ReplicaMacro string } +func ClearClusterParametersFromUrl(u *url.URL) *url.URL{ + q := u.Query() + q.Del(OnClusterQueryParam) + q.Del(ClusterMacroQueryParam) + q.Del(ReplicaMacroQueryParam) + q.Del(ZooPathQueryParam) + u.RawQuery = q.Encode() + + return u +} + func ExtractClusterParametersFromURL(u *url.URL) *ClusterParameters { onCluster := extractOnCluster(u) clusterMacro := extractClusterMacro(u) @@ -32,14 +43,6 @@ func ExtractClusterParametersFromURL(u *url.URL) *ClusterParameters { ReplicaMacro: replicaMacro, } - q := u.Query() - q.Del(OnClusterQueryParam) - q.Del(ClusterMacroQueryParam) - q.Del(ReplicaMacroQueryParam) - q.Del(ZooPathQueryParam) - - u.RawQuery = q.Encode() - return r } From 347c7aa5f5a18bc2cc65f107e877ddcbdf95dc16 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 18:14:56 +0300 Subject: [PATCH 23/34] Fix test usage of connection link --- pkg/driver/clickhouse/clickhouse.go | 2 ++ pkg/driver/clickhouse/clickhouse_test.go | 2 -- pkg/driver/clickhouse/clickhouse_testutils_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 6296797c..2a204fc8 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -76,6 +76,8 @@ func connectionString(initialURL *url.URL) string { u.RawQuery = query.Encode() + u = ClearClusterParametersFromUrl(u) + return u.String() } diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index 53705700..f16fc6be 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -42,8 +42,6 @@ func TestConnectionString(t *testing.T) { {"clickhouse://aaa:111@myhost/mydb?username=bbb&password=222", "clickhouse://bbb:222@myhost:9000/mydb"}, // custom parameters {"clickhouse://myhost/mydb?dial_timeout=200ms", "clickhouse://myhost:9000/mydb?dial_timeout=200ms"}, - // on_cluster parameter - {"clickhouse://myhost/mydb?on_cluster=true", "clickhouse://myhost:9000/mydb?on_cluster=true"}, } for _, c := range cases { diff --git a/pkg/driver/clickhouse/clickhouse_testutils_test.go b/pkg/driver/clickhouse/clickhouse_testutils_test.go index 8ddfeab4..0dfb4cff 100644 --- a/pkg/driver/clickhouse/clickhouse_testutils_test.go +++ b/pkg/driver/clickhouse/clickhouse_testutils_test.go @@ -33,7 +33,7 @@ func prepTestClickHouseDB(t *testing.T, drv *Driver) *sql.DB { require.NoError(t, err) // connect database - db, err := sql.Open("clickhouse", drv.databaseURL.String()) + db, err := drv.Open() require.NoError(t, err) return db From 70aab0288ddf4a3e383f6b1121de161c62d538b4 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 18:25:33 +0300 Subject: [PATCH 24/34] Added a test to see that driver creation is still atmoic --- pkg/driver/clickhouse/clickhouse_cluster_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index ecd14a65..66e4d02c 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/amacneil/dbmate/v2/pkg/dbmate" "github.com/amacneil/dbmate/v2/pkg/dbutil" "github.com/stretchr/testify/require" @@ -40,6 +41,19 @@ func waitForNodesToSync() { time.Sleep(25 * time.Millisecond) } +// Makes sure driver creatinon is atomic +func TestDriverCreationSanity(t *testing.T){ + url := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) + u := dbutil.MustParseURL(url) + dbm := dbmate.New(u) + drv, err := dbm.Driver() + require.NoError(t, err) + drvAgain, err := dbm.Driver() + require.NoError(t, err) + + require.Equal(t, drv, drvAgain) +} + func TestOnClusterClause(t *testing.T) { cases := []struct { input string From d928a27347f397808cefa5c2504fafc3eded2630 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 18:26:44 +0300 Subject: [PATCH 25/34] Added indication of cluster to dump schema test --- pkg/driver/clickhouse/clickhouse_cluster_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index 66e4d02c..a99a97a1 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -132,6 +132,7 @@ func TestClickHouseDumpSchemaOnCluster(t *testing.T) { schema, err := drv.DumpSchema(db) require.NoError(t, err) require.Contains(t, string(schema), "CREATE TABLE "+drv.databaseName()+".test_migrations") + require.Contains(t, string(schema), "ENGINE = ReplicatedReplacingMergeTree") require.Contains(t, string(schema), "--\n"+ "-- Dbmate schema migrations\n"+ "--\n\n"+ From 114b8b7399b9b31e31467efa235fbef85a1f8b0e Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 21:15:01 +0300 Subject: [PATCH 26/34] Ran golangchi --- pkg/driver/clickhouse/clickhouse.go | 2 +- pkg/driver/clickhouse/clickhouse_cluster_test.go | 2 +- pkg/driver/clickhouse/cluster_parameters.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 2a204fc8..7c23f6f7 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -76,7 +76,7 @@ func connectionString(initialURL *url.URL) string { u.RawQuery = query.Encode() - u = ClearClusterParametersFromUrl(u) + u = ClearClusterParametersFromURL(u) return u.String() } diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index a99a97a1..7d57ab20 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -42,7 +42,7 @@ func waitForNodesToSync() { } // Makes sure driver creatinon is atomic -func TestDriverCreationSanity(t *testing.T){ +func TestDriverCreationSanity(t *testing.T) { url := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) u := dbutil.MustParseURL(url) dbm := dbmate.New(u) diff --git a/pkg/driver/clickhouse/cluster_parameters.go b/pkg/driver/clickhouse/cluster_parameters.go index 6565914e..3bd3212d 100644 --- a/pkg/driver/clickhouse/cluster_parameters.go +++ b/pkg/driver/clickhouse/cluster_parameters.go @@ -19,7 +19,7 @@ type ClusterParameters struct { ReplicaMacro string } -func ClearClusterParametersFromUrl(u *url.URL) *url.URL{ +func ClearClusterParametersFromURL(u *url.URL) *url.URL { q := u.Query() q.Del(OnClusterQueryParam) q.Del(ClusterMacroQueryParam) From 59ee572dfc940dd2c761fc07d1b5d0ade692537e Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 22:13:27 +0300 Subject: [PATCH 27/34] increase wait time for replicas sync --- pkg/driver/clickhouse/clickhouse_cluster_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index 7d57ab20..255ef21c 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -38,11 +38,11 @@ func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool) { // To make sure data insertion is synced on both nodes func waitForNodesToSync() { - time.Sleep(25 * time.Millisecond) + time.Sleep(50 * time.Millisecond) } // Makes sure driver creatinon is atomic -func TestDriverCreationSanity(t *testing.T) { +func TestDriverCreationSanity(t *testing.T){ url := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) u := dbutil.MustParseURL(url) dbm := dbmate.New(u) From 78c024a512acc36f40fc7b4aa805aaf3c8df505e Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 22:25:11 +0300 Subject: [PATCH 28/34] Replace sleep with insert_quorom settings --- pkg/driver/clickhouse/clickhouse_cluster_test.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index 255ef21c..b62bcd87 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "testing" - "time" "github.com/amacneil/dbmate/v2/pkg/dbmate" "github.com/amacneil/dbmate/v2/pkg/dbutil" @@ -36,11 +35,6 @@ func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool) { } } -// To make sure data insertion is synced on both nodes -func waitForNodesToSync() { - time.Sleep(50 * time.Millisecond) -} - // Makes sure driver creatinon is atomic func TestDriverCreationSanity(t *testing.T){ url := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) @@ -242,8 +236,6 @@ func TestClickHouseSelectMigrationsOnCluster(t *testing.T) { err = tx.Commit() require.NoError(t, err) - waitForNodesToSync() - migrations01, err := drv01.SelectMigrations(db01, -1) require.NoError(t, err) require.Equal(t, true, migrations01["abc1"]) @@ -305,8 +297,6 @@ func TestClickHouseInsertMigrationOnCluster(t *testing.T) { err = tx.Commit() require.NoError(t, err) - waitForNodesToSync() - err = db01.QueryRow("select count(*) from test_migrations where version = 'abc1'").Scan(&count01) require.NoError(t, err) require.Equal(t, 1, count01) @@ -349,8 +339,6 @@ func TestClickHouseDeleteMigrationOnCluster(t *testing.T) { err = tx.Commit() require.NoError(t, err) - waitForNodesToSync() - count01 := 0 err = db01.QueryRow("select count(*) from test_migrations final where applied").Scan(&count01) require.NoError(t, err) From 1e7a86c09174cefce16614ad70a0c35185607e9f Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 22:25:20 +0300 Subject: [PATCH 29/34] Replace sleep with insert_quorom settings --- .../ch-cluster-01/users.d/default_profile.xml | 10 ++++++++++ .../ch-cluster-02/users.d/default_profile.xml | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/default_profile.xml create mode 100644 pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/default_profile.xml diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/default_profile.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/default_profile.xml new file mode 100644 index 00000000..34cce837 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-01/users.d/default_profile.xml @@ -0,0 +1,10 @@ + + + + + 2 + + + diff --git a/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/default_profile.xml b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/default_profile.xml new file mode 100644 index 00000000..34cce837 --- /dev/null +++ b/pkg/driver/clickhouse/testdata/cluster_config/ch-cluster-02/users.d/default_profile.xml @@ -0,0 +1,10 @@ + + + + + 2 + + + From acaa08effed7e9509b87cab719206ee77fee47f3 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 22 Apr 2023 22:29:06 +0300 Subject: [PATCH 30/34] ran golangchi --- pkg/driver/clickhouse/clickhouse_cluster_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/driver/clickhouse/clickhouse_cluster_test.go b/pkg/driver/clickhouse/clickhouse_cluster_test.go index b62bcd87..0c50a351 100644 --- a/pkg/driver/clickhouse/clickhouse_cluster_test.go +++ b/pkg/driver/clickhouse/clickhouse_cluster_test.go @@ -36,7 +36,7 @@ func assertDatabaseExists(t *testing.T, drv *Driver, shouldExist bool) { } // Makes sure driver creatinon is atomic -func TestDriverCreationSanity(t *testing.T){ +func TestDriverCreationSanity(t *testing.T) { url := fmt.Sprintf("%s?on_cluster", os.Getenv("CLICKHOUSE_CLUSTER_01_TEST_URL")) u := dbutil.MustParseURL(url) dbm := dbmate.New(u) From f7593db554e3acaa3e559b0a7cfe773ae0bce9e7 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 13 May 2023 12:03:33 +0300 Subject: [PATCH 31/34] Added docs for the cluster query parameters to the clickhouse section --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index c86a48ae..e9413acb 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,33 @@ DATABASE_URL="sqlite:/tmp/database.sqlite3" DATABASE_URL="clickhouse://username:password@127.0.0.1:9000/database_name" ``` +To work with ClickHouse cluster, there are 4 connection query parameters that can be supplied: + +- `on_cluster` - Indicataion to use cluster statements and replicated migration table. (default: `false`) If this parameter is not supplied, other cluster related query parameters are ignored. +```sh +DATABASE_URL="clickhouse://username:password@127.0.0.1:9000/database_name?on_cluster" + +DATABASE_URL="clickhouse://username:password@127.0.0.1:9000/database_name?on_cluster=true" +``` + +- `cluster_macro` (Optional) - Macro value to be used for ON CLUSTER statements and for the replciated migration table engine zookeeper path. (default: `{cluster}`) + +```sh +DATABASE_URL="clickhouse://username:password@127.0.0.1:9000/database_name?on_cluster&cluster_macro={my_cluster}" +``` + +- `replica_macro` (Optional) - Macro value to be used for the replica name in the replciated migration table engine. (default: `{replica}`) + +```sh +DATABASE_URL="clickhouse://username:password@127.0.0.1:9000/database_name?on_cluster&replica_macro={my_replica}" +``` + +- `zoo_path` (Optional) - The path to the table migration in ClickHouse/Zoo Keeper. (default: `/clickhouse/tables//{table}`) + +```sh +DATABASE_URL="clickhouse://username:password@127.0.0.1:9000/database_name?on_cluster&zoo_path=/zk/path/tables" +``` + [See other supported connection options](https://github.com/ClickHouse/clickhouse-go#dsn). ### Creating Migrations From 88664b27774815464e2b2f00b25aa0ea4989a462 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 13 May 2023 13:38:10 +0300 Subject: [PATCH 32/34] Added a escape string function to the clickhouse driver --- pkg/driver/clickhouse/clickhouse.go | 6 ++++++ pkg/driver/clickhouse/clickhouse_test.go | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 7c23f6f7..212cdc96 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -127,6 +127,12 @@ func (drv *Driver) quoteIdentifier(str string) string { return fmt.Sprintf(`"%s"`, str) } +func (drv *Driver) escapeString(str string) string { + quoteEscaper := strings.NewReplacer(`'`, `\'`, `\`, `\\`) + str = quoteEscaper.Replace(str) + return str +} + // CreateDatabase creates the specified database func (drv *Driver) CreateDatabase() error { name := drv.databaseName() diff --git a/pkg/driver/clickhouse/clickhouse_test.go b/pkg/driver/clickhouse/clickhouse_test.go index f16fc6be..ef1f521c 100644 --- a/pkg/driver/clickhouse/clickhouse_test.go +++ b/pkg/driver/clickhouse/clickhouse_test.go @@ -391,3 +391,26 @@ func TestClickHouseQuotedMigrationsTableName(t *testing.T) { require.Equal(t, `"bizarre""$name"`, name) }) } + +func TestEscapeString(t *testing.T) { + cases := []struct { + input string + expected string + }{ + // nothig to escape + {`lets go`, `lets go`}, + // escape ' + {`let's go`, `let\'s go`}, + // escape \ + {`let\s go`, `let\\s go`}, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + drv := testClickHouseDriver(t) + + actual := drv.escapeString(c.input) + require.Equal(t, c.expected, actual) + }) + } +} From 1398b9ff61f9cb03f2b39e62fe1db01ef34750c5 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 13 May 2023 13:48:28 +0300 Subject: [PATCH 33/34] Added usage of escaping to cluster settings on sql statements --- pkg/driver/clickhouse/clickhouse.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 212cdc96..6c306b29 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -102,7 +102,8 @@ func (drv *Driver) openClickHouseDB() (*sql.DB, error) { func (drv *Driver) onClusterClause() string { clusterClause := "" if drv.clusterParameters.OnCluster { - clusterClause = fmt.Sprintf(" ON CLUSTER '%s'", drv.clusterParameters.ClusterMacro) + escapedClusterMacro := drv.escapeString(drv.clusterParameters.ClusterMacro) + clusterClause = fmt.Sprintf(" ON CLUSTER '%s'", escapedClusterMacro) } return clusterClause } @@ -274,7 +275,9 @@ func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) { func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { engineClause := "ReplacingMergeTree(ts)" if drv.clusterParameters.OnCluster { - engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree('%s', '%s', ts)", drv.clusterParameters.ZooPath, drv.clusterParameters.ReplicaMacro) + escapedZooPath := drv.escapeString(drv.clusterParameters.ZooPath) + escapedReplicaMacro := drv.escapeString(drv.clusterParameters.ReplicaMacro) + engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree('%s', '%s', ts)", escapedZooPath, escapedReplicaMacro ) } _, err := db.Exec(fmt.Sprintf(` From 73a9230428699bb0d6d408dbbc4b233f4fc3a105 Mon Sep 17 00:00:00 2001 From: Fathercandle Date: Sat, 13 May 2023 15:35:30 +0300 Subject: [PATCH 34/34] Ran golanci --- pkg/driver/clickhouse/clickhouse.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go index 6c306b29..0f176f64 100644 --- a/pkg/driver/clickhouse/clickhouse.go +++ b/pkg/driver/clickhouse/clickhouse.go @@ -277,7 +277,7 @@ func (drv *Driver) CreateMigrationsTable(db *sql.DB) error { if drv.clusterParameters.OnCluster { escapedZooPath := drv.escapeString(drv.clusterParameters.ZooPath) escapedReplicaMacro := drv.escapeString(drv.clusterParameters.ReplicaMacro) - engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree('%s', '%s', ts)", escapedZooPath, escapedReplicaMacro ) + engineClause = fmt.Sprintf("ReplicatedReplacingMergeTree('%s', '%s', ts)", escapedZooPath, escapedReplicaMacro) } _, err := db.Exec(fmt.Sprintf(`