use of com.datastax.driver.mapping.meta.EntityFieldMetaData in project cassandra-driver-mapping by valchkou.
the class SchemaSync method alterTableStatements.
/**
* Compare TableMetadata against Entity metadata and generate alter statements if necessary.
* <p>
* Cannot alter clustered and primary key columns.
*
* @param class the class to generate statements for or indexed
* @return a new {@code List<RegularStatement>}.
*/
private static <T> List<RegularStatement> alterTableStatements(String keyspace, Session session, EntityTypeMetadata entityMetadata, SyncOptions syncOptions) {
boolean doNotAddCols = false;
boolean doDropCols = true;
if (syncOptions != null) {
List<SyncOptionTypes> opts = syncOptions.getOptions(entityMetadata.getEntityClass());
doNotAddCols = opts.contains(SyncOptionTypes.DoNotAddColumns);
doDropCols = !opts.contains(SyncOptionTypes.DoNotDropColumns);
}
List<RegularStatement> statements = new ArrayList<RegularStatement>();
// get EntityTypeMetadata
String table = entityMetadata.getTableName();
// get TableMetadata - requires connection to cassandra
Cluster cluster = session.getCluster();
KeyspaceMetadata keyspaceMetadata = cluster.getMetadata().getKeyspace(keyspace);
TableMetadata tableMetadata = keyspaceMetadata.getTable(table);
// build statements for a new column or a columns with changed datatype.
for (EntityFieldMetaData field : entityMetadata.getFields()) {
String column = field.getColumnName();
String fieldType = field.getDataType().name();
ColumnMetadata columnMetadata = tableMetadata.getColumn(column);
String colIndex = null;
/*if (columnMetadata!= null && columnMetadata.getIndex() != null) {
colIndex = columnMetadata.getIndex().getName();
}*/
String fieldIndex = null;
if (entityMetadata.getIndex(column) != null) {
fieldIndex = entityMetadata.getIndex(column);
}
if (columnMetadata == null) {
if (doNotAddCols)
continue;
// if column not exists in Cassandra then build add column Statement
String colType = fieldType;
if (field.isGenericType()) {
colType = field.getGenericDef();
}
AlterTable statement = new AlterTable.Builder().addColumn(keyspace, table, column, colType);
statements.add(statement);
if (fieldIndex != null) {
statements.add(new DropIndex(column, fieldIndex));
statements.add(new CreateIndex(keyspace, table, column, fieldIndex));
}
} else if (colIndex != null || fieldIndex != null) {
if (colIndex == null) {
statements.add(new CreateIndex(keyspace, table, column, fieldIndex));
} else if (fieldIndex == null) {
statements.add(new DropIndex(column, colIndex));
} else if (!"".equals(fieldIndex) && !fieldIndex.equals(colIndex)) {
statements.add(new DropIndex(column, colIndex));
statements.add(new CreateIndex(keyspace, table, column, fieldIndex));
}
} else if (!fieldType.equals(columnMetadata.getType().getName().name())) {
// can't change datatype for clustered columns
if (tableMetadata.getClusteringColumns().contains(columnMetadata)) {
continue;
}
// can't change datatype for PK columns
if (tableMetadata.getPrimaryKey().contains(columnMetadata)) {
continue;
}
// drop index if any
/*if (columnMetadata.getIndex() != null) {
statements.add(new DropIndex(column, columnMetadata.getIndex().getName()));
}*/
// alter column datatype
statements.add(new AlterTable.Builder().alterColumn(keyspace, table, column, fieldType));
// create index if any
if (entityMetadata.getIndex(column) != null) {
statements.add(new CreateIndex(keyspace, table, column, entityMetadata.getIndex(column)));
}
}
}
// column is in Cassandra but not in entity anymore
if (doDropCols) {
for (ColumnMetadata colmeta : tableMetadata.getColumns()) {
colmeta.getName();
boolean exists = false;
for (EntityFieldMetaData field : entityMetadata.getFields()) {
if (colmeta.getName().equalsIgnoreCase(field.getColumnName())) {
exists = true;
break;
}
}
if (!exists) {
AlterTable statement = new AlterTable.Builder().dropColumn(keyspace, table, colmeta.getName());
statements.add(statement);
}
}
}
return statements;
}
use of com.datastax.driver.mapping.meta.EntityFieldMetaData in project cassandra-driver-mapping by valchkou.
the class MappingBuilder method prepareRemoveItemsFromSetOrList.
public static BoundStatement prepareRemoveItemsFromSetOrList(Object id, Class<?> clazz, String propertyName, Object item, String keyspace, Session session) {
EntityTypeMetadata emeta = EntityTypeParser.getEntityMetadata(clazz);
EntityFieldMetaData fmeta = emeta.getFieldMetadata(propertyName);
Update update = QueryBuilder.update(keyspace, emeta.getTableName());
if (item instanceof Set<?> && fmeta.getType() == Set.class) {
Set<?> set = (Set<?>) item;
if (set.size() == 0)
return null;
update.with(QueryBuilder.removeAll(fmeta.getColumnName(), set));
} else if (item instanceof List<?> && fmeta.getType() == List.class) {
List<?> list = (List<?>) item;
if (list.size() == 0)
return null;
update.with(QueryBuilder.discardAll(fmeta.getColumnName(), list));
} else if (fmeta.getType() == Set.class) {
update.with(QueryBuilder.remove(fmeta.getColumnName(), item));
} else if (fmeta.getType() == List.class) {
update.with(QueryBuilder.discard(fmeta.getColumnName(), item));
}
return prepareUpdate(id, emeta, update, session);
}
use of com.datastax.driver.mapping.meta.EntityFieldMetaData in project cassandra-driver-mapping by valchkou.
the class MappingBuilder method buildUpdate.
/**
* Statement to persist an entity in Cassandra
*
* @param entity to be inserted
* @return com.datastax.driver.core.BoundStatement
*/
public static <E> BuiltStatement buildUpdate(E entity, WriteOptions options, String keyspace) {
Class<?> clazz = entity.getClass();
EntityTypeMetadata entityMetadata = EntityTypeParser.getEntityMetadata(clazz);
String table = entityMetadata.getTableName();
List<EntityFieldMetaData> fields = entityMetadata.getFields();
List<String> pkCols = entityMetadata.getPkColumns();
List<Object> pkVals = entityMetadata.getEntityPKValues(entity);
String[] columns = new String[fields.size()];
Object[] values = new Object[fields.size()];
Update update = QueryBuilder.update(keyspace, table);
EntityFieldMetaData verField = null;
Object newVersion = null;
Object oldVersion = null;
// increment and set @Version field
if (entityMetadata.hasVersion()) {
verField = entityMetadata.getVersionField();
oldVersion = verField.getValue(entity);
newVersion = incVersion(oldVersion);
verField.setValue(entity, newVersion);
update.onlyIf(eq(verField.getColumnName(), oldVersion));
}
for (int i = 0; i < fields.size(); i++) {
EntityFieldMetaData field = fields.get(i);
String colName = field.getColumnName();
Object colVal = null;
if (pkCols.contains(colName)) {
int idx = pkCols.indexOf(colName);
colVal = pkVals.get(idx);
update.where(eq(colName, colVal));
continue;
} else {
colVal = field.getValue(entity);
}
columns[i] = colName;
if (field.equals(verField)) {
values[i] = newVersion;
} else {
values[i] = colVal;
}
update.with(set(colName, colVal));
}
applyOptions(options, update, entityMetadata);
return update;
}
use of com.datastax.driver.mapping.meta.EntityFieldMetaData in project cassandra-driver-mapping by valchkou.
the class MappingBuilder method prepareSelect.
/**
* Prepare BoundStatement to select row by id
*/
public static <T> BoundStatement prepareSelect(Class<T> clazz, Object id, final ReadOptions options, final String keyspace, final Session session) {
EntityTypeMetadata entityMetadata = EntityTypeParser.getEntityMetadata(clazz);
final List<EntityFieldMetaData> fields = entityMetadata.getFields();
final List<String> pkCols = entityMetadata.getPkColumns();
final String table = entityMetadata.getTableName();
// get prepared statement
PreparedStatement ps;
try {
ps = statementCache.get(getSelectCacheKey(table, session, fields), new Callable<PreparedStatement>() {
@Override
public PreparedStatement call() throws Exception {
Select stmt = buildSelectAll(table, pkCols, options, keyspace, fields);
return session.prepare(stmt);
}
});
} catch (ExecutionException e) {
// if the error caused by prepare the client will get it as is,
// otherwise process will not blow and statement will not be cached.
Select stmt = buildSelectAll(table, pkCols, options, keyspace, fields);
ps = session.prepare(stmt);
}
// bind parameters
Object[] values = entityMetadata.getIdValues(id).toArray(new Object[pkCols.size()]);
BoundStatement bs = ps.bind(values);
return bs;
}
use of com.datastax.driver.mapping.meta.EntityFieldMetaData in project cassandra-driver-mapping by valchkou.
the class MappingBuilder method prepareSave.
public static <E> BuiltStatement prepareSave(E entity, WriteOptions options, String keyspace) {
Class<?> clazz = entity.getClass();
EntityTypeMetadata entityMetadata = EntityTypeParser.getEntityMetadata(clazz);
long version = Long.MIN_VALUE;
if (entityMetadata.hasVersion()) {
EntityFieldMetaData verField = entityMetadata.getVersionField();
version = ((Long) verField.getValue(entity)).longValue();
}
BuiltStatement stmt = null;
if (version > 0) {
stmt = buildUpdate(entity, options, keyspace);
} else {
stmt = buildInsert(entity, options, keyspace);
}
return stmt;
}
Aggregations