From caccb9f34aa9b77802b99be5b884c0b2e7c3cc58 Mon Sep 17 00:00:00 2001 From: KushnirykOleh Date: Tue, 6 Apr 2021 17:54:14 +0300 Subject: [PATCH] [LB-1330] fixed snapshot generating query for Astra (#65) * fixed snapshot generating query for Astra * added AWSkeyspace fix * fixed readme --- README.md | 2 +- README.test-harness.md | 5 +++-- .../snapshot/ColumnSnapshotGeneratorCassandra.java | 13 ++++++++++--- .../snapshot/IndexSnapshotGeneratorCassandra.java | 7 ++++--- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cddd69ef..c5b49582 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ get ip `docker inspect mycassandra` -start another instance for cqlsh +start another instance for cqlsh, check for IP address, replace mentioned IP with the one inspect command shows `docker run -it --rm cassandra bash` diff --git a/README.test-harness.md b/README.test-harness.md index e82cd345..37d0211c 100644 --- a/README.test-harness.md +++ b/README.test-harness.md @@ -16,9 +16,10 @@ To be able to run the harness tests locally setting up docker container is curre To create a local test database docker container, execute the following steps: - Run main cassandra instance `docker run -p 9042:9042 --rm --name mycassandra -d cassandra`, and give it few seconds to start +- Run `docker inspect mycassandra` to get a main instance IP address. By default, it's 172.17.0.2 but may change in our local env. - To execute init script run second container `docker run -it --rm cassandra bash` -- enter cql console `cqlsh 172.17.0.2` -- copy and paste `test.cql` file content +- enter cql console `cqlsh 172.17.0.2` (or other IP showed by `docker inspect mycassandra` if this doesn't work) +- copy and paste `test.cql` file content to create keyspace and tables for tests. #### Executing the tests From your IDE, right click on the `LiquibaseHarnessSuiteTest` test class present in `src/test/groovy` directory. diff --git a/src/main/java/liquibase/ext/cassandra/snapshot/ColumnSnapshotGeneratorCassandra.java b/src/main/java/liquibase/ext/cassandra/snapshot/ColumnSnapshotGeneratorCassandra.java index e5fcd741..2271bdfc 100644 --- a/src/main/java/liquibase/ext/cassandra/snapshot/ColumnSnapshotGeneratorCassandra.java +++ b/src/main/java/liquibase/ext/cassandra/snapshot/ColumnSnapshotGeneratorCassandra.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class ColumnSnapshotGeneratorCassandra extends ColumnSnapshotGenerator { @@ -36,7 +37,7 @@ protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) thro if (foundObject instanceof Relation) { Database database = snapshot.getDatabase(); Relation relation = (Relation) foundObject; - String query = String.format("SELECT COLUMN_NAME, TYPE, KIND FROM system_schema.columns WHERE keyspace_name = '%s' AND table_name='%s';" + String query = String.format("SELECT KEYSPACE_NAME, COLUMN_NAME, TYPE, KIND FROM system_schema.columns WHERE KEYSPACE_NAME = '%s' AND table_name='%s';" , database.getDefaultCatalogName(), relation.getName()); Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database); @@ -52,11 +53,15 @@ protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) thro protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException { Database database = snapshot.getDatabase(); Relation relation = ((Column) example).getRelation(); - String query = String.format("SELECT COLUMN_NAME, TYPE, KIND FROM system_schema.columns WHERE keyspace_name = '%s' AND table_name='%s' AND column_name='%s';" - , database.getDefaultCatalogName(), relation, example.getName()); + //we can't add column name as query parameter here as AWS keyspaces don't support such where statement + String query = String.format("SELECT KEYSPACE_NAME, COLUMN_NAME, TYPE, KIND FROM system_schema.columns WHERE keyspace_name = '%s' AND table_name='%s';" + , database.getDefaultCatalogName(), relation); List> returnList = Scope.getCurrentScope().getSingleton(ExecutorService.class) .getExecutor("jdbc", database).queryForList(new RawSqlStatement(query)); + returnList = returnList.stream() + .filter(stringMap -> ((String)stringMap.get("COLUMN_NAME")).equalsIgnoreCase(example.getName())) + .collect(Collectors.toList()); if (returnList.size() != 1) { Scope.getCurrentScope().getLog(ColumnSnapshotGeneratorCassandra.class).warning(String.format( "expecting exactly 1 column with name %s, got %s", example.getName(), returnList.size())); @@ -71,6 +76,8 @@ protected Column readColumn(Map tableMap, Relation table) { String rawColumnName = StringUtil.trimToNull((String) tableMap.get("COLUMN_NAME")); String rawColumnType = StringUtil.trimToNull((String) tableMap.get("TYPE")); String rawColumnKind = StringUtil.trimToNull((String) tableMap.get("KIND")); + // we don't really need KEYSPACE_NAME param in query to build Column obj, but Astra Cassandra implementation + // (and maybe some others) fails if it's missing Column column = new Column(); column.setName(rawColumnName); column.setRelation(table); diff --git a/src/main/java/liquibase/ext/cassandra/snapshot/IndexSnapshotGeneratorCassandra.java b/src/main/java/liquibase/ext/cassandra/snapshot/IndexSnapshotGeneratorCassandra.java index 9e697c18..cf16b58c 100644 --- a/src/main/java/liquibase/ext/cassandra/snapshot/IndexSnapshotGeneratorCassandra.java +++ b/src/main/java/liquibase/ext/cassandra/snapshot/IndexSnapshotGeneratorCassandra.java @@ -38,7 +38,7 @@ protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) thro Relation relation = (Relation) foundObject; Database database = snapshot.getDatabase(); - String query = String.format("SELECT INDEX_NAME, OPTIONS FROM system_schema.indexes WHERE keyspace_name = '%s' AND TABLE_NAME='%s';", + String query = String.format("SELECT KEYSPACE_NAME, INDEX_NAME, OPTIONS FROM system_schema.indexes WHERE KEYSPACE_NAME = '%s' AND TABLE_NAME='%s';", database.getDefaultCatalogName(), relation.getName()); Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database); @@ -52,7 +52,8 @@ protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) thro private Index readIndex(Map tableMap, Relation relation) { String indexName = StringUtil.trimToNull((String) tableMap.get("INDEX_NAME")); String options = StringUtil.trimToNull((String) tableMap.get("OPTIONS")); - + // we don't really need KEYSPACE_NAME param in query to build Column obj, but Astra Cassandra implementation + // (and maybe some others) fails if it's missing Index index = new Index(); index.setName(indexName); index.setRelation(relation); @@ -85,7 +86,7 @@ protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot Relation relation = ((Index) example).getRelation(); Database database = snapshot.getDatabase(); - String query = String.format("SELECT INDEX_NAME, OPTIONS FROM system_schema.indexes WHERE keyspace_name = '%s' AND TABLE_NAME='%s' AND INDEX_NAME= '%s';", + String query = String.format("SELECT KEYSPACE_NAME, INDEX_NAME, OPTIONS FROM system_schema.indexes WHERE KEYSPACE_NAME = '%s' AND TABLE_NAME='%s' AND INDEX_NAME= '%s';", database.getDefaultCatalogName(), relation.getName(), example.getName()); Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);