Add tests for schemaExists and truncateSchema methods

Project: http://git-wip-us.apache.org/repos/asf/gora/repo
Commit: http://git-wip-us.apache.org/repos/asf/gora/commit/89109b85
Tree: http://git-wip-us.apache.org/repos/asf/gora/tree/89109b85
Diff: http://git-wip-us.apache.org/repos/asf/gora/diff/89109b85

Branch: refs/heads/master
Commit: 89109b855537050f5b9d125a88d26ca2c1d12f78
Parents: 2695794
Author: madhawa <madhaw...@gmail.com>
Authored: Sun Jun 25 02:35:02 2017 +0530
Committer: madhawa <madhaw...@gmail.com>
Committed: Sun Jun 25 02:41:37 2017 +0530

----------------------------------------------------------------------
 .../cassandra/store/CassandraQueryFactory.java  | 146 ++++++++++++++++++-
 .../gora/cassandra/store/CassandraStore.java    |  31 ++--
 .../compositeKey/gora-cassandra-mapping.xml     |  78 ++++++++++
 ...stCassandraStoreWithNativeSerialization.java |  34 ++++-
 4 files changed, 272 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/gora/blob/89109b85/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraQueryFactory.java
----------------------------------------------------------------------
diff --git 
a/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraQueryFactory.java
 
b/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraQueryFactory.java
index 422fbc6..fc90c5f 100644
--- 
a/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraQueryFactory.java
+++ 
b/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraQueryFactory.java
@@ -16,9 +16,13 @@
  */
 package org.apache.gora.cassandra.store;
 
+import org.apache.gora.cassandra.bean.CassandraKey;
+import org.apache.gora.cassandra.bean.ClusterKeyField;
 import org.apache.gora.cassandra.bean.Field;
 import org.apache.gora.cassandra.bean.KeySpace;
+import org.apache.gora.cassandra.bean.PartitionKeyField;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -26,6 +30,13 @@ import java.util.Map;
  */
 class CassandraQueryFactory {
 
+  /**
+   * This method returns the CQL query to create key space.
+   * refer : 
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/create_keyspace_r.html
+   *
+   * @param mapping Cassandra Mapping
+   * @return CQL Query
+   */
   static String getCreateKeySpaceQuery(CassandraMapping mapping) {
     KeySpace keySpace = mapping.getKeySpace();
     StringBuilder stringBuffer = new StringBuilder();
@@ -59,6 +70,25 @@ class CassandraQueryFactory {
     StringBuilder stringBuffer = new StringBuilder();
     stringBuffer.append("CREATE TABLE IF NOT EXISTS 
").append(mapping.getKeySpace().getName()).append(".").append(mapping.getCoreName()).append("
 (");
     boolean isCommaNeeded = false;
+    CassandraKey cassandraKey = mapping.getCassandraKey();
+    // appending Cassandra key columns into db schema
+    if (cassandraKey != null) {
+      for (PartitionKeyField partitionKeyField : 
cassandraKey.getPartitionKeyFields()) {
+        if (partitionKeyField.isComposite()) {
+          for (Field compositeField : partitionKeyField.getFields()) {
+            stringBuffer = processFields(stringBuffer, compositeField, 
isCommaNeeded);
+          }
+
+        } else {
+          stringBuffer = processFields(stringBuffer, partitionKeyField, 
isCommaNeeded);
+        }
+        isCommaNeeded = true;
+      }
+      for (ClusterKeyField clusterKeyField : 
cassandraKey.getClusterKeyFields()) {
+        stringBuffer = processFields(stringBuffer, clusterKeyField, 
isCommaNeeded);
+      }
+    }
+    // appending Other columns
     for (Field field : mapping.getFieldList()) {
       if (isCommaNeeded) {
         stringBuffer.append(", ");
@@ -69,22 +99,126 @@ class CassandraQueryFactory {
       if (isStaticColumn) {
         stringBuffer.append(" STATIC");
       }
-      if(isPrimaryKey) {
+      if (isPrimaryKey) {
         stringBuffer.append("  PRIMARY KEY ");
       }
       isCommaNeeded = true;
     }
 
+    if (cassandraKey != null) {
+      List<PartitionKeyField> pkey = cassandraKey.getPartitionKeyFields();
+      if (pkey != null) {
+        stringBuffer.append(", PRIMARY KEY (");
+        boolean isCommaNeededToApply = false;
+        for (PartitionKeyField keyField : pkey) {
+          if (isCommaNeededToApply) {
+            stringBuffer.append(",");
+          }
+          if (keyField.isComposite()) {
+            stringBuffer.append("(");
+            boolean isCommaNeededHere = false;
+            for (Field field : keyField.getFields()) {
+              if (isCommaNeededHere) {
+                stringBuffer.append(", ");
+              }
+              stringBuffer.append(field.getColumnName());
+              isCommaNeededHere = true;
+            }
+            stringBuffer.append(")");
+          } else {
+            stringBuffer.append(keyField.getColumnName());
+          }
+          isCommaNeededToApply = true;
+        }
+        stringBuffer.append(")");
+      }
+    }
+
     stringBuffer.append(")");
-    if(Boolean.parseBoolean(mapping.getProperty("compactStorage"))) {
+    boolean isWithNeeded = true;
+    if (Boolean.parseBoolean(mapping.getProperty("compactStorage"))) {
       stringBuffer.append(" WITH COMPACT STORAGE ");
-    } else {
-      String id = mapping.getProperty("id");
-      if (id != null) {
-        stringBuffer.append(" WITH ID = '").append(id).append("'");
+      isWithNeeded = false;
+    }
+
+    String id = mapping.getProperty("id");
+    if (id != null) {
+      if (isWithNeeded) {
+        stringBuffer.append(" WITH ");
+      } else {
+        stringBuffer.append(" AND ");
+      }
+      stringBuffer.append("ID = '").append(id).append("'");
+      isWithNeeded = false;
+    }
+    if (cassandraKey != null) {
+      List<ClusterKeyField> clusterKeyFields = 
cassandraKey.getClusterKeyFields();
+      if (clusterKeyFields != null) {
+        if (isWithNeeded) {
+          stringBuffer.append(" WITH ");
+        } else {
+          stringBuffer.append(" AND ");
+        }
+        stringBuffer.append(" CLUSTERING ORDER BY (");
+        boolean isCommaNeededToApply = false;
+        for (ClusterKeyField keyField : clusterKeyFields) {
+          if (isCommaNeededToApply) {
+            stringBuffer.append(", ");
+          }
+          stringBuffer.append(keyField.getColumnName()).append(" ");
+          if (keyField.getOrder() != null) {
+            stringBuffer.append(keyField.getOrder());
+          }
+          isCommaNeededToApply = true;
+        }
+        stringBuffer.append(")");
       }
     }
     return stringBuffer.toString();
   }
 
+  private static StringBuilder processFields(StringBuilder stringBuilder, 
Field field, boolean isCommaNeeded) {
+    if (isCommaNeeded) {
+      stringBuilder.append(", ");
+    }
+    stringBuilder.append(field.getColumnName()).append(" 
").append(field.getType());
+    boolean isStaticColumn = Boolean.parseBoolean(field.getProperty("static"));
+    if (isStaticColumn) {
+      stringBuilder.append(" STATIC");
+    }
+    return stringBuilder;
+  }
+
+  /**
+   * This method returns the CQL query to drop table.
+   * refer : 
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/drop_table_r.html
+   *
+   * @param mapping Cassandra Mapping
+   * @return CQL query
+   */
+  static String getDropTableQuery(CassandraMapping mapping) {
+    return "DROP TABLE IF EXISTS " + mapping.getKeySpace().getName() + "." + 
mapping.getCoreName();
+  }
+
+  /**
+   * This method returns the CQL query to drop key space.
+   * refer : 
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/drop_keyspace_r.html
+   *
+   * @param mapping Cassandra Mapping
+   * @return CQL query
+   */
+  static String getDropKeySpaceQuery(CassandraMapping mapping) {
+    return "DROP KEYSPACE IF EXISTS " + mapping.getKeySpace().getName();
+  }
+
+  /**
+   * This method returns the CQL query to truncate (removes all the data) in 
the table.
+   * refer : 
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/truncate_r.html
+   *
+   * @param mapping Cassandra Mapping
+   * @return CQL query
+   */
+  static String getTruncateTableQuery(CassandraMapping mapping) {
+    return "TRUNCATE TABLE " + mapping.getKeySpace().getName() + "." + 
mapping.getCoreName();
+  }
 }

http://git-wip-us.apache.org/repos/asf/gora/blob/89109b85/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraStore.java
----------------------------------------------------------------------
diff --git 
a/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraStore.java
 
b/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraStore.java
index fad0fd4..113d0c4 100644
--- 
a/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraStore.java
+++ 
b/gora-cassandra-cql/src/main/java/org/apache/gora/cassandra/store/CassandraStore.java
@@ -20,12 +20,14 @@ package org.apache.gora.cassandra.store;
 import com.datastax.driver.core.Cluster;
 import com.datastax.driver.core.ConsistencyLevel;
 import com.datastax.driver.core.HostDistance;
+import com.datastax.driver.core.KeyspaceMetadata;
 import com.datastax.driver.core.PoolingOptions;
 import com.datastax.driver.core.ProtocolOptions;
 import com.datastax.driver.core.ProtocolVersion;
 import com.datastax.driver.core.QueryOptions;
 import com.datastax.driver.core.Session;
 import com.datastax.driver.core.SocketOptions;
+import com.datastax.driver.core.TableMetadata;
 import com.datastax.driver.core.TypeCodec;
 import com.datastax.driver.core.policies.ConstantReconnectionPolicy;
 import com.datastax.driver.core.policies.DCAwareRoundRobinPolicy;
@@ -249,7 +251,7 @@ public class CassandraStore<K, T extends Persistent> 
implements DataStore<K, T>
           Element partitionKeys = key.getChild("partitionKey");
           Element clusterKeys = key.getChild("clusterKey");
           List<Element> partitionKeyFields = 
partitionKeys.getChildren("field");
-          List<Element> partitionCompositeKeyFields = 
partitionKeys.getChildren("compositeField");
+          List<Element> partitionCompositeKeyFields = 
partitionKeys.getChildren("compositeKey");
           // process non composite partition keys
           for (Element partitionKeyField : partitionKeyFields) {
             PartitionKeyField fieldKey = new PartitionKeyField();
@@ -458,7 +460,7 @@ public class CassandraStore<K, T extends Persistent> 
implements DataStore<K, T>
           break;
         }
         default:
-          LOG.error("Unsupported Cassandra load balancing " + "policy: " + 
loadBalancingProp);
+          LOG.error("Unsupported Cassandra load balancing  policy: {} ", 
loadBalancingProp);
           break;
       }
     }
@@ -549,7 +551,7 @@ public class CassandraStore<K, T extends Persistent> 
implements DataStore<K, T>
           break;
         }
         default:
-          LOG.error("Unsupported reconnection policy " + reconnectionPolicy);
+          LOG.error("Unsupported reconnection policy : {} ", 
reconnectionPolicy);
       }
     }
     return builder;
@@ -578,7 +580,7 @@ public class CassandraStore<K, T extends Persistent> 
implements DataStore<K, T>
           builder = builder.withRetryPolicy(new 
LoggingRetryPolicy(FallthroughRetryPolicy.INSTANCE));
           break;
         default:
-          LOG.error("Unsupported retry policy " + retryPolicy);
+          LOG.error("Unsupported retry policy : {} ", retryPolicy);
           break;
       }
     }
@@ -643,20 +645,23 @@ public class CassandraStore<K, T extends Persistent> 
implements DataStore<K, T>
 
   @Override
   public String getSchemaName() {
-    return null;
+    return mapping.getCoreName();
   }
 
   @Override
   public void createSchema() {
-    LOG.debug("creating Cassandra keyspace");
+    LOG.debug("creating Cassandra keyspace {}", 
mapping.getKeySpace().getName());
     
this.session.execute(CassandraQueryFactory.getCreateKeySpaceQuery(mapping));
-    LOG.debug("creating Cassandra column family / table");
+    LOG.debug("creating Cassandra column family / table {}", 
mapping.getCoreName());
     this.session.execute(CassandraQueryFactory.getCreateTableQuery(mapping));
   }
 
   @Override
   public void deleteSchema() {
-
+    LOG.debug("dropping Cassandra table {}", mapping.getCoreName());
+    this.session.execute(CassandraQueryFactory.getDropTableQuery(mapping));
+    LOG.debug("dropping Cassandra keyspace {}", 
mapping.getKeySpace().getName());
+    this.session.execute(CassandraQueryFactory.getDropKeySpaceQuery(mapping));
   }
 
   @Override
@@ -765,11 +770,19 @@ public class CassandraStore<K, T extends Persistent> 
implements DataStore<K, T>
 
   @Override
   public void truncateSchema() {
+    LOG.debug("truncating Cassandra table {}", mapping.getCoreName());
+    this.session.execute(CassandraQueryFactory.getTruncateTableQuery(mapping));
   }
 
   @Override
   public boolean schemaExists() {
-    return false;
+    KeyspaceMetadata keyspace = 
cluster.getMetadata().getKeyspace(mapping.getKeySpace().getName());
+    if (keyspace != null) {
+      TableMetadata table = keyspace.getTable(mapping.getCoreName());
+      return table != null;
+    } else {
+      return false;
+    }
   }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/gora/blob/89109b85/gora-cassandra-cql/src/test/conf/compositeKey/gora-cassandra-mapping.xml
----------------------------------------------------------------------
diff --git 
a/gora-cassandra-cql/src/test/conf/compositeKey/gora-cassandra-mapping.xml 
b/gora-cassandra-cql/src/test/conf/compositeKey/gora-cassandra-mapping.xml
new file mode 100644
index 0000000..556d553
--- /dev/null
+++ b/gora-cassandra-cql/src/test/conf/compositeKey/gora-cassandra-mapping.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one or more
+  ~  contributor license agreements.  See the NOTICE file distributed with
+  ~  this work for additional information regarding copyright ownership.
+  ~  The ASF licenses this file to You under the Apache License, Version 2.0
+  ~  (the "License"); you may not use this file except in compliance with
+  ~  the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+<!--
+   The value of 'host' attribute of keyspace tag should match exactly what is 
in
+   gora.properties file. Essentially this means that if you are using port 
number, you should
+   use it every where regardless of whether it is the default port or not.
+   At runtime Gora will otherwise try to connect to localhost
+   https://issues.apache.org/jira/browse/GORA-269
+
+   The values of 'replication_factor' and 'placement_strategy' attribute of 
keyspace tag
+   only apply if gora create the kyespace. they have no effect if this is 
being used against 
+   an existing keyspace. the default value for 'replication_factor' is '1'
+   
+   The value of 'placement_strategy' should be a fully qualifed class name 
that is known to
+   the cassansra cluster, not the application or gora. As of this writing, the 
classes that ship
+   with cassandra are:
+   'org.apache.cassandra.locator.SimpleStrategy'
+   'org.apache.cassandra.locator.NetworkTopologyStrategy'
+   gora cassandra would use SimpleStrategy by default if no value for this 
attribute is specified
+   
+   The default value of 'gc_grace_seconds' is '0' which is ONLY VIABLE FOR 
SINGLE NODE
+   CLUSTER. you should update this value according to your cluster 
configuration. 
+   https://wiki.apache.org/cassandra/StorageConfiguration
+
+   The value of 'ttl' (time to live) attribute of field tag should most likely 
always
+   be zero unless you want Cassandra to create Tombstones and delete portions 
of your
+   data once this period expires. Any positive value is read and bound to the 
number
+   of seconds after which the value for that field will disappear. The default 
value of ttl
+   is '0'
+
+   More information on gora-cassandra configuration and mapping's can be found
+   at http://gora.apache.org/current/gora-cassandra.html
+-->
+
+
+<gora-otd>
+    <keyspace name="EmployeeSpace" durableWrite="false">
+        <placementStrategy name="SimpleStrategy" replication_factor="1"/>
+    </keyspace>
+
+    <class name="org.apache.gora.examples.generated.Employee" 
keyClass="org.apache.gora.examples.generated.WebPage" keyspace="EmployeeSpace"
+           table="Employee"  compactStorage="true" id="31323131">
+        <field name="name" column="name" type="text" ttl="10"/>
+        <field name="dateOfBirth" column="dob" type="timestamp" ttl="10"/>
+    </class>
+
+    <cassandraKey name="org.apache.gora.examples.generated.WebPage">
+        <partitionKey>
+            <compositeKey>
+                <field name="city" column="city" type="text"/>
+                <field name="country" column="country" type="text"/>
+            </compositeKey>
+            <field name="employerId" column="empID" type="int"/>
+            <field name="departmentId" column="deptID" type="int"/>
+        </partitionKey>
+        <clusterKey>
+            <field name="joinDate" column="joinDate" type="timestamp" 
order="desc"/>
+        </clusterKey>
+    </cassandraKey>
+
+</gora-otd>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/gora/blob/89109b85/gora-cassandra-cql/src/test/java/org/apache/gora/cassandra/store/TestCassandraStoreWithNativeSerialization.java
----------------------------------------------------------------------
diff --git 
a/gora-cassandra-cql/src/test/java/org/apache/gora/cassandra/store/TestCassandraStoreWithNativeSerialization.java
 
b/gora-cassandra-cql/src/test/java/org/apache/gora/cassandra/store/TestCassandraStoreWithNativeSerialization.java
index 217dea3..5bb1114 100644
--- 
a/gora-cassandra-cql/src/test/java/org/apache/gora/cassandra/store/TestCassandraStoreWithNativeSerialization.java
+++ 
b/gora-cassandra-cql/src/test/java/org/apache/gora/cassandra/store/TestCassandraStoreWithNativeSerialization.java
@@ -26,7 +26,7 @@ public class TestCassandraStoreWithNativeSerialization {
   public static void setUpClass() throws Exception {
     setProperties();
     testDriver.setParameters(parameter);
-//    testDriver.setUpClass();
+    testDriver.setUpClass();
     userDataStore = testDriver.createDataStore(UUID.class, User.class);
   }
 
@@ -47,7 +47,7 @@ public class TestCassandraStoreWithNativeSerialization {
 
   @AfterClass
   public static void tearDownClass() throws Exception {
-//    testDriver.tearDownClass();
+    testDriver.tearDownClass();
   }
 
   /**
@@ -84,4 +84,34 @@ public class TestCassandraStoreWithNativeSerialization {
     User deletedUser = userDataStore.get(id);
     Assert.assertNull(deletedUser);
   }
+
+  /**
+   * In this test case, schema exists method behavior of the data store is 
testing.
+   */
+  @Test
+  public void testSchemaExists() {
+    userDataStore.deleteSchema();
+    Assert.assertFalse(userDataStore.schemaExists());
+    userDataStore.createSchema();
+    Assert.assertTrue(userDataStore.schemaExists());
+  }
+
+  /**
+   * In this test case, schema exists method behavior of the data store is 
testing.
+   */
+  @Test
+  public void testTruncateSchema() {
+    if(!userDataStore.schemaExists()) {
+      userDataStore.createSchema();
+    }
+    UUID id = UUID.randomUUID();
+    User user1 = new User(id, "Madhawa Kasun", Date.from(Instant.now()));
+    userDataStore.put(id, user1);
+    User olduser =  userDataStore.get(id);
+    Assert.assertEquals(olduser.getName(), user1.getName());
+    Assert.assertEquals(olduser.getDateOfBirth(), user1.getDateOfBirth());
+    userDataStore.truncateSchema();
+    olduser =  userDataStore.get(id);
+    Assert.assertNull(olduser);
+  }
 }

Reply via email to