SchemaUtil class to build create/alter cqls

This commit is contained in:
Albert Shift 2015-03-17 17:13:17 -07:00
parent c05d3e2737
commit ead9866e5a
5 changed files with 176 additions and 53 deletions

View file

@ -0,0 +1,121 @@
package casser.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import casser.mapping.CasserMappingEntity;
import casser.mapping.CasserMappingProperty;
import casser.support.CasserMappingException;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.DataType;
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.SchemaBuilder;
public final class SchemaUtil {
private SchemaUtil() {
}
public static String createTableCql(CasserMappingEntity<?> entity) {
Create create = SchemaBuilder.createTable(entity.getTableName());
List<CasserMappingProperty<?>> partitionKeys = new ArrayList<CasserMappingProperty<?>>();
List<CasserMappingProperty<?>> clusteringColumns = new ArrayList<CasserMappingProperty<?>>();
List<CasserMappingProperty<?>> columns = new ArrayList<CasserMappingProperty<?>>();
for (CasserMappingProperty<?> prop : entity.getMappingProperties()) {
if (prop.isPartitionKey()) {
partitionKeys.add(prop);
} else if (prop.isClusteringColumn()) {
clusteringColumns.add(prop);
} else {
columns.add(prop);
}
}
Collections
.sort(partitionKeys, OrdinalBasedPropertyComparator.INSTANCE);
Collections.sort(clusteringColumns,
OrdinalBasedPropertyComparator.INSTANCE);
for (CasserMappingProperty<?> prop : partitionKeys) {
create.addPartitionKey(prop.getColumnName(), prop.getDataType());
}
for (CasserMappingProperty<?> prop : clusteringColumns) {
create.addClusteringColumn(prop.getColumnName(), prop.getDataType());
}
for (CasserMappingProperty<?> prop : columns) {
create.addColumn(prop.getColumnName(), prop.getDataType());
}
return create.buildInternal();
}
public static String alterTableCql(TableMetadata tmd,
CasserMappingEntity<?> entity, boolean dropRemovedColumns) {
boolean altered = false;
Alter alter = SchemaBuilder.alterTable(entity.getTableName());
final Set<String> visitedColumns = dropRemovedColumns ? new HashSet<String>()
: Collections.<String> emptySet();
for (CasserMappingProperty<?> prop : entity.getMappingProperties()) {
String columnName = prop.getColumnName();
DataType columnDataType = prop.getDataType();
String loweredColumnName = columnName.toLowerCase();
if (dropRemovedColumns) {
visitedColumns.add(loweredColumnName);
}
ColumnMetadata columnMetadata = tmd.getColumn(loweredColumnName);
if (columnMetadata != null
&& columnDataType.equals(columnMetadata.getType())) {
continue;
}
if (prop.isPartitionKey() || prop.isClusteringColumn()) {
throw new CasserMappingException(
"unable to add or alter column in the primary index "
+ columnName + " for entity "
+ entity.getName());
}
if (columnMetadata == null) {
alter.addColumn(columnName).type(columnDataType);
altered = true;
} else {
alter.alterColumn(columnName).type(columnDataType);
altered = true;
}
}
if (altered) {
return alter.buildInternal();
}
return null;
}
}

View file

@ -1,19 +1,13 @@
package casser.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import casser.mapping.CasserMappingEntity;
import casser.mapping.CasserMappingProperty;
import casser.support.CasserException;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
public class SessionInitializer extends AbstractSessionOperations {
@ -22,6 +16,8 @@ public class SessionInitializer extends AbstractSessionOperations {
private boolean showCql = false;
private Set<CasserMappingEntity<?>> dropEntitiesOnClose = null;
private boolean dropRemovedColumns = false;
SessionInitializer(Session session) {
if (session == null) {
@ -46,28 +42,33 @@ public class SessionInitializer extends AbstractSessionOperations {
return this;
}
public SessionInitializer dropRemovedColumns(boolean enabled) {
this.dropRemovedColumns = enabled;
return this;
}
@Override
boolean isShowCql() {
return showCql;
}
public SessionInitializer validate(Object... dsls) {
process(AutoDslType.VALIDATE, dsls);
process(AutoDdl.VALIDATE, dsls);
return this;
}
public SessionInitializer update(Object... dsls) {
process(AutoDslType.UPDATE, dsls);
process(AutoDdl.UPDATE, dsls);
return this;
}
public SessionInitializer create(Object... dsls) {
process(AutoDslType.CREATE, dsls);
process(AutoDdl.CREATE, dsls);
return this;
}
public SessionInitializer createDrop(Object... dsls) {
process(AutoDslType.CREATE_DROP, dsls);
process(AutoDdl.CREATE_DROP, dsls);
return this;
}
@ -80,14 +81,14 @@ public class SessionInitializer extends AbstractSessionOperations {
return new CasserSession(session, showCql, dropEntitiesOnClose);
}
private enum AutoDslType {
private enum AutoDdl {
VALIDATE,
UPDATE,
CREATE,
CREATE_DROP;
}
private void process(AutoDslType type, Object[] dsls) {
private void process(AutoDdl type, Object[] dsls) {
for (Object dsl : dsls) {
processSingle(type, dsl);
@ -95,7 +96,7 @@ public class SessionInitializer extends AbstractSessionOperations {
}
private void processSingle(AutoDslType type, Object dsl) {
private void processSingle(AutoDdl type, Object dsl) {
Class<?> iface = null;
@ -120,13 +121,13 @@ public class SessionInitializer extends AbstractSessionOperations {
CasserMappingEntity<?> entity = new CasserMappingEntity(iface);
if (type == AutoDslType.CREATE || type == AutoDslType.CREATE_DROP) {
if (type == AutoDdl.CREATE || type == AutoDdl.CREATE_DROP) {
createNewTable(entity);
}
else {
TableMetadata tmd = getTableMetadata(entity);
if (type == AutoDslType.VALIDATE) {
if (type == AutoDdl.VALIDATE) {
if (tmd == null) {
throw new CasserException("table not exists " + entity.getTableName() + "for entity " + entity.getEntityInterface());
@ -134,7 +135,7 @@ public class SessionInitializer extends AbstractSessionOperations {
validateTable(tmd, entity);
}
else if (type == AutoDslType.UPDATE) {
else if (type == AutoDdl.UPDATE) {
if (tmd == null) {
createNewTable(entity);
@ -146,7 +147,7 @@ public class SessionInitializer extends AbstractSessionOperations {
}
}
if (type == AutoDslType.CREATE_DROP) {
if (type == AutoDdl.CREATE_DROP) {
getOrCreateDropEntitiesSet().add(entity);
}
@ -169,42 +170,7 @@ public class SessionInitializer extends AbstractSessionOperations {
private void createNewTable(CasserMappingEntity<?> entity) {
Create create = SchemaBuilder.createTable(entity.getTableName());
List<CasserMappingProperty<?>> partitionKeys = new ArrayList<CasserMappingProperty<?>>();
List<CasserMappingProperty<?>> clusteringColumns = new ArrayList<CasserMappingProperty<?>>();
List<CasserMappingProperty<?>> columns = new ArrayList<CasserMappingProperty<?>>();
for (CasserMappingProperty<?> prop : entity.getMappingProperties()) {
if (prop.isPartitionKey()) {
partitionKeys.add(prop);
}
else if (prop.isClusteringColumn()) {
clusteringColumns.add(prop);
}
else {
columns.add(prop);
}
}
Collections.sort(partitionKeys, OrdinalBasedPropertyComparator.INSTANCE);
Collections.sort(clusteringColumns, OrdinalBasedPropertyComparator.INSTANCE);
for (CasserMappingProperty<?> prop : partitionKeys) {
create.addPartitionKey(prop.getColumnName(), prop.getDataType());
}
for (CasserMappingProperty<?> prop : clusteringColumns) {
create.addClusteringColumn(prop.getColumnName(), prop.getDataType());
}
for (CasserMappingProperty<?> prop : columns) {
create.addColumn(prop.getColumnName(), prop.getDataType());
}
String cql = create.getQueryString();
String cql = SchemaUtil.createTableCql(entity);
doExecute(cql);
@ -212,9 +178,19 @@ public class SessionInitializer extends AbstractSessionOperations {
private void validateTable(TableMetadata tmd, CasserMappingEntity<?> entity) {
String cql = SchemaUtil.alterTableCql(tmd, entity, dropRemovedColumns);
if (cql != null) {
throw new CasserException("schema changed for entity " + entity.getEntityInterface() + ", apply this command: " + cql);
}
}
private void alterTable(TableMetadata tmd, CasserMappingEntity<?> entity) {
String cql = SchemaUtil.alterTableCql(tmd, entity, dropRemovedColumns);
if (cql != null) {
doExecute(cql);
}
}
}

View file

@ -4,6 +4,8 @@ import java.util.Collection;
public interface CasserEntity<E> {
String getName();
String getTableName();
Collection<CasserProperty<E>> getProperties();

View file

@ -61,6 +61,11 @@ public class CasserMappingEntity<E> implements CasserEntity<E> {
return iface;
}
@Override
public String getName() {
return iface.toString();
}
@Override
public Collection<CasserProperty<E>> getProperties() {
return Collections.unmodifiableCollection(props.values());

View file

@ -0,0 +1,19 @@
package casser.support;
public class CasserMappingException extends CasserException {
private static final long serialVersionUID = -4730562130753392363L;
public CasserMappingException(String msg) {
super(msg);
}
public CasserMappingException(Throwable t) {
super(t);
}
public CasserMappingException(String msg, Throwable t) {
super(msg, t);
}
}