From c4b81d1210830d40c7ab7bd2f22230e4223bc380 Mon Sep 17 00:00:00 2001 From: Alan Graham Date: Tue, 17 Jul 2018 15:19:54 +0000 Subject: [PATCH 1/3] Support for multiple statements in Cassandra cql migration files based on semi-colon and newline. --- database/cassandra/cassandra.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/database/cassandra/cassandra.go b/database/cassandra/cassandra.go index 87de62c..687323f 100644 --- a/database/cassandra/cassandra.go +++ b/database/cassandra/cassandra.go @@ -155,9 +155,17 @@ func (c *Cassandra) Run(migration io.Reader) error { } // run migration query := string(migr[:]) - if err := c.session.Query(query).Exec(); err != nil { - // TODO: cast to Cassandra error and get line number - return database.Error{OrigErr: err, Err: "migration failed", Query: migr} + + // split query by semi-colon + queries := strings.Split(query, ";\n") + + for _, q := range(queries) { + tq := strings.TrimSpace(q) + if (tq == "") { continue } + if err := c.session.Query(tq).Exec(); err != nil { + // TODO: cast to Cassandra error and get line number + return database.Error{OrigErr: err, Err: "migration failed", Query: migr} + } } return nil From 327822c29ac0e214a8479e30937aea13eaee8581 Mon Sep 17 00:00:00 2001 From: Alan Graham Date: Fri, 20 Jul 2018 13:27:54 +0000 Subject: [PATCH 2/3] Added Cassandra URL flag to enable multi statement migrations --- database/cassandra/README.md | 2 ++ database/cassandra/cassandra.go | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/database/cassandra/README.md b/database/cassandra/README.md index f99b110..0c74ad1 100644 --- a/database/cassandra/README.md +++ b/database/cassandra/README.md @@ -3,6 +3,7 @@ * Drop command will not work on Cassandra 2.X because it rely on system_schema table which comes with 3.X * Other commands should work properly but are **not tested** +* The Cassandra driver (gocql) 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. Note that this simply splits the migration into separately-executed statements by a semi-colon ';'. The queries are also not executed in any sort of transaction/batch, meaning you are responsible for fixing partial migrations. ## Usage @@ -12,6 +13,7 @@ system_schema table which comes with 3.X | URL Query | Default value | Description | |------------|-------------|-----------| | `x-migrations-table` | schema_migrations | Name of the migrations table | +| `x-multi-statement` | false | Enable multiple statements to be ran in a single migration (See note above) | | `port` | 9042 | The port to bind to | | `consistency` | ALL | Migration consistency | `protocol` | | Cassandra protocol version (3 or 4) diff --git a/database/cassandra/cassandra.go b/database/cassandra/cassandra.go index 687323f..4f5a7db 100644 --- a/database/cassandra/cassandra.go +++ b/database/cassandra/cassandra.go @@ -31,6 +31,7 @@ var ( type Config struct { MigrationsTable string KeyspaceName string + MultiStatementEnabled bool } type Cassandra struct { @@ -127,6 +128,7 @@ func (c *Cassandra) Open(url string) (database.Driver, error) { return WithInstance(session, &Config{ KeyspaceName: strings.TrimPrefix(u.Path, "/"), MigrationsTable: u.Query().Get("x-migrations-table"), + MultiStatementEnabled: u.Query().Get("x-multi-statement") == "true", }) } @@ -156,13 +158,20 @@ func (c *Cassandra) Run(migration io.Reader) error { // run migration query := string(migr[:]) - // split query by semi-colon - queries := strings.Split(query, ";\n") + if c.config.MultiStatementEnabled { + // split query by semi-colon + queries := strings.Split(query, ";") - for _, q := range(queries) { - tq := strings.TrimSpace(q) - if (tq == "") { continue } - if err := c.session.Query(tq).Exec(); err != nil { + for _, q := range(queries) { + tq := strings.TrimSpace(q) + if (tq == "") { continue } + if err := c.session.Query(tq).Exec(); err != nil { + // TODO: cast to Cassandra error and get line number + return database.Error{OrigErr: err, Err: "migration failed", Query: migr} + } + } + } else { + if err := c.session.Query(query).Exec(); err != nil { // TODO: cast to Cassandra error and get line number return database.Error{OrigErr: err, Err: "migration failed", Query: migr} } From 4244ebea6aa21b3e115a54b491079ae5a405560e Mon Sep 17 00:00:00 2001 From: Alan Graham Date: Tue, 24 Jul 2018 19:30:44 +0000 Subject: [PATCH 3/3] Add detail to README for Cassandra flag, improve if block --- database/cassandra/README.md | 4 +++- database/cassandra/cassandra.go | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/database/cassandra/README.md b/database/cassandra/README.md index 0c74ad1..f0e1182 100644 --- a/database/cassandra/README.md +++ b/database/cassandra/README.md @@ -3,7 +3,9 @@ * Drop command will not work on Cassandra 2.X because it rely on system_schema table which comes with 3.X * Other commands should work properly but are **not tested** -* The Cassandra driver (gocql) 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. Note that this simply splits the migration into separately-executed statements by a semi-colon ';'. The queries are also not executed in any sort of transaction/batch, meaning you are responsible for fixing partial migrations. +* The Cassandra driver (gocql) 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. ## Usage diff --git a/database/cassandra/cassandra.go b/database/cassandra/cassandra.go index 4f5a7db..b5503c0 100644 --- a/database/cassandra/cassandra.go +++ b/database/cassandra/cassandra.go @@ -170,13 +170,13 @@ func (c *Cassandra) Run(migration io.Reader) error { return database.Error{OrigErr: err, Err: "migration failed", Query: migr} } } - } else { - if err := c.session.Query(query).Exec(); err != nil { - // TODO: cast to Cassandra error and get line number - return database.Error{OrigErr: err, Err: "migration failed", Query: migr} - } + return nil } + if err := c.session.Query(query).Exec(); err != nil { + // TODO: cast to Cassandra error and get line number + return database.Error{OrigErr: err, Err: "migration failed", Query: migr} + } return nil }