diff --git a/pom.xml b/pom.xml index 60a0e08..6f08394 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ UTF-8 2.0.2.2 - 2.1.4 + 2.1.5 2.1.2 16.0.1 diff --git a/src/main/java/casser/core/AbstractSessionOperations.java b/src/main/java/casser/core/AbstractSessionOperations.java index 935e000..cc9be27 100644 --- a/src/main/java/casser/core/AbstractSessionOperations.java +++ b/src/main/java/casser/core/AbstractSessionOperations.java @@ -26,6 +26,7 @@ import com.datastax.driver.core.RegularStatement; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSetFuture; import com.datastax.driver.core.Session; +import com.datastax.driver.core.Statement; import com.datastax.driver.core.querybuilder.BuiltStatement; public abstract class AbstractSessionOperations { @@ -40,27 +41,13 @@ public abstract class AbstractSessionOperations { abstract public Executor getExecutor(); - public ResultSet execute(String cql) { + public ResultSet execute(Statement statement) { - try { - - if (logger.isInfoEnabled()) { - logger.info("Execute query " + cql); - } - - if (isShowCql() && cql != null) { - System.out.println(cql); - } - - return currentSession().execute(cql); - } - catch(RuntimeException e) { - throw translateException(e); - } + return executeAsync(statement).getUninterruptibly(); } - public ResultSetFuture executeAsync(BuiltStatement statement) { + public ResultSetFuture executeAsync(Statement statement) { try { @@ -70,20 +57,30 @@ public abstract class AbstractSessionOperations { if (isShowCql()) { - RegularStatement regular = statement.setForceNoValues(true); - - String cql = regular.getQueryString(); - - System.out.println(cql); - - return currentSession().executeAsync(regular); - } - else { + if (statement instanceof BuiltStatement) { + + BuiltStatement builtStatement = (BuiltStatement) statement; - return currentSession().executeAsync(statement); + RegularStatement regularStatement = builtStatement.setForceNoValues(true); + + System.out.println(regularStatement.getQueryString()); + } + else if (statement instanceof RegularStatement) { + + RegularStatement regularStatement = (RegularStatement) statement; + + System.out.println(regularStatement.getQueryString()); + + } + else { + System.out.println(statement.toString()); + } + } + return currentSession().executeAsync(statement); + } catch(RuntimeException e) { throw translateException(e); diff --git a/src/main/java/casser/core/CasserSession.java b/src/main/java/casser/core/CasserSession.java index 58ff0c1..d5752d1 100644 --- a/src/main/java/casser/core/CasserSession.java +++ b/src/main/java/casser/core/CasserSession.java @@ -270,10 +270,8 @@ public class CasserSession extends AbstractSessionOperations implements Closeabl } private void dropEntity(CasserMappingEntity entity) { - - String cql = SchemaUtil.dropTableCql(entity); - - execute(cql); + + execute(SchemaUtil.dropTable(entity)); } diff --git a/src/main/java/casser/core/SchemaUtil.java b/src/main/java/casser/core/SchemaUtil.java index 2866028..f150295 100644 --- a/src/main/java/casser/core/SchemaUtil.java +++ b/src/main/java/casser/core/SchemaUtil.java @@ -21,6 +21,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import casser.mapping.CasserEntityType; import casser.mapping.CasserMappingEntity; import casser.mapping.CasserMappingProperty; import casser.mapping.CqlUtil; @@ -29,29 +30,49 @@ import casser.support.CasserMappingException; import com.datastax.driver.core.ColumnMetadata; import com.datastax.driver.core.DataType; +import com.datastax.driver.core.RegularStatement; +import com.datastax.driver.core.SimpleStatement; import com.datastax.driver.core.TableMetadata; import com.datastax.driver.core.schemabuilder.Alter; import com.datastax.driver.core.schemabuilder.Create; import com.datastax.driver.core.schemabuilder.Create.Options; +import com.datastax.driver.core.schemabuilder.CreateType; import com.datastax.driver.core.schemabuilder.SchemaBuilder; +import com.datastax.driver.core.schemabuilder.SchemaStatement; public final class SchemaUtil { private SchemaUtil() { } - public static String useCql(String keyspace, boolean forceQuote) { + public static RegularStatement use(String keyspace, boolean forceQuote) { if (forceQuote) { - return "USE " + keyspace; + return new SimpleStatement("USE" + CqlUtil.forceQuote(keyspace)); } else { - return "USE" + CqlUtil.forceQuote(keyspace); + return new SimpleStatement("USE " + keyspace); } } + + public static SchemaStatement createUserType(CasserMappingEntity entity) { - public static String createTableCql(CasserMappingEntity entity) { + if (entity.getType() != CasserEntityType.USER_DEFINED_TYPE) { + throw new CasserMappingException("expected user defined type entity " + entity); + } + + CreateType create = SchemaBuilder.createType(entity.getName()); + - Create create = SchemaBuilder.createTable(entity.getTableName()); + return create; + } + + public static SchemaStatement createTable(CasserMappingEntity entity) { + + if (entity.getType() != CasserEntityType.TABLE) { + throw new CasserMappingException("expected table entity " + entity); + } + + Create create = SchemaBuilder.createTable(entity.getName()); List> partitionKeys = new ArrayList>(); List> clusteringColumns = new ArrayList>(); @@ -102,16 +123,20 @@ public final class SchemaUtil { } - return create.buildInternal(); + return create; } - public static String alterTableCql(TableMetadata tmd, + public static List alterTable(TableMetadata tmd, CasserMappingEntity entity, boolean dropRemovedColumns) { - boolean altered = false; + if (entity.getType() != CasserEntityType.TABLE) { + throw new CasserMappingException("expected table entity " + entity); + } + + List result = new ArrayList(); - Alter alter = SchemaBuilder.alterTable(entity.getTableName()); + Alter alter = SchemaBuilder.alterTable(entity.getName()); final Set visitedColumns = dropRemovedColumns ? new HashSet() : Collections. emptySet(); @@ -138,32 +163,40 @@ public final class SchemaUtil { throw new CasserMappingException( "unable to alter column that is a part of primary key '" + columnName + "' for entity " - + entity.getName()); + + entity); } if (columnMetadata == null) { - alter.addColumn(columnName).type(columnDataType); - altered = true; + result.add(alter.addColumn(columnName).type(columnDataType)); } else { - alter.alterColumn(columnName).type(columnDataType); - altered = true; + result.add(alter.alterColumn(columnName).type(columnDataType)); } } - - if (altered) { - return alter.buildInternal(); + + if (dropRemovedColumns) { + for (ColumnMetadata cm : tmd.getColumns()) { + if (!visitedColumns.contains(cm.getName())) { + + result.add(alter.dropColumn(cm.getName())); + + } + } } - return null; + return result; } - public static String dropTableCql(CasserMappingEntity entity) { + public static SchemaStatement dropTable(CasserMappingEntity entity) { - return SchemaBuilder.dropTable(entity.getTableName()).buildInternal(); + if (entity.getType() != CasserEntityType.TABLE) { + throw new CasserMappingException("expected table entity " + entity); + } + + return SchemaBuilder.dropTable(entity.getName()); } diff --git a/src/main/java/casser/core/SessionInitializer.java b/src/main/java/casser/core/SessionInitializer.java index c2c9e47..790f769 100644 --- a/src/main/java/casser/core/SessionInitializer.java +++ b/src/main/java/casser/core/SessionInitializer.java @@ -140,13 +140,13 @@ public class SessionInitializer extends AbstractSessionOperations { } public SessionInitializer use(String keyspace) { - session.execute(SchemaUtil.useCql(keyspace, false)); + session.execute(SchemaUtil.use(keyspace, false)); this.usingKeyspace = keyspace; return this; } public SessionInitializer use(String keyspace, boolean forceQuote) { - session.execute(SchemaUtil.useCql(keyspace, forceQuote)); + session.execute(SchemaUtil.use(keyspace, forceQuote)); this.usingKeyspace = keyspace; return this; } @@ -236,7 +236,7 @@ public class SessionInitializer extends AbstractSessionOperations { } private TableMetadata getTableMetadata(CasserMappingEntity entity) { - String tableName = entity.getTableName(); + String tableName = entity.getName(); return getKeyspaceMetadata().getTable(tableName.toLowerCase()); } diff --git a/src/main/java/casser/core/TableOperations.java b/src/main/java/casser/core/TableOperations.java index a88a41f..f48c7bb 100644 --- a/src/main/java/casser/core/TableOperations.java +++ b/src/main/java/casser/core/TableOperations.java @@ -15,10 +15,16 @@ */ package casser.core; +import java.util.List; + import casser.mapping.CasserMappingEntity; import casser.support.CasserException; +import com.datastax.driver.core.RegularStatement; import com.datastax.driver.core.TableMetadata; +import com.datastax.driver.core.querybuilder.Batch; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.schemabuilder.SchemaStatement; public final class TableOperations { @@ -31,23 +37,19 @@ public final class TableOperations { } public void createTable(CasserMappingEntity entity) { - - String cql = SchemaUtil.createTableCql(entity); - - sessionOps.execute(cql); - + sessionOps.execute(SchemaUtil.createTable(entity)); } public void validateTable(TableMetadata tmd, CasserMappingEntity entity) { if (tmd == null) { - throw new CasserException("table not exists " + entity.getTableName() + "for entity " + entity.getMappingInterface()); + throw new CasserException("table not exists " + entity.getName() + "for entity " + entity.getMappingInterface()); } - String cql = SchemaUtil.alterTableCql(tmd, entity, dropRemovedColumns); + List list = SchemaUtil.alterTable(tmd, entity, dropRemovedColumns); - if (cql != null) { - throw new CasserException("schema changed for entity " + entity.getMappingInterface() + ", apply this command: " + cql); + if (!list.isEmpty()) { + throw new CasserException("schema changed for entity " + entity.getMappingInterface() + ", apply this command: " + list); } } @@ -57,10 +59,11 @@ public final class TableOperations { createTable(entity); } - String cql = SchemaUtil.alterTableCql(tmd, entity, dropRemovedColumns); + List list = SchemaUtil.alterTable(tmd, entity, dropRemovedColumns); - if (cql != null) { - sessionOps.execute(cql); + if (!list.isEmpty()) { + Batch b = QueryBuilder.batch(list.toArray(new RegularStatement[list.size()])); + sessionOps.execute(b); } } diff --git a/src/main/java/casser/core/UserTypeOperations.java b/src/main/java/casser/core/UserTypeOperations.java index 806feee..b419c3b 100644 --- a/src/main/java/casser/core/UserTypeOperations.java +++ b/src/main/java/casser/core/UserTypeOperations.java @@ -15,7 +15,7 @@ */ package casser.core; -import casser.mapping.CasserMappingUserType; +import casser.mapping.CasserMappingEntity; import com.datastax.driver.core.UserType; @@ -27,16 +27,18 @@ public final class UserTypeOperations { this.sessionOps = sessionOps; } - public void createUserType(String name, CasserMappingUserType type) { + public void createUserType(String name, CasserMappingEntity entity) { + + } - public void validateUserType(String name, UserType userType, CasserMappingUserType type) { + public void validateUserType(String name, UserType userType, CasserMappingEntity entity) { } - public void updateUserType(String name, UserType userType, CasserMappingUserType type) { + public void updateUserType(String name, UserType userType, CasserMappingEntity entity) { } diff --git a/src/main/java/casser/core/operation/CountOperation.java b/src/main/java/casser/core/operation/CountOperation.java index 84eca11..f480de2 100644 --- a/src/main/java/casser/core/operation/CountOperation.java +++ b/src/main/java/casser/core/operation/CountOperation.java @@ -38,7 +38,7 @@ public final class CountOperation extends AbstractFilterOperation extends AbstractFilterStreamOperation entity, Object pojo) { super(sessionOperations); - this.insert = QueryBuilder.insertInto(entity.getTableName()); + this.insert = QueryBuilder.insertInto(entity.getName()); for (CasserMappingProperty prop : entity.getMappingProperties()) { diff --git a/src/main/java/casser/mapping/CasserEntity.java b/src/main/java/casser/mapping/CasserEntity.java index 0bca432..7ec12b1 100644 --- a/src/main/java/casser/mapping/CasserEntity.java +++ b/src/main/java/casser/mapping/CasserEntity.java @@ -19,9 +19,9 @@ import java.util.Collection; public interface CasserEntity { - String getName(); + CasserEntityType getType(); - String getTableName(); + String getName(); Collection> getProperties(); diff --git a/src/main/java/casser/mapping/CasserMappingUserType.java b/src/main/java/casser/mapping/CasserEntityType.java similarity index 77% rename from src/main/java/casser/mapping/CasserMappingUserType.java rename to src/main/java/casser/mapping/CasserEntityType.java index 10237bd..aee9fd9 100644 --- a/src/main/java/casser/mapping/CasserMappingUserType.java +++ b/src/main/java/casser/mapping/CasserEntityType.java @@ -15,15 +15,6 @@ */ package casser.mapping; -public class CasserMappingUserType implements CasserUserType { - - public CasserMappingUserType(Class clazz) { - - } - - @Override - public String getName() { - return null; - } - +public enum CasserEntityType { + TABLE, USER_DEFINED_TYPE; } diff --git a/src/main/java/casser/mapping/CasserMappingEntity.java b/src/main/java/casser/mapping/CasserMappingEntity.java index 38c98e7..24b7f90 100644 --- a/src/main/java/casser/mapping/CasserMappingEntity.java +++ b/src/main/java/casser/mapping/CasserMappingEntity.java @@ -72,12 +72,17 @@ public class CasserMappingEntity implements CasserEntity { } + @Override + public CasserEntityType getType() { + return CasserEntityType.TABLE; + } + public Class getMappingInterface() { return iface; } @Override - public String getName() { + public String toString() { return iface.toString(); } @@ -91,7 +96,7 @@ public class CasserMappingEntity implements CasserEntity { } @Override - public String getTableName() { + public String getName() { if (tableName == null) { diff --git a/src/main/java/casser/mapping/CasserMappingRepository.java b/src/main/java/casser/mapping/CasserMappingRepository.java index 09b21d7..1609686 100644 --- a/src/main/java/casser/mapping/CasserMappingRepository.java +++ b/src/main/java/casser/mapping/CasserMappingRepository.java @@ -27,7 +27,7 @@ public class CasserMappingRepository { private final Map, CasserMappingEntity> entityMap = new HashMap, CasserMappingEntity>(); - private final Map> udtMap = new HashMap>(); + private final Map> udtMap = new HashMap>(); private boolean readOnly = false; @@ -42,15 +42,15 @@ public class CasserMappingRepository { throw new CasserException("read-only mode"); } - udtMap.putIfAbsent(name, new CasserMappingUserType(userTypeClass)); + udtMap.putIfAbsent(name, new CasserMappingEntity(userTypeClass)); } - public Map> knownUserTypes() { + public Map> knownUserTypes() { return Collections.unmodifiableMap(udtMap); } - public CasserMappingUserType findUserType(Class userTypeClass) { + public CasserMappingEntity findUserType(Class userTypeClass) { return udtMap.get(userTypeClass); } diff --git a/src/main/java/casser/mapping/CasserUserType.java b/src/main/java/casser/mapping/CasserUserType.java index 28813b7..fb76539 100644 --- a/src/main/java/casser/mapping/CasserUserType.java +++ b/src/main/java/casser/mapping/CasserUserType.java @@ -15,8 +15,12 @@ */ package casser.mapping; +import java.util.Collection; + public interface CasserUserType { - public String getName(); + String getName(); + + Collection> getProperties(); } diff --git a/src/test/java/casser/test/integration/core/usertype/Account.java b/src/test/java/casser/test/integration/core/usertype/Account.java index 3ec1dd4..fa91089 100644 --- a/src/test/java/casser/test/integration/core/usertype/Account.java +++ b/src/test/java/casser/test/integration/core/usertype/Account.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2015 Noorq, Inc. + * + * Licensed 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. + */ package casser.test.integration.core.usertype; import casser.mapping.PartitionKey; diff --git a/src/test/java/casser/test/integration/core/usertype/Address.java b/src/test/java/casser/test/integration/core/usertype/Address.java index 4138dd8..b7560fd 100644 --- a/src/test/java/casser/test/integration/core/usertype/Address.java +++ b/src/test/java/casser/test/integration/core/usertype/Address.java @@ -1,50 +1,41 @@ +/* + * Copyright (C) 2015 Noorq, Inc. + * + * Licensed 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. + */ package casser.test.integration.core.usertype; import casser.mapping.Field; import casser.mapping.UserDefinedType; @UserDefinedType("address") -public class Address { +public interface Address { @Field("line_1") - private String street; + String getStreet(); - private String city; + void setStreet(String street); - private int zip; + String getCity(); - private String country; + void setCity(String city); - public String getStreet() { - return street; - } + int getZip(); - public void setStreet(String street) { - this.street = street; - } + void setZip(int zip); - public String getCity() { - return city; - } + String getCountry(); - public void setCity(String city) { - this.city = city; - } - - public int getZip() { - return zip; - } - - public void setZip(int zip) { - this.zip = zip; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } + void setCountry(String country); } diff --git a/src/test/java/casser/test/integration/core/usertype/UserDefinedTypeTest.java b/src/test/java/casser/test/integration/core/usertype/UserDefinedTypeTest.java index 22b744c..ace8249 100644 --- a/src/test/java/casser/test/integration/core/usertype/UserDefinedTypeTest.java +++ b/src/test/java/casser/test/integration/core/usertype/UserDefinedTypeTest.java @@ -1,5 +1,22 @@ +/* + * Copyright (C) 2015 Noorq, Inc. + * + * Licensed 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. + */ package casser.test.integration.core.usertype; +import java.util.regex.Pattern; + import org.junit.Before; import org.junit.Test; @@ -7,24 +24,100 @@ import casser.core.Casser; import casser.core.CasserSession; import casser.test.integration.build.AbstractEmbeddedCassandraTest; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.UserType; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.querybuilder.Select; +import com.datastax.driver.core.schemabuilder.Create; +import com.datastax.driver.core.schemabuilder.CreateType; +import com.datastax.driver.core.schemabuilder.SchemaBuilder; + public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest { Account account; - CasserSession session; + CasserSession csession; @Before public void beforeTest() { account = Casser.dsl(Account.class); - //session = Casser.init(getSession()).showCql().add(Account.class).autoCreateDrop().get(); + //csession = Casser.init(getSession()).showCql().add(Account.class).autoCreateDrop().get(); + + Session session = getSession(); + + + CreateType ct = SchemaBuilder.createType("address"); + ct.addColumn("street", DataType.text()); + ct.addColumn("city", DataType.text()); + ct.addColumn("zip_code", DataType.cint()); + ct.addColumn("phones", DataType.set(DataType.text())); + String cql = ct.build(); + + System.out.println(cql); + + //session.execute("CREATE TYPE address (street text, city text, zip_code int, phones set)"); + + session.execute(cql); + + + ct = SchemaBuilder.createType("fullname"); + ct.addColumn("firstname", DataType.text()); + ct.addColumn("lastname", DataType.text()); + cql = ct.build(); + + System.out.println(cql); + + session.execute(cql); + + //session.execute("CREATE TYPE fullname (firstname text,lastname text)"); + + System.out.println("keyspace = " + session.getLoggedKeyspace()); + + KeyspaceMetadata km = session.getCluster().getMetadata().getKeyspace(session.getLoggedKeyspace()); + + UserType address = km.getUserType("address"); + UserType fullname = km.getUserType("fullname"); + + Create create = SchemaBuilder.createTable("users"); + + create.addPartitionKey("id", DataType.uuid()); + create.addUDTColumn("name", SchemaBuilder.frozen("fullname")); + create.addUDTMapColumn("addresses", DataType.ascii(), SchemaBuilder.frozen("address")); + + cql = create.buildInternal(); + + System.out.println(cql); + + session.execute(create); + + //session.execute("CREATE TABLE users (id uuid PRIMARY KEY, name fullname, " + // + "addresses map)"); + + + } @Test public void testUDT() { - System.out.println("test it"); + Session session = getSession(); + + Select select = QueryBuilder.select().column("\"name\".\"lastname\"").from("users"); + + System.out.println(select); + + ResultSet resultSet = session.execute("SELECT \"name\".\"lastname\" FROM users;"); + + System.out.println("resultSet = " + resultSet); + + + + //csession.select(account.getAddress()::getStreet).sync(); } }