From df7ce674e978cbd16200991d3155edc3fecccaeb Mon Sep 17 00:00:00 2001 From: Anton Markelov Date: Fri, 3 Aug 2018 16:08:47 +1000 Subject: [PATCH] add support for the multiline clickhouse queries --- database/clickhouse/README.md | 9 ++++++++- database/clickhouse/clickhouse.go | 27 +++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/database/clickhouse/README.md b/database/clickhouse/README.md index 2b185b3..b1ebe88 100644 --- a/database/clickhouse/README.md +++ b/database/clickhouse/README.md @@ -1,6 +1,6 @@ # ClickHouse -`clickhouse://host:port?username=user&password=qwerty&database=clicks` +`clickhouse://host:port?username=user&password=qwerty&database=clicks&x-multi-statement=true` | URL Query | Description | |------------|-------------| @@ -10,3 +10,10 @@ | `password` | The user's password | | `host` | The host to connect to. | | `port` | The port to bind to. | +| `x-multi-statement` | false | Enable multiple statements to be ran in a single migration (See note below) | + +## Notes + +* The Clickhouse driver does not natively support executing multipe statements in a single query. To allow for multiple statements in a single migration, you can use the `x-multi-statement` param. There are two important caveats: + * This mode splits the migration text into separately-executed statements by a semi-colon `;`. Thus `x-multi-statement` cannot be used when a statement in the migration contains a string with a semi-colon. + * The queries are not executed in any sort of transaction/batch, meaning you are responsible for fixing partial migrations. \ No newline at end of file diff --git a/database/clickhouse/clickhouse.go b/database/clickhouse/clickhouse.go index 5492f41..4435a77 100644 --- a/database/clickhouse/clickhouse.go +++ b/database/clickhouse/clickhouse.go @@ -6,6 +6,7 @@ import ( "io" "io/ioutil" "net/url" + "strings" "time" "github.com/golang-migrate/migrate" @@ -17,8 +18,9 @@ var DefaultMigrationsTable = "schema_migrations" var ErrNilConfig = fmt.Errorf("no config") type Config struct { - DatabaseName string - MigrationsTable string + DatabaseName string + MigrationsTable string + MultiStatementEnabled bool } func init() { @@ -66,8 +68,9 @@ func (ch *ClickHouse) Open(dsn string) (database.Driver, error) { ch = &ClickHouse{ conn: conn, config: &Config{ - MigrationsTable: purl.Query().Get("x-migrations-table"), - DatabaseName: purl.Query().Get("database"), + MigrationsTable: purl.Query().Get("x-migrations-table"), + DatabaseName: purl.Query().Get("database"), + MultiStatementEnabled: purl.Query().Get("x-multi-statement") == "true", }, } @@ -97,6 +100,22 @@ func (ch *ClickHouse) Run(r io.Reader) error { if err != nil { return err } + + if ch.config.MultiStatementEnabled { + // split query by semi-colon + queries := strings.Split(string(migration), ";") + for _, q := range queries { + tq := strings.TrimSpace(q) + if tq == "" { + continue + } + if _, err := ch.conn.Exec(string(q)); err != nil { + return database.Error{OrigErr: err, Err: "migration failed", Query: []byte(q)} + } + } + return nil + } + if _, err := ch.conn.Exec(string(migration)); err != nil { return database.Error{OrigErr: err, Err: "migration failed", Query: migration} }