DATACASS-656 - Test cleanups.

Original pull request: #167.
This commit is contained in:
Mark Paluch
2019-12-11 15:42:52 +01:00
parent 100a94bfad
commit 2946f2913a
99 changed files with 1762 additions and 627 deletions

View File

@@ -95,7 +95,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
bean.setConverter(beanFactory.getBean(CassandraConverter.class));
bean.setSchemaAction(getSchemaAction());
bean.setKeyspacePopulator(keyspacePopulator());
bean.setKeyspacePopulator(keyspaceCleaner());
bean.setKeyspaceCleaner(keyspaceCleaner());
return bean;
}
@@ -161,7 +161,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
mappingContext.setInitialEntitySet(getInitialEntitySet());
CustomConversions customConversions = beanFactory.getBean(CassandraCustomConversions.class);
CustomConversions customConversions = beanFactory.getBean(CustomConversions.class);
mappingContext.setCustomConversions(customConversions);
mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder());
@@ -185,8 +185,8 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
/**
* Return the {@link Set} of initial entity classes. Scans by default the class path using
* {@link #getEntityBasePackages()}. Can be overriden by subclasses to skip class path scanning and return a fixed set
* of entity classes.
* {@link #getEntityBasePackages()}. Can be overridden by subclasses to skip class path scanning and return a fixed
* set of entity classes.
*
* @return {@link Set} of initial entity classes.
* @throws ClassNotFoundException if the entity scan fails.
@@ -200,11 +200,9 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
/**
* Creates a {@link CassandraAdminTemplate}.
*
* @throws Exception if the {@link com.datastax.driver.core.Session} could not be obtained.
*/
@Bean
public CassandraAdminTemplate cassandraTemplate() throws Exception {
public CassandraAdminTemplate cassandraTemplate() {
return new CassandraAdminTemplate(getRequiredSessionFactory(), beanFactory.getBean(CassandraConverter.class));
}
@@ -216,6 +214,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
super.setBeanFactory(beanFactory);
}
/**

View File

@@ -41,8 +41,8 @@ public abstract class AbstractReactiveCassandraConfiguration extends AbstractCas
private @Nullable BeanFactory beanFactory;
/**
* Creates a {@link ReactiveSession} object. This wraps a {@link com.datastax.driver.core.Session} to expose Cassandra
* access in a reactive style.
* Creates a {@link ReactiveSession} object. This wraps a {@link com.datastax.oss.driver.api.core.CqlSession} to
* expose Cassandra access in a reactive style.
*
* @return the {@link ReactiveSession}.
* @see #session()
@@ -93,5 +93,6 @@ public abstract class AbstractReactiveCassandraConfiguration extends AbstractCas
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
super.setBeanFactory(beanFactory);
}
}

View File

@@ -141,7 +141,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
/**
* Returns the list of startup scripts to be run after {@link #getKeyspaceCreations() keyspace creations} and after
* initialization.
* initialization in the {@code system} keyspace.
*
* @return the list of startup scripts, may be empty but never {@link null}
* @deprecated since 3.0, declare a
@@ -154,7 +154,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
/**
* Returns the list of shutdown scripts to be run after {@link #getKeyspaceDrops() keyspace drops} and right before
* shutdown.
* shutdown in the {@code system} keyspace.
*
* @return the list of shutdown scripts, may be empty but never {@link null}
* @deprecated since 3.0, declare a

View File

@@ -33,6 +33,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.core.CassandraPersistentEntitySchemaCreator;
import org.springframework.data.cassandra.core.CassandraPersistentEntitySchemaDropper;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
@@ -401,18 +402,40 @@ public class CqlSessionFactoryBean implements FactoryBean<CqlSession>, Initializ
public void afterPropertiesSet() {
CqlSessionBuilder sessionBuilder = buildBuilder();
this.systemSession = sessionBuilder.build();
this.systemSession = buildSystemSession(sessionBuilder);
initializeCluster(this.systemSession);
this.session = buildSession(sessionBuilder);
executeScripts(getStartupScripts().stream(), this.session);
performSchemaAction();
this.systemSession.refreshSchema();
this.session.refreshSchema();
}
/**
* Build the system session.
*
* @param sessionBuilder
* @return
*/
protected CqlSession buildSystemSession(CqlSessionBuilder sessionBuilder) {
return sessionBuilder.withKeyspace("system").build();
}
/**
* Build the keyspace session.
*
* @param sessionBuilder
* @return
*/
protected CqlSession buildSession(CqlSessionBuilder sessionBuilder) {
if (StringUtils.hasText(getKeyspaceName())) {
sessionBuilder.withKeyspace(getKeyspaceName());
}
this.session = sessionBuilder.build();
executeScripts(getStartupScripts().stream(), this.session);
performSchemaAction();
return sessionBuilder.build();
}
/* (non-Javadoc)
@@ -426,12 +449,26 @@ public class CqlSessionFactoryBean implements FactoryBean<CqlSession>, Initializ
executeScripts(getShutdownScripts().stream(), this.session);
executeSpecsAndScripts(keyspaceDrops, keyspaceShutdownScripts, this.systemSession);
systemSession.close();
session.close();
closeSystemSession();
closeSession();
}
}
private CqlSessionBuilder buildBuilder() {
/**
* Close the regular session object.
*/
protected void closeSession() {
session.close();
}
/**
* Close the system session object.
*/
protected void closeSystemSession() {
systemSession.close();
}
protected CqlSessionBuilder buildBuilder() {
Assert.hasText(this.contactPoints, "At least one server is required");
@@ -514,9 +551,9 @@ public class CqlSessionFactoryBean implements FactoryBean<CqlSession>, Initializ
* statement.
*/
protected void createTables(boolean drop, boolean dropUnused, boolean ifNotExists) {
// TODO
/*CassandraAdminTemplate adminTemplate = new CassandraAdminTemplate(this.session, converter);
performSchemaActions(drop, dropUnused, ifNotExists, adminTemplate);*/
CassandraAdminTemplate adminTemplate = new CassandraAdminTemplate(this.session, converter);
performSchemaActions(drop, dropUnused, ifNotExists, adminTemplate);
}
private void performSchemaActions(boolean drop, boolean dropUnused, boolean ifNotExists,

View File

@@ -131,6 +131,8 @@ public class SessionFactoryFactoryBean extends AbstractFactoryBean<SessionFactor
}
performSchemaAction();
this.session.refreshSchema();
}
@Override

View File

@@ -76,6 +76,7 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
import com.datastax.oss.driver.api.querybuilder.select.Select;
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
@@ -522,10 +523,10 @@ public class AsyncCassandraTemplate
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.select.Select> select = getStatementFactory()
.selectOneById(id, (source, sink) -> getConverter().write(source, sink, entity), entity.getTableName());
.selectOneById(id, entity, entity.getTableName());
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().queryForResultSet(select.build()),
resultSet -> resultSet.remaining() > 0);
resultSet -> resultSet.one() != null);
}
/* (non-Javadoc)
@@ -541,7 +542,7 @@ public class AsyncCassandraTemplate
.select(query.limit(1), getRequiredPersistentEntity(entityClass), getTableName(entityClass));
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().queryForResultSet(select.build()),
resultSet -> resultSet.remaining() > 0);
resultSet -> resultSet.one() != null);
}
/* (non-Javadoc)
@@ -555,8 +556,7 @@ public class AsyncCassandraTemplate
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
CqlIdentifier tableName = entity.getTableName();
StatementBuilder<Select> select = getStatementFactory().selectOneById(id,
(source, sink) -> getConverter().write(source, sink, entity), tableName);
StatementBuilder<Select> select = getStatementFactory().selectOneById(id, entity, tableName);
Function<Row, T> mapper = getMapper(entityClass, entityClass, tableName);
return new MappingListenableFutureAdapter<>(
@@ -595,11 +595,16 @@ public class AsyncCassandraTemplate
StatementBuilder<RegularInsert> builder = getStatementFactory().insert(entityToUse, options, persistentEntity,
tableName);
return source.isVersionedEntity() ? doInsertVersioned(builder.build(), entityToUse, source, tableName)
: doInsert(builder.build(), entityToUse, source, tableName);
if (source.isVersionedEntity()) {
builder.apply(Insert::ifNotExists);
return doInsertVersioned(builder.build(), entityToUse, source, tableName);
}
return doInsert(builder.build(), entityToUse, source, tableName);
}
private <T> ListenableFuture<EntityWriteResult<T>> doInsertVersioned(Statement<?> insert, T entity,
private <T> ListenableFuture<EntityWriteResult<T>> doInsertVersioned(SimpleStatement insert, T entity,
AdaptibleEntity<T> source, CqlIdentifier tableName) {
return executeSave(entity, tableName, insert, result -> {
@@ -613,7 +618,8 @@ public class AsyncCassandraTemplate
}
@SuppressWarnings("unused")
private <T> ListenableFuture<EntityWriteResult<T>> doInsert(Statement<?> insert, T entity, AdaptibleEntity<T> source,
private <T> ListenableFuture<EntityWriteResult<T>> doInsert(SimpleStatement insert, T entity,
AdaptibleEntity<T> source,
CqlIdentifier tableName) {
return executeSave(entity, tableName, insert);
@@ -703,9 +709,9 @@ public class AsyncCassandraTemplate
AdaptibleEntity<Object> source, CqlIdentifier tableName) {
StatementBuilder<Delete> delete = getStatementFactory().delete(entity, options, getConverter(), tableName);
source.appendVersionCondition(delete);
;
return executeDelete(entity, tableName, delete.build(), result -> {
return executeDelete(entity, tableName, source.appendVersionCondition(delete).build(), result -> {
if (!result.wasApplied()) {
throw new OptimisticLockingFailureException(
@@ -734,8 +740,7 @@ public class AsyncCassandraTemplate
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
CqlIdentifier tableName = entity.getTableName();
StatementBuilder<Delete> builder = getStatementFactory().deleteById(id,
(source, sink) -> getConverter().write(source, sink, entity), tableName);
StatementBuilder<Delete> builder = getStatementFactory().deleteById(id, entity, tableName);
SimpleStatement delete = builder.build();
maybeEmitEvent(new BeforeDeleteEvent<>(delete, entityClass, tableName));
@@ -771,13 +776,13 @@ public class AsyncCassandraTemplate
// -------------------------------------------------------------------------
private <T> ListenableFuture<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName,
Statement<?> statement) {
SimpleStatement statement) {
return executeSave(entity, tableName, statement, ignore -> {});
}
private <T> ListenableFuture<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName,
Statement<?> statement, Consumer<WriteResult> beforeAfterSaveEvent) {
SimpleStatement statement, Consumer<WriteResult> beforeAfterSaveEvent) {
maybeEmitEvent(new BeforeSaveEvent<>(entity, tableName, statement));
T entityToSave = maybeCallBeforeSave(entity, tableName, statement);
@@ -798,7 +803,7 @@ public class AsyncCassandraTemplate
});
}
private ListenableFuture<WriteResult> executeDelete(Object entity, CqlIdentifier tableName, Statement<?> statement,
private ListenableFuture<WriteResult> executeDelete(Object entity, CqlIdentifier tableName, SimpleStatement statement,
Consumer<WriteResult> resultConsumer) {
maybeEmitEvent(new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));
@@ -927,9 +932,9 @@ public class AsyncCassandraTemplate
@Value
class AsyncStatementCallback implements AsyncSessionCallback<AsyncResultSet>, CqlProvider {
@lombok.NonNull Statement<?> statement;
@lombok.NonNull SimpleStatement statement;
AsyncStatementCallback(Statement<?> statement) {
AsyncStatementCallback(SimpleStatement statement) {
this.statement = statement;
}
@@ -949,7 +954,7 @@ public class AsyncCassandraTemplate
*/
@Override
public String getCql() {
return this.statement.toString();
return this.statement.getQuery();
}
}
}

View File

@@ -76,6 +76,7 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
import com.datastax.oss.driver.api.querybuilder.select.Select;
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
@@ -565,11 +566,9 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
StatementBuilder<Select> select = getStatementFactory().selectOneById(id, entity, entity.getTableName());
StatementBuilder<Select> select = getStatementFactory().selectOneById(id,
(source, sink) -> getConverter().write(source, sink, entity), entity.getTableName());
return getCqlOperations().queryForResultSet(select.build()).iterator().hasNext();
return getCqlOperations().queryForResultSet(select.build()).one() != null;
}
/* (non-Javadoc)
@@ -589,7 +588,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
StatementBuilder<Select> select = getStatementFactory().select(query.limit(1),
getRequiredPersistentEntity(entityClass), tableName);
return getCqlOperations().queryForResultSet(select.build()).iterator().hasNext();
return getCqlOperations().queryForResultSet(select.build()).one() != null;
}
/* (non-Javadoc)
@@ -603,8 +602,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
CqlIdentifier tableName = entity.getTableName();
StatementBuilder<Select> select = getStatementFactory().selectOneById(id,
(source, sink) -> getConverter().write(source, sink, entity), tableName);
StatementBuilder<Select> select = getStatementFactory().selectOneById(id, entity, tableName);
Function<Row, T> mapper = getMapper(entityClass, entityClass, tableName);
List<T> result = getCqlOperations().query(select.build(), (row, rowNum) -> mapper.apply(row));
@@ -640,10 +638,14 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
StatementBuilder<RegularInsert> builder = getStatementFactory().insert(entityToUse, options,
source.getPersistentEntity(), tableName);
SimpleStatement insert = builder.build();
return source.isVersionedEntity() ? doInsertVersioned(insert, entityToUse, source, tableName)
: doInsert(insert, entityToUse, tableName);
if (source.isVersionedEntity()) {
builder.apply(Insert::ifNotExists);
return doInsertVersioned(builder.build(), entityToUse, source, tableName);
}
return doInsert(builder.build(), entityToUse, tableName);
}
private <T> EntityWriteResult<T> doInsertVersioned(SimpleStatement insert, T entity, AdaptibleEntity<T> source,
@@ -699,8 +701,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
T toSave = source.incrementVersion();
StatementBuilder<Update> builder = getStatementFactory().update(toSave, options, persistentEntity, tableName);
source.appendVersionCondition(builder, previousVersion);
SimpleStatement update = builder.build();
SimpleStatement update = source.appendVersionCondition(builder, previousVersion).build();
return executeSave(toSave, tableName, update, result -> {
@@ -742,14 +743,14 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
CqlIdentifier tableName = persistentEntity.getTableName();
StatementBuilder<Delete> builder = getStatementFactory().delete(entity, options, getConverter(), tableName);
source.appendVersionCondition(builder);
SimpleStatement delete = builder.build();
return source.isVersionedEntity() ? doDeleteVersioned(delete, entity, source, tableName)
: doDelete(delete, entity, tableName);
return source.isVersionedEntity()
? doDeleteVersioned(source.appendVersionCondition(builder).build(), entity, source, tableName)
: doDelete(builder.build(), entity, tableName);
}
private WriteResult doDeleteVersioned(Statement<?> statement, Object entity, AdaptibleEntity<Object> source,
private WriteResult doDeleteVersioned(SimpleStatement statement, Object entity, AdaptibleEntity<Object> source,
CqlIdentifier tableName) {
return executeDelete(entity, tableName, statement, result -> {
@@ -778,8 +779,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
CqlIdentifier tableName = entity.getTableName();
StatementBuilder<Delete> delete = getStatementFactory().deleteById(id,
(source, sink) -> getConverter().write(source, sink, entity), tableName);
StatementBuilder<Delete> delete = getStatementFactory().deleteById(id, entity, tableName);
SimpleStatement statement = delete.build();
maybeEmitEvent(new BeforeDeleteEvent<>(statement, entityClass, tableName));
@@ -850,11 +850,11 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
// Implementation hooks and utility methods
// -------------------------------------------------------------------------
private <T> EntityWriteResult<T> executeSave(T entity, CqlIdentifier tableName, Statement<?> statement) {
private <T> EntityWriteResult<T> executeSave(T entity, CqlIdentifier tableName, SimpleStatement statement) {
return executeSave(entity, tableName, statement, ignore -> {});
}
private <T> EntityWriteResult<T> executeSave(T entity, CqlIdentifier tableName, Statement<?> statement,
private <T> EntityWriteResult<T> executeSave(T entity, CqlIdentifier tableName, SimpleStatement statement,
Consumer<WriteResult> resultConsumer) {
maybeEmitEvent(new BeforeSaveEvent<>(entity, tableName, statement));
@@ -868,7 +868,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return EntityWriteResult.of(result, entityToSave);
}
private WriteResult executeDelete(Object entity, CqlIdentifier tableName, Statement<?> statement,
private WriteResult executeDelete(Object entity, CqlIdentifier tableName, SimpleStatement statement,
Consumer<WriteResult> resultConsumer) {
maybeEmitEvent(new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));
@@ -967,7 +967,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
@Value
static class StatementCallback implements SessionCallback<WriteResult>, CqlProvider {
@lombok.NonNull Statement<?> statement;
@lombok.NonNull SimpleStatement statement;
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.cql.SessionCallback#doInSession(org.springframework.data.cassandra.Session)
@@ -982,7 +982,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
*/
@Override
public String getCql() {
return this.statement.toString();
return this.statement.getQuery();
}
}
}

View File

@@ -151,7 +151,7 @@ class EntityOperations {
* @param currentVersionNumber previous version number.
* @return the altered {@link Update} containing the {@code IF} condition for optimistic locking.
*/
void appendVersionCondition(StatementBuilder<Update> update, Number currentVersionNumber);
StatementBuilder<Update> appendVersionCondition(StatementBuilder<Update> update, Number currentVersionNumber);
/**
* Appends a {@code IF} condition to an {@link Delete} statement for optimistic locking to perform the delete only
@@ -162,7 +162,7 @@ class EntityOperations {
* @return the altered {@link Delete} containing the {@code IF} condition for optimistic locking.
* @see #getVersion()
*/
void appendVersionCondition(StatementBuilder<Delete> delete);
StatementBuilder<Delete> appendVersionCondition(StatementBuilder<Delete> delete);
/**
* Initializes the version property of the of the current entity if available.
@@ -273,9 +273,10 @@ class EntityOperations {
* @see org.springframework.data.cassandra.core.EntityOperations.AdaptibleEntity#appendVersionCondition(com.datastax.oss.driver.api.querybuilder.update.Update, java.lang.Number)
*/
@Override
public void appendVersionCondition(StatementBuilder<Update> update, Number currentVersionNumber) {
public StatementBuilder<Update> appendVersionCondition(StatementBuilder<Update> update,
Number currentVersionNumber) {
update.bind((statement, factory) -> {
return update.bind((statement, factory) -> {
return statement.if_(Condition.column(getVersionColumnName()).isEqualTo(factory.create(currentVersionNumber)));
});
}
@@ -284,9 +285,9 @@ class EntityOperations {
* @see org.springframework.data.cassandra.core.EntityOperations.AdaptibleEntity#appendVersionCondition(com.datastax.oss.driver.api.querybuilder.delete.Delete)
*/
@Override
public void appendVersionCondition(StatementBuilder<Delete> delete) {
public StatementBuilder<Delete> appendVersionCondition(StatementBuilder<Delete> delete) {
delete.bind((statement, factory) -> {
return delete.bind((statement, factory) -> {
return statement.if_(Condition.column(getVersionColumnName()).isEqualTo(factory.create(getVersion())));
});
}

View File

@@ -35,6 +35,7 @@ import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
import com.datastax.oss.driver.api.core.cql.ResultSet;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
/**
@@ -121,7 +122,7 @@ class EntityQueryUtils {
*/
static CqlIdentifier getTableName(Statement<?> statement) {
String cql = statement.toString();
String cql = statement instanceof SimpleStatement ? ((SimpleStatement) statement).getQuery() : statement.toString();
Matcher matcher = FROM_REGEX.matcher(cql);
if (matcher.find()) {
@@ -131,10 +132,14 @@ class EntityQueryUtils {
int separator = cqlTableName.indexOf('.');
if (separator != -1) {
cqlTableName = cqlTableName.substring(separator + 1);
}
if (cqlTableName.startsWith("\"") || cqlTableName.endsWith("\"")) {
return CqlIdentifier.fromCql(cqlTableName.substring(separator + 1));
}
return CqlIdentifier.fromCql(cqlTableName);
return CqlIdentifier.fromInternal(cqlTableName);
}
return CqlIdentifier.fromCql("unknown");

View File

@@ -79,6 +79,7 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
import com.datastax.oss.driver.api.querybuilder.select.Select;
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
@@ -316,7 +317,7 @@ public class ReactiveCassandraTemplate
Assert.notNull(statement, "Statement must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
Function<Row, T> mapper = getMapper(entityClass, entityClass, null);
Function<Row, T> mapper = getMapper(entityClass, entityClass, EntityQueryUtils.getTableName(statement));
return getReactiveCqlOperations().query(statement, (row, rowNum) -> mapper.apply(row));
}
@@ -503,8 +504,8 @@ public class ReactiveCassandraTemplate
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
StatementBuilder<Select> builder = getStatementFactory().selectOneById(id, getConverter(),
getTableName(entityClass));
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
StatementBuilder<Select> builder = getStatementFactory().selectOneById(id, entity, entity.getTableName());
return getReactiveCqlOperations().queryForRows(builder.build()).hasElements();
}
@@ -538,7 +539,7 @@ public class ReactiveCassandraTemplate
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
StatementBuilder<Select> builder = getStatementFactory().selectOneById(id, getConverter(),
StatementBuilder<Select> builder = getStatementFactory().selectOneById(id, getRequiredPersistentEntity(entityClass),
getTableName(entityClass));
return selectOne(builder.build(), entityClass);
@@ -576,14 +577,17 @@ public class ReactiveCassandraTemplate
StatementBuilder<RegularInsert> builder = getStatementFactory().insert(entityToUse, options, persistentEntity,
tableName);
SimpleStatement insert = builder.build();
return source.isVersionedEntity() ? doInsertVersioned(insert, entityToUse, source, tableName)
: doInsert(insert, entityToUse, tableName);
if (source.isVersionedEntity()) {
builder.apply(Insert::ifNotExists);
return doInsertVersioned(builder.build(), entityToUse, source, tableName);
}
return doInsert(builder.build(), entityToUse, tableName);
});
}
private <T> Mono<EntityWriteResult<T>> doInsertVersioned(Statement<?> insert, T entity, AdaptibleEntity<T> source,
private <T> Mono<EntityWriteResult<T>> doInsertVersioned(SimpleStatement insert, T entity, AdaptibleEntity<T> source,
CqlIdentifier tableName) {
return executeSave(entity, tableName, insert, (result, sink) -> {
@@ -601,7 +605,7 @@ public class ReactiveCassandraTemplate
});
}
private <T> Mono<EntityWriteResult<T>> doInsert(Statement<?> insert, T entity, CqlIdentifier tableName) {
private <T> Mono<EntityWriteResult<T>> doInsert(SimpleStatement insert, T entity, CqlIdentifier tableName) {
return executeSave(entity, tableName, insert);
}
@@ -641,9 +645,7 @@ public class ReactiveCassandraTemplate
T toSave = source.incrementVersion();
StatementBuilder<Update> builder = getStatementFactory().update(toSave, options, persistentEntity, tableName);
source.appendVersionCondition(builder, previousVersion);
SimpleStatement update = builder.build();
SimpleStatement update = source.appendVersionCondition(builder, previousVersion).build();
return executeSave(toSave, tableName, update, (result, sink) -> {
@@ -690,13 +692,13 @@ public class ReactiveCassandraTemplate
CqlIdentifier tableName = persistentEntity.getTableName();
StatementBuilder<Delete> builder = getStatementFactory().delete(entity, options, getConverter(), tableName);
SimpleStatement delete = builder.build();
return source.isVersionedEntity() ? doDeleteVersioned(delete, entity, source, tableName)
: doDelete(delete, entity, tableName);
return source.isVersionedEntity()
? doDeleteVersioned(source.appendVersionCondition(builder).build(), entity, source, tableName)
: doDelete(builder.build(), entity, tableName);
}
private Mono<WriteResult> doDeleteVersioned(Statement<?> delete, Object entity, AdaptibleEntity<Object> source,
private Mono<WriteResult> doDeleteVersioned(SimpleStatement delete, Object entity, AdaptibleEntity<Object> source,
CqlIdentifier tableName) {
return executeDelete(entity, tableName, delete, (result, sink) -> {
@@ -714,7 +716,7 @@ public class ReactiveCassandraTemplate
});
}
private Mono<WriteResult> doDelete(Statement<?> delete, Object entity, CqlIdentifier tableName) {
private Mono<WriteResult> doDelete(SimpleStatement delete, Object entity, CqlIdentifier tableName) {
return executeDelete(entity, tableName, delete, (result, sink) -> sink.next(result));
}
@@ -730,7 +732,7 @@ public class ReactiveCassandraTemplate
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
CqlIdentifier tableName = entity.getTableName();
StatementBuilder<Delete> builder = getStatementFactory().deleteById(id, getConverter(), tableName);
StatementBuilder<Delete> builder = getStatementFactory().deleteById(id, entity, tableName);
SimpleStatement delete = builder.build();
Mono<Boolean> result = getReactiveCqlOperations().execute(delete)
@@ -797,11 +799,11 @@ public class ReactiveCassandraTemplate
// Implementation hooks and utility methods
// -------------------------------------------------------------------------
private <T> Mono<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName, Statement<?> statement) {
private <T> Mono<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName, SimpleStatement statement) {
return executeSave(entity, tableName, statement, (writeResult, sink) -> sink.next(writeResult));
}
private <T> Mono<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName, Statement<?> statement,
private <T> Mono<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName, SimpleStatement statement,
BiConsumer<EntityWriteResult<T>, SynchronousSink<EntityWriteResult<T>>> handler) {
return Mono.defer(() -> {
@@ -818,7 +820,7 @@ public class ReactiveCassandraTemplate
}
private Mono<WriteResult> executeDelete(Object entity, CqlIdentifier tableName, Statement<?> statement,
private Mono<WriteResult> executeDelete(Object entity, CqlIdentifier tableName, SimpleStatement statement,
BiConsumer<WriteResult, SynchronousSink<WriteResult>> handler) {
maybeEmitEvent(new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));
@@ -915,7 +917,7 @@ public class ReactiveCassandraTemplate
@Value
static class StatementCallback implements ReactiveSessionCallback<WriteResult>, CqlProvider {
@lombok.NonNull Statement<?> statement;
@lombok.NonNull SimpleStatement statement;
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.cql.ReactiveSessionCallback#doInSession(org.springframework.data.cassandra.ReactiveSession)
@@ -930,7 +932,7 @@ public class ReactiveCassandraTemplate
*/
@Override
public String getCql() {
return this.statement.toString();
return this.statement.getQuery();
}
private static Mono<WriteResult> toWriteResult(ReactiveResultSet resultSet) {

View File

@@ -15,9 +15,13 @@
*/
package org.springframework.data.cassandra.core;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -201,16 +205,16 @@ public class StatementFactory {
* {@link UpdateOptions}.
*
* @param id must not be {@literal null}.
* @param entityWriter must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param tableName must not be {@literal null}.
* @return the select builder.
*/
StatementBuilder<Select> selectOneById(Object id, EntityWriter<Object, Object> entityWriter,
StatementBuilder<Select> selectOneById(Object id, CassandraPersistentEntity<?> persistentEntity,
CqlIdentifier tableName) {
Where where = new Where();
entityWriter.write(id, where);
cassandraConverter.write(id, where, persistentEntity);
return StatementBuilder.of(QueryBuilder.selectFrom(tableName).all().limit(1)).bind((statement, factory) -> {
return statement.where(toRelations(where, factory));
@@ -522,9 +526,9 @@ public class StatementFactory {
StatementBuilder<Delete> builder = delete(columnNames, tableName, filter);
query.getQueryOptions() //
.filter(UpdateOptions.class::isInstance) //
.map(UpdateOptions.class::cast) //
.map(UpdateOptions::getIfCondition) //
.filter(DeleteOptions.class::isInstance) //
.map(DeleteOptions.class::cast) //
.map(DeleteOptions::getIfCondition) //
.ifPresent(criteriaDefinitions -> {
applyDeleteIfCondition(builder, criteriaDefinitions);
});
@@ -661,17 +665,12 @@ public class StatementFactory {
select = QueryBuilder.selectFrom(from).all();
} else {
select = QueryBuilder.selectFrom(from).selectors();
List<com.datastax.oss.driver.api.querybuilder.select.Selector> mappedSelectors = selectors.stream()
.map(selector -> {
return selector.getAlias().map(it -> getSelection(selector).as(it)).orElseGet(() -> getSelection(selector));
}).collect(Collectors.toList());
for (Selector selector : selectors) {
com.datastax.oss.driver.api.querybuilder.select.Selector selection = getSelection(selector);
if (selector.getAlias().isPresent()) {
selection = selection.as(selector.getAlias().get());
}
select.selector(selection);
}
select = QueryBuilder.selectFrom(from).selectors(mappedSelectors);
}
StatementBuilder<Select> builder = StatementBuilder.of(select);
@@ -687,7 +686,7 @@ public class StatementFactory {
.collect(Collectors.toMap(Sort.Order::getProperty, //
order -> order.isAscending() ? ClusteringOrder.ASC : ClusteringOrder.DESC));
return select.orderBy(ordering);
return statement.orderBy(ordering);
});
}
@@ -706,14 +705,15 @@ public class StatementFactory {
return com.datastax.oss.driver.api.querybuilder.select.Selector
.column(((ColumnSelector) param).getExpression());
}
return com.datastax.oss.driver.api.querybuilder.select.Selector.function(param.toString());
return new SimpleSelector(param.toString());
}).toArray(com.datastax.oss.driver.api.querybuilder.select.Selector[]::new);
return com.datastax.oss.driver.api.querybuilder.select.Selector.function(selector.getExpression(), arguments);
}
return QueryBuilder.literal(selector.getExpression());
return com.datastax.oss.driver.api.querybuilder.select.Selector
.column(CqlIdentifier.fromInternal(selector.getExpression()));
}
private static StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update(CqlIdentifier table,
@@ -835,14 +835,20 @@ public class StatementFactory {
if (updateOp.getValue() instanceof Set) {
Collection<Object> collection = (Collection<Object>) updateOp.getValue();
Assert.isTrue(collection.size() == 1, "RemoveOp must contain a single set element");
return Assignment.removeSetElement(updateOp.toCqlIdentifier(), termFactory.create(updateOp.getValue()));
return Assignment.removeSetElement(updateOp.toCqlIdentifier(),
termFactory.create(collection.iterator().next()));
}
if (updateOp.getValue() instanceof List) {
Collection<Object> collection = (Collection<Object>) updateOp.getValue();
Assert.isTrue(collection.size() == 1, "RemoveOp must contain a single list element");
return Assignment.removeListElement(updateOp.toCqlIdentifier(), termFactory.create(updateOp.getValue()));
return Assignment.removeListElement(updateOp.toCqlIdentifier(),
termFactory.create(collection.iterator().next()));
}
return Assignment.remove(updateOp.toCqlIdentifier(), termFactory.create(updateOp.getValue()));
@@ -965,7 +971,8 @@ public class StatementFactory {
private static Relation toClause(CriteriaDefinition criteriaDefinition, TermFactory factory) {
CqlIdentifier columnName = criteriaDefinition.getColumnName().getCqlIdentifier().get();
CqlIdentifier columnName = criteriaDefinition.getColumnName().getCqlIdentifier()
.orElseGet(() -> CqlIdentifier.fromInternal(criteriaDefinition.getColumnName().toCql()));
Predicate predicate = criteriaDefinition.getPredicate();
@@ -1094,4 +1101,30 @@ public class StatementFactory {
throw new IllegalArgumentException(String.format("Criteria %s %s %s not supported for IF Conditions", columnName,
predicate.getOperator(), predicate.getValue()));
}
static class SimpleSelector implements com.datastax.oss.driver.api.querybuilder.select.Selector {
private final String selector;
SimpleSelector(String selector) {
this.selector = selector;
}
@NonNull
@Override
public com.datastax.oss.driver.api.querybuilder.select.Selector as(@NonNull CqlIdentifier alias) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public CqlIdentifier getAlias() {
return null;
}
@Override
public void appendTo(@NonNull StringBuilder builder) {
builder.append(selector);
}
}
}

View File

@@ -15,17 +15,20 @@
*/
package org.springframework.data.cassandra.core.convert;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.core.mapping.CassandraSimpleTypeHolder;
import org.springframework.data.cassandra.core.mapping.CassandraType;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.util.ClassUtils;
@@ -60,7 +63,15 @@ public abstract class CassandraJodaTimeConverters {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(MillisOfDayToLocalTimeConverter.INSTANCE);
converters.add(LocalTimeToMillisOfDayConverter.INSTANCE);
converters.add(FromJodaLocalTimeConverter.INSTANCE);
converters.add(ToJodaLocalTimeConverter.INSTANCE);
converters.add(FromJodaLocalDateConverter.INSTANCE);
converters.add(ToJodaLocalDateConverter.INSTANCE);
converters.add(LocalDateTimeToInstantConverter.INSTANCE);
converters.add(InstantToLocalDateTimeConverter.INSTANCE);
return converters;
}
@@ -70,7 +81,6 @@ public abstract class CassandraJodaTimeConverters {
*
* @author Mark Paluch
*/
@ReadingConverter
public enum MillisOfDayToLocalTimeConverter implements Converter<Long, LocalTime> {
INSTANCE;
@@ -86,8 +96,6 @@ public abstract class CassandraJodaTimeConverters {
*
* @author Mark Paluch
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.TIME)
public enum LocalTimeToMillisOfDayConverter implements Converter<LocalTime, Long> {
INSTANCE;
@@ -97,4 +105,99 @@ public abstract class CassandraJodaTimeConverters {
return (long) source.getMillisOfDay();
}
}
/**
* Simple singleton to convert {@link LocalTime}s to their {@link java.time.LocalTime} representation.
*
* @author Mark Paluch
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.TIME)
public enum FromJodaLocalTimeConverter implements Converter<LocalTime, java.time.LocalTime> {
INSTANCE;
@Override
public java.time.LocalTime convert(LocalTime source) {
return java.time.LocalTime.ofNanoOfDay(TimeUnit.MILLISECONDS.toNanos(source.getMillisOfDay()));
}
}
/**
* Simple singleton to convert {@link java.time.LocalTime}s to their {@link LocalTime} representation.
*
* @author Mark Paluch
*/
public enum ToJodaLocalTimeConverter implements Converter<java.time.LocalTime, LocalTime> {
INSTANCE;
@Override
public LocalTime convert(java.time.LocalTime source) {
return LocalTime.fromMillisOfDay(TimeUnit.NANOSECONDS.toMillis(source.toNanoOfDay()));
}
}
/**
* Simple singleton to convert {@link LocalTime}s to their {@link java.time.LocalDate} representation.
*
* @author Mark Paluch
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.DATE)
public enum FromJodaLocalDateConverter implements Converter<LocalDate, java.time.LocalDate> {
INSTANCE;
@Override
public java.time.LocalDate convert(LocalDate date) {
return java.time.LocalDate.of(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth());
}
}
/**
* Simple singleton to convert {@link java.time.LocalTime}s to their {@link LocalDate} representation.
*
* @author Mark Paluch
*/
public enum ToJodaLocalDateConverter implements Converter<java.time.LocalDate, LocalDate> {
INSTANCE;
@Override
public LocalDate convert(java.time.LocalDate date) {
return new LocalDate(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
}
}
/**
* Simple singleton to convert {@link LocalDateTime}s to their {@link java.time.Instant} representation.
*
* @since 3.0
*/
@WritingConverter
public enum LocalDateTimeToInstantConverter implements Converter<LocalDateTime, java.time.Instant> {
INSTANCE;
@Override
public java.time.Instant convert(LocalDateTime source) {
return source.toDate().toInstant();
}
}
/**
* Simple singleton to convert {@link java.time.LocalDateTime}s to their {@link LocalDateTime} representation.
*
* @since 3.0
*/
public enum InstantToLocalDateTimeConverter implements Converter<java.time.Instant, LocalDateTime> {
INSTANCE;
@Override
public LocalDateTime convert(java.time.Instant source) {
return new LocalDateTime(Date.from(source));
}
}
}

View File

@@ -15,15 +15,19 @@
*/
package org.springframework.data.cassandra.core.convert;
import static java.time.ZoneId.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.core.mapping.CassandraSimpleTypeHolder;
import org.springframework.data.cassandra.core.mapping.CassandraType;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
@@ -51,6 +55,13 @@ public abstract class CassandraJsr310Converters {
converters.add(MillisOfDayToLocalTimeConverter.INSTANCE);
converters.add(LocalTimeToMillisOfDayConverter.INSTANCE);
converters.add(DateToInstantConverter.INSTANCE);
converters.add(LocalDateToInstantConverter.INSTANCE);
converters.add(LocalDateConverter.INSTANCE);
converters.add(LocalTimeConverter.INSTANCE);
converters.add(InstantConverter.INSTANCE);
return converters;
}
@@ -77,8 +88,7 @@ public abstract class CassandraJsr310Converters {
* @author Mark Paluch
* @since 2.1
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.TIME)
@ReadingConverter
public enum LocalTimeToMillisOfDayConverter implements Converter<LocalTime, Long> {
INSTANCE;
@@ -88,4 +98,85 @@ public abstract class CassandraJsr310Converters {
return source.getLong(ChronoField.NANO_OF_DAY);
}
}
/**
* Simple singleton to convert {@link Date}s to their Cassandra {@link Instant} representation for the CQL Timestamp
* type. Used for Cassandra 3.x to 4.x driver migration where
*
* @since 3.0
*/
@WritingConverter
public enum DateToInstantConverter implements Converter<Date, Instant> {
INSTANCE;
@Override
public Instant convert(Date source) {
return source.toInstant();
}
}
/**
* Force {@link LocalDate} to remain a {@link LocalDate}.
*
* @since 3.0
*/
@WritingConverter
enum LocalDateConverter implements Converter<LocalDate, LocalDate> {
INSTANCE;
@Override
public LocalDate convert(LocalDate source) {
return source;
}
}
/**
* Force {@link LocalTime} to remain a {@link LocalTime}.
*
* @since 3.0
*/
@WritingConverter
enum LocalTimeConverter implements Converter<LocalTime, LocalTime> {
INSTANCE;
@Override
public LocalTime convert(LocalTime source) {
return source;
}
}
/**
* Force {@link Instant} to remain a {@link Instant}.
*
* @since 3.0
*/
@WritingConverter
enum InstantConverter implements Converter<Instant, Instant> {
INSTANCE;
@Override
public Instant convert(Instant source) {
return source;
}
}
/**
* Force {@link LocalDateTime} to remain a {@link Instant}.
*
* @since 3.0
*/
@WritingConverter
enum LocalDateToInstantConverter implements Converter<LocalDateTime, Instant> {
INSTANCE;
@Override
public Instant convert(LocalDateTime source) {
return source.atZone(systemDefault()).toInstant();
}
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.core.convert;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -29,7 +30,10 @@ import org.springframework.data.convert.ThreeTenBackPortConverters;
import org.springframework.data.convert.WritingConverter;
import org.springframework.util.ClassUtils;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.temporal.ChronoField;
/**
@@ -67,6 +71,17 @@ public abstract class CassandraThreeTenBackPortConverters {
converters.add(MillisOfDayToLocalTimeConverter.INSTANCE);
converters.add(LocalTimeToMillisOfDayConverter.INSTANCE);
converters.add(FromBpLocalTimeConverter.INSTANCE);
converters.add(ToBpLocalTimeConverter.INSTANCE);
converters.add(FromBpLocalDateConverter.INSTANCE);
converters.add(ToBpLocalDateConverter.INSTANCE);
converters.add(FromBpLocalDateTimeConverter.INSTANCE);
converters.add(ToBpLocalDateTimeConverter.INSTANCE);
converters.add(LocalDateTimeToInstantConverter.INSTANCE);
return converters;
}
@@ -93,8 +108,7 @@ public abstract class CassandraThreeTenBackPortConverters {
* @author Mark Paluch
* @since 2.1
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.TIME)
@ReadingConverter
public enum LocalTimeToMillisOfDayConverter implements Converter<LocalTime, Long> {
INSTANCE;
@@ -104,4 +118,120 @@ public abstract class CassandraThreeTenBackPortConverters {
return source.getLong(ChronoField.MILLI_OF_DAY);
}
}
/**
* Simple singleton to convert {@link LocalTime}s to their {@link java.time.LocalTime} representation.
*
* @since 3.0
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.TIME)
public enum FromBpLocalTimeConverter implements Converter<LocalTime, java.time.LocalTime> {
INSTANCE;
@Override
public java.time.LocalTime convert(LocalTime source) {
return java.time.LocalTime.ofNanoOfDay(source.toNanoOfDay());
}
}
/**
* Simple singleton to convert {@link java.time.LocalTime}s to their {@link LocalTime} representation.
*
* @since 3.0
*/
@ReadingConverter
public enum ToBpLocalTimeConverter implements Converter<java.time.LocalTime, LocalTime> {
INSTANCE;
@Override
public LocalTime convert(java.time.LocalTime source) {
return LocalTime.ofNanoOfDay(source.toNanoOfDay());
}
}
/**
* Simple singleton to convert {@link LocalTime}s to their {@link java.time.LocalDate} representation.
*
* @since 3.0
*/
@WritingConverter
@CassandraType(type = CassandraSimpleTypeHolder.Name.DATE)
public enum FromBpLocalDateConverter implements Converter<LocalDate, java.time.LocalDate> {
INSTANCE;
@Override
public java.time.LocalDate convert(LocalDate date) {
return java.time.LocalDate.of(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
}
}
/**
* Simple singleton to convert {@link java.time.LocalTime}s to their {@link LocalDate} representation.
*
* @since 3.0
*/
@ReadingConverter
public enum ToBpLocalDateConverter implements Converter<java.time.LocalDate, LocalDate> {
INSTANCE;
@Override
public LocalDate convert(java.time.LocalDate date) {
return LocalDate.of(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
}
}
/**
* Simple singleton to convert {@link LocalDateTime}s to their {@link java.time.LocalDateTime} representation.
*
* @since 3.0
*/
@ReadingConverter
public enum FromBpLocalDateTimeConverter implements Converter<LocalDateTime, java.time.LocalDateTime> {
INSTANCE;
@Override
public java.time.LocalDateTime convert(LocalDateTime date) {
return java.time.LocalDateTime.of(date.getYear(), date.getMonthValue(), date.getDayOfMonth(), date.getHour(),
date.getMinute(), date.getSecond(), date.getNano());
}
}
/**
* Simple singleton to convert {@link java.time.LocalDateTime}s to their {@link LocalDateTime} representation.
*
* @since 3.0
*/
@ReadingConverter
public enum ToBpLocalDateTimeConverter implements Converter<java.time.LocalDateTime, LocalDateTime> {
INSTANCE;
@Override
public LocalDateTime convert(java.time.LocalDateTime date) {
return LocalDateTime.of(date.getYear(), date.getMonthValue(), date.getDayOfMonth(), date.getHour(),
date.getMinute(), date.getSecond(), date.getNano());
}
}
/**
* Force {@link LocalDateTime} to remain a {@link Instant}.
*
* @since 3.0
*/
@WritingConverter
enum LocalDateTimeToInstantConverter implements Converter<LocalDateTime, java.time.Instant> {
INSTANCE;
@Override
public java.time.Instant convert(LocalDateTime source) {
return Instant.ofEpochMilli(source.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
}
}

View File

@@ -101,6 +101,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
CassandraMappingContext mappingContext = new CassandraMappingContext();
mappingContext.setCustomConversions(new CassandraCustomConversions(Collections.emptyList()));
mappingContext.afterPropertiesSet();
return mappingContext;
}
@@ -593,22 +594,31 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return id;
}
/**
* Check custom conversions for type override or fall back to
* {@link #determineTargetType(CassandraPersistentProperty)}
*
* @param property
* @return
*/
private Class<?> getTargetType(CassandraPersistentProperty property) {
return getCustomConversions().getCustomWriteTarget(property.getType())
.orElseGet(() -> determineTargetType(property));
}
return getCustomConversions().getCustomWriteTarget(property.getType()).orElseGet(() -> {
if (property.isAnnotationPresent(CassandraType.class)) {
return getPropertyTargetType(property);
}
if (property.isCompositePrimaryKey() || property.isCollectionLike()
|| getCustomConversions().isSimpleType(property.getType())) {
return property.getType();
}
private Class<?> determineTargetType(CassandraPersistentProperty property) {
if (property.isAnnotationPresent(CassandraType.class)) {
return getPropertyTargetType(property);
});
}
if (property.isCompositePrimaryKey() || property.isCollectionLike()
|| getCustomConversions().isSimpleType(property.getType())) {
return property.getType();
}
return getPropertyTargetType(property);
}
private Class<?> getPropertyTargetType(CassandraPersistentProperty property) {
@@ -638,7 +648,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
@Nullable
@SuppressWarnings("unchecked")
private <T> T getWriteValue(CassandraPersistentProperty property, ConvertingPropertyAccessor propertyAccessor) {
return (T) getWriteValue(propertyAccessor.getProperty(property, (Class<T>) getTargetType(property)),
return (T) getWriteValue(propertyAccessor.getProperty(property, (Class<T>) determineTargetType(property)),
property.getTypeInformation());
}

View File

@@ -149,7 +149,7 @@ class RowReader {
DataType valueType = setType.getElementType();
TypeCodec<Object> typeCodec = codecRegistry.codecFor(valueType);
return row.getList(index, typeCodec.getJavaType().getRawType());
return row.getSet(index, typeCodec.getJavaType().getRawType());
}
// Map

View File

@@ -87,16 +87,6 @@ public class CassandraExceptionTranslator implements CqlExceptionTranslator {
return new CassandraAuthenticationException(((AuthenticationException) exception).getEndPoint(), message,
exception);
}
/* TODO ???
if (exception instanceof DriverInternalError) {
return new CassandraInternalException(message, exception);
}
if (exception instanceof InvalidTypeException) {
return new CassandraTypeMismatchException(message, exception);
}
???
*/
if (exception instanceof ReadTimeoutException) {
return new CassandraReadTimeoutException(((ReadTimeoutException) exception).wasDataPresent(), message, exception);

View File

@@ -15,13 +15,17 @@
*/
package org.springframework.data.cassandra.core.cql;
import java.time.Duration;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.cql.SimpleStatementBuilder;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
import com.datastax.oss.driver.api.querybuilder.delete.DeleteSelection;
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
import com.datastax.oss.driver.api.querybuilder.update.Update;
import com.datastax.oss.driver.api.querybuilder.update.UpdateStart;
/**
* Utility class to associate {@link QueryOptions} and {@link WriteOptions} with QueryBuilder {@link Statement}s.
@@ -81,11 +85,6 @@ public abstract class QueryOptionsUtil {
statementBuilder.setConsistencyLevel(queryOptions.getConsistencyLevel());
}
// TODO:
/*if (queryOptions.getRetryPolicy() != null) {
statementToUse = statementToUse.setRetryPolicy(queryOptions.getRetryPolicy());
} */
if (queryOptions.getPageSize() != null) {
statementBuilder.setPageSize(queryOptions.getPageSize());
}
@@ -141,7 +140,9 @@ public abstract class QueryOptionsUtil {
Assert.notNull(delete, "Delete must not be null");
Assert.notNull(writeOptions, "WriteOptions must not be null");
// TODO: Timestamp? TTL
if (writeOptions.getTimestamp() != null) {
delete = (Delete) ((DeleteSelection) delete).usingTimestamp(writeOptions.getTimestamp());
}
return delete;
}
@@ -158,8 +159,22 @@ public abstract class QueryOptionsUtil {
Assert.notNull(update, "Update must not be null");
Assert.notNull(writeOptions, "WriteOptions must not be null");
// TODO: Timestamp, TTL?
if (hasTtl(writeOptions.getTtl())) {
update = (Update) ((UpdateStart) update).usingTtl(getTtlSeconds(writeOptions.getTtl()));
}
if (writeOptions.getTimestamp() != null) {
update = (Update) ((UpdateStart) update).usingTimestamp(writeOptions.getTimestamp());
}
return update;
}
private static int getTtlSeconds(Duration ttl) {
return Math.toIntExact(ttl.getSeconds());
}
private static boolean hasTtl(Duration ttl) {
return !ttl.isZero() && !ttl.isNegative();
}
}

View File

@@ -37,6 +37,7 @@ public class AddColumnCqlGenerator extends ColumnChangeCqlGenerator<AddColumnSpe
*/
@Override
public StringBuilder toCql(StringBuilder cql) {
return cql.append("ADD ").append(spec().getName()).append(' ').append(spec().getType().asCql(true, true));
return cql.append("ADD ").append(spec().getName().asCql(true)).append(' ')
.append(spec().getType().asCql(true, true));
}
}

View File

@@ -31,6 +31,7 @@ public class AlterColumnCqlGenerator extends ColumnChangeCqlGenerator<AlterColum
}
public StringBuilder toCql(StringBuilder cql) {
return cql.append("ALTER ").append(spec().getName()).append(" TYPE ").append(spec().getType().asCql(true, true));
return cql.append("ALTER ").append(spec().getName().asCql(true)).append(" TYPE ")
.append(spec().getType().asCql(true, true));
}
}

View File

@@ -47,7 +47,7 @@ public class AlterKeyspaceCqlGenerator extends KeyspaceOptionsCqlGenerator<Alter
}
private void preambleCql(StringBuilder cql) {
cql.append("ALTER KEYSPACE ").append(spec().getName()).append(" ");
cql.append("ALTER KEYSPACE ").append(spec().getName().asCql(true)).append(" ");
}
@SuppressWarnings("unchecked")

View File

@@ -74,7 +74,7 @@ public class AlterTableCqlGenerator extends TableOptionsCqlGenerator<AlterTableS
}
private void preambleCql(StringBuilder cql) {
cql.append("ALTER TABLE ").append(spec().getName());
cql.append("ALTER TABLE ").append(spec().getName().asCql(true));
}
private void changesCql(StringBuilder cql) {

View File

@@ -64,7 +64,7 @@ public class AlterUserTypeCqlGenerator extends UserTypeNameCqlGenerator<AlterUse
}
private StringBuilder preambleCql(StringBuilder cql) {
return cql.append("ALTER TYPE ").append(spec().getName()).append(' ');
return cql.append("ALTER TYPE ").append(spec().getName().asCql(true)).append(' ');
}
private StringBuilder changesCql(StringBuilder cql) {

View File

@@ -48,15 +48,15 @@ public class CreateIndexCqlGenerator extends IndexNameCqlGenerator<CreateIndexSp
.append(spec().getIfNotExists() ? " IF NOT EXISTS" : "");
if (spec().getName() != null) {
cql.append(" ").append(spec().getName());
cql.append(" ").append(spec().getName().asCql(true));
}
cql.append(" ON ").append(spec().getTableName()).append(" (");
if (spec().getColumnFunction() != ColumnFunction.NONE) {
cql.append(spec().getColumnFunction().name()).append("(").append(spec().getColumnName()).append(")");
cql.append(spec().getColumnFunction().name()).append("(").append(spec().getColumnName().asCql(true)).append(")");
} else {
cql.append(spec().getColumnName());
cql.append(spec().getColumnName().asCql(true));
}
cql.append(")");

View File

@@ -50,7 +50,8 @@ public class CreateKeyspaceCqlGenerator extends KeyspaceOptionsCqlGenerator<Crea
}
private void preambleCql(StringBuilder cql) {
cql.append("CREATE KEYSPACE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "").append(spec().getName());
cql.append("CREATE KEYSPACE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "")
.append(spec().getName().asCql(true));
}
@SuppressWarnings("unchecked")

View File

@@ -64,7 +64,8 @@ public class CreateTableCqlGenerator extends TableOptionsCqlGenerator<TableSpeci
}
private void preambleCql(StringBuilder cql) {
cql.append("CREATE TABLE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "").append(spec().getName());
cql.append("CREATE TABLE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "")
.append(spec().getName().asCql(true));
}
@SuppressWarnings("unchecked")
@@ -176,7 +177,7 @@ public class CreateTableCqlGenerator extends TableOptionsCqlGenerator<TableSpeci
} else {
ordering.append(", ");
}
ordering.append(col.getName()).append(" ").append(col.getOrdering().cql());
ordering.append(col.getName().asCql(true)).append(" ").append(col.getOrdering().cql());
}
}
@@ -196,7 +197,7 @@ public class CreateTableCqlGenerator extends TableOptionsCqlGenerator<TableSpeci
} else {
str.append(", ");
}
str.append(col.getName());
str.append(col.getName().asCql(true));
}
}
}

View File

@@ -52,14 +52,15 @@ public class CreateUserTypeCqlGenerator extends UserTypeNameCqlGenerator<CreateU
Assert.notNull(getSpecification().getName(), "User type name must not be null");
Assert.isTrue(!getSpecification().getFields().isEmpty(),
String.format("User type [%s] does not contain fields", getSpecification().getName()));
String.format("User type [%s] does not contain fields", getSpecification().getName().asCql(true)));
return columns(preambleCql(cql)).append(";");
}
private StringBuilder preambleCql(StringBuilder cql) {
return cql.append("CREATE TYPE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "").append(spec().getName());
return cql.append("CREATE TYPE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "")
.append(spec().getName().asCql(true));
}
private StringBuilder columns(StringBuilder cql) {

View File

@@ -32,6 +32,6 @@ public class DropColumnCqlGenerator extends ColumnChangeCqlGenerator<DropColumnS
}
public StringBuilder toCql(StringBuilder cql) {
return cql.append("DROP ").append(spec().getName());
return cql.append("DROP ").append(spec().getName().asCql(true));
}
}

View File

@@ -37,6 +37,6 @@ public class DropIndexCqlGenerator extends IndexNameCqlGenerator<DropIndexSpecif
public StringBuilder toCql(StringBuilder cql) {
return cql.append("DROP INDEX ")
// .append(spec().getIfExists() ? "IF EXISTS " : "")
.append(spec().getName()).append(";");
.append(spec().getName().asCql(true)).append(";");
}
}

View File

@@ -34,7 +34,8 @@ public class DropKeyspaceCqlGenerator extends KeyspaceNameCqlGenerator<DropKeysp
@Override
public StringBuilder toCql(StringBuilder cql) {
return cql.append("DROP KEYSPACE ").append(spec().getIfExists() ? "IF EXISTS " : "").append(spec().getName())
return cql.append("DROP KEYSPACE ").append(spec().getIfExists() ? "IF EXISTS " : "")
.append(spec().getName().asCql(true))
.append(";");
}
}

View File

@@ -41,6 +41,6 @@ public class DropTableCqlGenerator extends TableNameCqlGenerator<DropTableSpecif
DropTableSpecification specification = spec();
return cql.append("DROP TABLE ").append(specification.getIfExists() ? "IF EXISTS " : "")
.append(specification.getName()).append(";");
.append(specification.getName().asCql(true)).append(";");
}
}

View File

@@ -46,7 +46,8 @@ public class DropUserTypeCqlGenerator extends UserTypeNameCqlGenerator<DropUserT
*/
@Override
public StringBuilder toCql(StringBuilder cql) {
return cql.append("DROP TYPE").append(spec().getIfExists() ? " IF EXISTS " : " ").append(spec().getName())
return cql.append("DROP TYPE").append(spec().getIfExists() ? " IF EXISTS " : " ")
.append(spec().getName().asCql(true))
.append(";");
}
}

View File

@@ -51,6 +51,7 @@ public class RenameColumnCqlGenerator extends ColumnChangeCqlGenerator<RenameCol
* @see org.springframework.data.cassandra.core.cql.generator.ColumnChangeCqlGenerator#toCql(java.lang.StringBuilder)
*/
public StringBuilder toCql(StringBuilder cql) {
return cql.append(keyword).append(' ').append(spec().getName()).append(" TO ").append(spec().getTargetName());
return cql.append(keyword).append(' ').append(spec().getName().asCql(true)).append(" TO ")
.append(spec().getTargetName().asCql(true));
}
}

View File

@@ -202,7 +202,7 @@ public class ColumnSpecification {
}
public StringBuilder toCql(StringBuilder cql) {
return cql.append(name).append(" ").append(type);
return cql.append(name.asCql(true)).append(" ").append(type.asCql(true, true));
}
/* (non-Javadoc)

View File

@@ -69,7 +69,7 @@ public class FieldSpecification {
}
public StringBuilder toCql(StringBuilder cql) {
return cql.append(name).append(" ").append(type);
return cql.append(name.asCql(true)).append(" ").append(type.asCql(true, true));
}
/*

View File

@@ -204,9 +204,19 @@ public class DefaultBridgedReactiveSession implements ReactiveSession {
static class DefaultReactiveResultSet implements ReactiveResultSet {
private final AsyncResultSet resultSet;
private final boolean wasApplied;
DefaultReactiveResultSet(AsyncResultSet resultSet) {
this.resultSet = resultSet;
boolean wasApplied;
try {
wasApplied = resultSet.wasApplied();
} catch (Exception e) {
wasApplied = false;
}
this.wasApplied = wasApplied;
}
/* (non-Javadoc)
@@ -277,7 +287,7 @@ public class DefaultBridgedReactiveSession implements ReactiveSession {
*/
@Override
public boolean wasApplied() {
return this.resultSet.wasApplied();
return this.wasApplied;
}
/* (non-Javadoc)

View File

@@ -15,11 +15,17 @@
*/
package org.springframework.data.cassandra.core.cql.util;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import org.springframework.util.Assert;
@@ -29,6 +35,8 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatementBuilder;
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
import com.datastax.oss.driver.api.querybuilder.BuildableQuery;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import com.datastax.oss.driver.api.querybuilder.term.Term;
import com.datastax.oss.driver.internal.querybuilder.CqlHelper;
/**
* Functional builder for Cassandra {@link BuildableQuery statements}. Statements are built by applying
@@ -106,11 +114,11 @@ public class StatementBuilder<S extends BuildableQuery> {
* @param action the builder function to be applied to the statement.
* @return {@code this} {@link StatementBuilder}.
*/
public StatementBuilder<S> apply(UnaryOperator<S> action) {
public <R extends BuildableQuery> StatementBuilder<S> apply(Function<S, R> action) {
Assert.notNull(action, "BindFunction must not be null");
queryActions.add((source, termFactory) -> action.apply(source));
queryActions.add((source, termFactory) -> (S) action.apply(source));
return this;
}
@@ -168,7 +176,7 @@ public class StatementBuilder<S extends BuildableQuery> {
if (parameterHandling == ParameterHandling.INLINE) {
TermFactory termFactory = value -> QueryBuilder.literal(value, codecRegistry);
TermFactory termFactory = value -> toLiteralTerms(value, codecRegistry);
for (BuilderRunnable<S> runnable : queryActions) {
statement = runnable.run(statement, termFactory);
@@ -214,6 +222,44 @@ public class StatementBuilder<S extends BuildableQuery> {
throw new UnsupportedOperationException(String.format("ParameterHandling %s not supported", parameterHandling));
}
private static Term toLiteralTerms(@Nullable Object value, CodecRegistry codecRegistry) {
if (value instanceof List) {
List<Term> terms = new ArrayList<>();
for (Object o : (List<Object>) value) {
terms.add(toLiteralTerms(o, codecRegistry));
}
return new ListTerm(terms);
}
if (value instanceof Set) {
List<Term> terms = new ArrayList<>();
for (Object o : (Set<Object>) value) {
terms.add(toLiteralTerms(o, codecRegistry));
}
return new SetTerm(terms);
}
if (value instanceof Map) {
Map<Term, Term> terms = new LinkedHashMap<>();
((Map<?, ?>) value).forEach((k, v) -> {
terms.put(toLiteralTerms(k, codecRegistry), toLiteralTerms(v, codecRegistry));
});
return new MapTerm(terms);
}
return QueryBuilder.literal(value, codecRegistry);
}
private SimpleStatementBuilder onBuild(SimpleStatementBuilder statementBuilder) {
onBuild.forEach(it -> it.accept(statementBuilder));
@@ -264,4 +310,111 @@ public class StatementBuilder<S extends BuildableQuery> {
*/
BY_NAME;
}
static class ListTerm implements Term {
private final Collection<? extends Term> components;
public ListTerm(@NonNull Collection<? extends Term> components) {
this.components = components;
}
@Override
public void appendTo(@NonNull StringBuilder builder) {
if (components.isEmpty()) {
builder.append("[]");
return;
}
CqlHelper.append(components, builder, "[", ",", "]");
}
@Override
public boolean isIdempotent() {
for (Term component : components) {
if (!component.isIdempotent()) {
return false;
}
}
return true;
}
}
static class SetTerm implements Term {
private final Collection<? extends Term> components;
public SetTerm(@NonNull Collection<? extends Term> components) {
this.components = components;
}
@Override
public void appendTo(@NonNull StringBuilder builder) {
if (components.isEmpty()) {
builder.append("{}");
return;
}
CqlHelper.append(components, builder, "{", ",", "}");
}
@Override
public boolean isIdempotent() {
for (Term component : components) {
if (!component.isIdempotent()) {
return false;
}
}
return true;
}
}
static class MapTerm implements Term {
private final Map<? extends Term, ? extends Term> components;
public MapTerm(Map<? extends Term, ? extends Term> components) {
this.components = components;
}
@Override
public void appendTo(@NonNull StringBuilder builder) {
if (components.isEmpty()) {
builder.append("{}");
return;
}
boolean first = true;
for (Map.Entry<? extends Term, ? extends Term> entry : components.entrySet()) {
if (first) {
builder.append("{");
first = false;
} else {
builder.append(",");
}
entry.getKey().appendTo(builder);
builder.append(":");
entry.getValue().appendTo(builder);
}
if (!first) {
builder.append("}");
}
}
@Override
public boolean isIdempotent() {
for (Map.Entry<? extends Term, ? extends Term> entry : components.entrySet()) {
if (!entry.getKey().isIdempotent() || !entry.getValue().isIdempotent()) {
return false;
}
}
return true;
}
}
}

View File

@@ -107,7 +107,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
return determineName(annotation.value(), annotation.forceQuote());
}
return CqlIdentifier.fromCql(getType().getSimpleName());
return IdentifierFactory.create(getType().getSimpleName(), false);
}
CqlIdentifier determineName(String value, boolean forceQuote) {

View File

@@ -48,11 +48,11 @@ import org.springframework.util.StringUtils;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.data.TupleValue;
import com.datastax.oss.driver.api.core.data.UdtValue;
import com.datastax.oss.driver.api.core.detach.AttachmentPoint;
import com.datastax.oss.driver.api.core.type.DataType;
import com.datastax.oss.driver.api.core.type.DataTypes;
import com.datastax.oss.driver.api.core.type.TupleType;
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
import com.datastax.oss.driver.internal.core.metadata.schema.ShallowUserDefinedType;
/**
* Default implementation of a {@link MappingContext} for Cassandra using {@link CassandraPersistentEntity} and
@@ -466,23 +466,26 @@ public class CassandraMappingContext
CassandraPersistentEntity<?> primaryKeyEntity = getRequiredPersistentEntity(property.getRawType());
for (CassandraPersistentProperty primaryKeyProperty : primaryKeyEntity) {
DataType dataType = getDataTypeWithUserTypeFactory(primaryKeyProperty, DataTypeProvider.ShallowType);
if (primaryKeyProperty.isPartitionKeyColumn()) {
specification.partitionKeyColumn(primaryKeyProperty.getRequiredColumnName(),
getDataType(primaryKeyProperty));
specification.partitionKeyColumn(primaryKeyProperty.getRequiredColumnName(), dataType);
} else { // cluster column
specification.clusteredKeyColumn(primaryKeyProperty.getRequiredColumnName(),
getDataType(primaryKeyProperty), primaryKeyProperty.getPrimaryKeyOrdering());
specification.clusteredKeyColumn(primaryKeyProperty.getRequiredColumnName(), dataType,
primaryKeyProperty.getPrimaryKeyOrdering());
}
}
} else {
DataType type = UserTypeUtil
.potentiallyFreeze(getDataTypeWithUserTypeFactory(property, DataTypeProvider.ShallowType));
if (property.isIdProperty() || property.isPartitionKeyColumn()) {
specification.partitionKeyColumn(property.getRequiredColumnName(),
UserTypeUtil.potentiallyFreeze(getDataType(property)));
specification.partitionKeyColumn(property.getRequiredColumnName(), type);
} else if (property.isClusterKeyColumn()) {
specification.clusteredKeyColumn(property.getRequiredColumnName(),
UserTypeUtil.potentiallyFreeze(getDataType(property)), property.getPrimaryKeyOrdering());
specification.clusteredKeyColumn(property.getRequiredColumnName(), type, property.getPrimaryKeyOrdering());
} else {
specification.column(property.getRequiredColumnName(), UserTypeUtil.potentiallyFreeze(getDataType(property)));
specification.column(property.getRequiredColumnName(), type);
}
}
}
@@ -838,19 +841,31 @@ public class CassandraMappingContext
}
},
FrozenLiteral {
ShallowType {
@Override
public DataType getDataType(CassandraPersistentEntity<?> entity) {
return new ShallowUserDefinedType(com.datastax.oss.driver.api.core.CqlIdentifier.fromCql("system"),
entity.getTableName(), true);
return entity.isTupleType() ? entity.getTupleType() : new ShallowUserDefinedType(entity.getTableName(), false);
}
@Override
DataType getUserType(com.datastax.oss.driver.api.core.CqlIdentifier userTypeName,
UserTypeResolver userTypeResolver) {
return new ShallowUserDefinedType(com.datastax.oss.driver.api.core.CqlIdentifier.fromCql("system"),
userTypeName, true);
return new ShallowUserDefinedType(userTypeName, false);
}
},
FrozenLiteral {
@Override
public DataType getDataType(CassandraPersistentEntity<?> entity) {
return new ShallowUserDefinedType(entity.getTableName(), true);
}
@Override
DataType getUserType(com.datastax.oss.driver.api.core.CqlIdentifier userTypeName,
UserTypeResolver userTypeResolver) {
return new ShallowUserDefinedType(userTypeName, true);
}
};
@@ -876,4 +891,113 @@ public class CassandraMappingContext
UserTypeResolver userTypeResolver);
}
static class ShallowUserDefinedType implements com.datastax.oss.driver.api.core.type.UserDefinedType {
private final CqlIdentifier name;
private final boolean frozen;
public ShallowUserDefinedType(String name, boolean frozen) {
this(CqlIdentifier.fromInternal(name), frozen);
}
public ShallowUserDefinedType(CqlIdentifier name, boolean frozen) {
this.name = name;
this.frozen = frozen;
}
@Override
public CqlIdentifier getKeyspace() {
return null;
}
@Override
public CqlIdentifier getName() {
return name;
}
@Override
public boolean isFrozen() {
return frozen;
}
@Override
public List<CqlIdentifier> getFieldNames() {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public int firstIndexOf(CqlIdentifier id) {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public int firstIndexOf(String name) {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public List<DataType> getFieldTypes() {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public com.datastax.oss.driver.api.core.type.UserDefinedType copy(boolean newFrozen) {
return new ShallowUserDefinedType(this.name, newFrozen);
}
@Override
public UdtValue newValue() {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public UdtValue newValue(@edu.umd.cs.findbugs.annotations.NonNull Object... fields) {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public AttachmentPoint getAttachmentPoint() {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public boolean isDetached() {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public void attach(@edu.umd.cs.findbugs.annotations.NonNull AttachmentPoint attachmentPoint) {
throw new UnsupportedOperationException(
"This implementation should only be used internally, this is likely a driver bug");
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof com.datastax.oss.driver.api.core.type.UserDefinedType))
return false;
com.datastax.oss.driver.api.core.type.UserDefinedType that = (com.datastax.oss.driver.api.core.type.UserDefinedType) o;
return isFrozen() == that.isFrozen() && Objects.equals(getName(), that.getName());
}
@Override
public int hashCode() {
return Objects.hash(name, frozen);
}
@Override
public String toString() {
return "ShallowUserDefinedType{" + "name=" + name + ", frozen=" + frozen + '}';
}
}
}

View File

@@ -31,9 +31,9 @@ import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.core.data.TupleValue;
import com.datastax.oss.driver.api.core.data.UdtValue;
import com.datastax.oss.driver.api.core.type.DataType;
import com.datastax.oss.driver.api.core.type.DataTypes;
import com.datastax.oss.driver.api.core.type.UserDefinedType;
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
import com.datastax.oss.driver.api.core.type.reflect.GenericType;
@@ -82,7 +82,7 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
simpleTypes.add(Number.class);
simpleTypes.add(Row.class);
simpleTypes.add(TupleValue.class);
simpleTypes.add(UserDefinedType.class);
simpleTypes.add(UdtValue.class);
classToDataType = Collections.unmodifiableMap(classToDataType(codecRegistry, primitiveWrappers));
nameToDataType = Collections.unmodifiableMap(nameToDataType());

View File

@@ -23,7 +23,6 @@ import com.datastax.oss.driver.api.core.type.ListType;
import com.datastax.oss.driver.api.core.type.MapType;
import com.datastax.oss.driver.api.core.type.SetType;
import com.datastax.oss.driver.api.core.type.UserDefinedType;
import com.datastax.oss.driver.internal.core.metadata.schema.ShallowUserDefinedType;
/**
* {@link com.datastax.driver.core.UserType} utility methods. Mainly for internal use within the framework.
@@ -78,8 +77,7 @@ class UserTypeUtil {
}
if (isNonFrozenUdt(dataType)) {
UserDefinedType userDefinedType = (UserDefinedType) dataType;
return new ShallowUserDefinedType(userDefinedType.getKeyspace(), userDefinedType.getName(), true);
return ((UserDefinedType) dataType).copy(true);
}
return dataType;
@@ -92,5 +90,4 @@ class UserTypeUtil {
private static boolean isNonFrozenUdt(DataType dataType) {
return dataType instanceof UserDefinedType && !((UserDefinedType) dataType).isFrozen();
}
}

View File

@@ -177,7 +177,12 @@ public class CassandraPageRequest extends PageRequest {
*/
@Nullable
public ByteBuffer getPagingState() {
return this.pagingState;
if (this.pagingState == null) {
return null;
}
return this.pagingState.asReadOnlyBuffer();
}
/**
@@ -198,7 +203,7 @@ public class CassandraPageRequest extends PageRequest {
Assert.state(hasNext(), "Cannot create a next page request without a PagingState");
return new CassandraPageRequest(getPageNumber() + 1, getPageSize(), getSort(), this.pagingState, false);
return new CassandraPageRequest(getPageNumber() + 1, getPageSize(), getSort(), getPagingState(), false);
}
/**
@@ -212,7 +217,7 @@ public class CassandraPageRequest extends PageRequest {
Assert.notNull(sort, "Sort must not be null");
return new CassandraPageRequest(this.getPageNumber(), this.getPageSize(), sort, this.pagingState, this.nextAllowed);
return new CassandraPageRequest(this.getPageNumber(), this.getPageSize(), sort, getPagingState(), this.nextAllowed);
}
/* (non-Javadoc)

View File

@@ -18,6 +18,7 @@ package org.springframework.data.cassandra.core.query;
import lombok.EqualsAndHashCode;
import java.util.Optional;
import java.util.function.Function;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -84,6 +85,18 @@ public interface CriteriaDefinition {
public Object getValue() {
return this.value;
}
/**
* This method allows the application of a function to this {@link Predicate} value. The function should expect a
* single {@link Object} argument and produce an {@code R} result. Any exception thrown by f() will be propagated to
* the caller.
*
* @param <R>
* @return the result of the {@link Function mappingFunction}.
*/
public <R> R as(Function<Object, ? extends R> mappingFunction) {
return mappingFunction.apply(this.value);
}
}
/**

View File

@@ -21,13 +21,15 @@ import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.springframework.data.cassandra.core.cql.KeyspaceIdentifier;
import org.springframework.data.cassandra.core.cql.keyspace.AlterKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.DropKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceActionSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceOption.ReplicationStrategy;
import com.datastax.oss.driver.api.core.CqlIdentifier;
/**
* Unit tests for {@link KeyspaceActionSpecificationFactoryBean}.
*
@@ -53,7 +55,7 @@ public class KeyspaceActionSpecificationFactoryBeanUnitTests {
CreateKeyspaceSpecification create = (CreateKeyspaceSpecification) actions.get(0);
assertThat(create.getName()).isEqualTo(KeyspaceIdentifier.of("my_keyspace"));
assertThat(create.getName()).isEqualTo(CqlIdentifier.fromCql("my_keyspace"));
assertThat(create.getOptions()).containsKeys("durable_writes", "replication");
}
@@ -72,7 +74,7 @@ public class KeyspaceActionSpecificationFactoryBeanUnitTests {
DropKeyspaceSpecification drop = (DropKeyspaceSpecification) actions.get(1);
assertThat(drop.getName()).isEqualTo(KeyspaceIdentifier.of("my_keyspace"));
assertThat(drop.getName()).isEqualTo(CqlIdentifier.fromCql("my_keyspace"));
}
@Test // DATACASS-502
@@ -93,7 +95,7 @@ public class KeyspaceActionSpecificationFactoryBeanUnitTests {
AlterKeyspaceSpecification alter = (AlterKeyspaceSpecification) actions.get(0);
assertThat(alter.getName()).isEqualTo(KeyspaceIdentifier.of("my_keyspace"));
assertThat(alter.getName()).isEqualTo(CqlIdentifier.fromCql("my_keyspace"));
assertThat(alter.getOptions()).containsKeys("durable_writes", "replication");
}
@@ -113,7 +115,7 @@ public class KeyspaceActionSpecificationFactoryBeanUnitTests {
AlterKeyspaceSpecification alter = (AlterKeyspaceSpecification) actions.get(0);
assertThat(alter.getName()).isEqualTo(KeyspaceIdentifier.of("my_keyspace"));
assertThat(alter.getName()).isEqualTo(CqlIdentifier.fromCql("my_keyspace"));
assertThat(alter.getOptions()).containsKeys("durable_writes", "replication");
}
@@ -131,7 +133,7 @@ public class KeyspaceActionSpecificationFactoryBeanUnitTests {
AlterKeyspaceSpecification alter = (AlterKeyspaceSpecification) actions.get(0);
assertThat(alter.getName()).isEqualTo(KeyspaceIdentifier.of("my_keyspace"));
assertThat(alter.getName()).isEqualTo(CqlIdentifier.fromCql("my_keyspace"));
assertThat(alter.getOptions()).doesNotContainKeys("replication");
}
}

View File

@@ -19,44 +19,42 @@ package org.springframework.data.cassandra.config;
import static org.assertj.core.api.Assertions.*;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.data.cassandra.core.cql.SessionCallback;
import org.springframework.data.cassandra.core.cql.session.init.KeyspacePopulator;
import org.springframework.data.cassandra.core.cql.session.init.ResourceKeyspacePopulator;
import org.springframework.data.cassandra.domain.Person;
import org.springframework.data.cassandra.test.util.AbstractKeyspaceCreatingIntegrationTest;
import org.springframework.data.cassandra.repository.support.IntegrationTestConfig;
import org.springframework.data.cassandra.test.util.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata;
import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata;
/**
* Integration test testing various {@link SchemaAction SchemaActions} on startup of a Spring configured,
* Apache Cassandra application client.
* Integration test testing various {@link SchemaAction SchemaActions} on startup of a Spring configured, Apache
* Cassandra application client.
*
* @author John Blum
* @author Mark Paluch
* @see org.springframework.data.cassandra.test.util.AbstractKeyspaceCreatingIntegrationTest
*/
public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest {
public class SchemaActionIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest {
protected static final String CREATE_PERSON_TABLE_CQL =
"CREATE TABLE IF NOT EXISTS person (id int, firstName text, lastName text, PRIMARY KEY(id));";
protected static final String DROP_ADDRESS_TYPE_CQL = "DROP TYPE IF EXISTS address";
protected static final String DROP_PERSON_TABLE_CQL = "DROP TABLE IF EXISTS person";
protected static final String CREATE_PERSON_TABLE_CQL = "CREATE TABLE IF NOT EXISTS person (id int, firstName text, lastName text, PRIMARY KEY(id));";
protected ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(annotatedClasses);
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses);
applicationContext.registerShutdownHook();
@@ -74,7 +72,7 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
@SuppressWarnings("all")
protected void assertTableWithColumnsExists(CqlSession session, String tableName, String... columns) {
KeyspaceMetadata keyspaceMetadata = session.getMetadata().getKeyspace(session.getKeyspace().get()).orElse(null);
KeyspaceMetadata keyspaceMetadata = session.refreshSchema().getKeyspace(session.getKeyspace().get()).orElse(null);
assertThat(keyspaceMetadata).isNotNull();
@@ -90,23 +88,13 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
assertThat(tableMetadata.getColumns()).hasSize(columns.length);
}
@Before
public void setup() {
CqlSession session = getSession();
session.execute(DROP_PERSON_TABLE_CQL);
session.execute(DROP_ADDRESS_TYPE_CQL);
}
@Test
public void createWithNoExistingTableCreatesTableFromEntity() {
doInSessionWithConfiguration(CreateWithNoExistingTableConfiguration.class, session -> {
assertTableWithColumnsExists(session, "person", "firstName", "lastName", "nickname",
"birthDate", "numberOfChildren", "cool", "createdDate", "zoneId", "mainAddress",
"alternativeAddresses");
assertTableWithColumnsExists(session, "person", "firstName", "lastName", "nickname", "birthDate",
"numberOfChildren", "cool", "createdDate", "zoneId", "mainAddress", "alternativeAddresses");
return null;
});
@@ -118,6 +106,7 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
try {
doInSessionWithConfiguration(CreateWithExistingTableConfiguration.class, session -> {
fail(String.format("%s should have failed", CreateWithExistingTableConfiguration.class.getSimpleName()));
return null;
});
@@ -125,7 +114,7 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
fail("Expected BeanCreationException");
} catch (BeanCreationException cause) {
assertThat(cause).hasMessageContaining(String.format("Table %s.person already exists", getKeyspace()));
assertThat(cause).hasMessageContaining("person already exists");
}
}
@@ -134,9 +123,8 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
doInSessionWithConfiguration(CreateIfNotExistsWithNoExistingTableConfiguration.class, session -> {
assertTableWithColumnsExists(session, "person", "firstName", "lastName", "nickname",
"birthDate", "numberOfChildren", "cool", "createdDate", "zoneId", "mainAddress",
"alternativeAddresses");
assertTableWithColumnsExists(session, "person", "firstName", "lastName", "nickname", "birthDate",
"numberOfChildren", "cool", "createdDate", "zoneId", "mainAddress", "alternativeAddresses");
return null;
});
@@ -158,25 +146,15 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
doInSessionWithConfiguration(RecreateSchemaActionWithExistingTableConfiguration.class, session -> {
assertTableWithColumnsExists(session, "person", "firstName", "lastName", "nickname",
"birthDate", "numberOfChildren", "cool", "createdDate", "zoneId", "mainAddress",
"alternativeAddresses");
assertTableWithColumnsExists(session, "person", "firstName", "lastName", "nickname", "birthDate",
"numberOfChildren", "cool", "createdDate", "zoneId", "mainAddress", "alternativeAddresses");
return null;
});
}
@Configuration
static class CreateWithNoExistingTableConfiguration extends CassandraConfiguration {
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE;
}
}
@Configuration
static class CreateWithExistingTableConfiguration extends CassandraConfiguration {
static class CreateWithNoExistingTableConfiguration extends IntegrationTestConfig {
@Override
public SchemaAction getSchemaAction() {
@@ -184,22 +162,33 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
}
@Override
protected List<String> getStartupScripts() {
return Collections.singletonList(CREATE_PERSON_TABLE_CQL);
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.singleton(Person.class);
}
}
@Configuration
static class CreateIfNotExistsWithNoExistingTableConfiguration extends CassandraConfiguration {
static class CreateWithExistingTableConfiguration extends IntegrationTestConfig {
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE_IF_NOT_EXISTS;
return SchemaAction.CREATE;
}
@Nullable
@Override
protected KeyspacePopulator keyspacePopulator() {
return new ResourceKeyspacePopulator(new ByteArrayResource(CREATE_PERSON_TABLE_CQL.getBytes()));
}
@Override
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.singleton(Person.class);
}
}
@Configuration
static class CreateIfNotExistsWithExistingTableConfiguration extends CassandraConfiguration {
static class CreateIfNotExistsWithNoExistingTableConfiguration extends IntegrationTestConfig {
@Override
public SchemaAction getSchemaAction() {
@@ -207,36 +196,48 @@ public class SchemaActionIntegrationTests extends AbstractKeyspaceCreatingIntegr
}
@Override
protected List<String> getStartupScripts() {
return Collections.singletonList(CREATE_PERSON_TABLE_CQL);
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.singleton(Person.class);
}
}
@Configuration
static class RecreateSchemaActionWithExistingTableConfiguration extends CassandraConfiguration {
static class CreateIfNotExistsWithExistingTableConfiguration extends IntegrationTestConfig {
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE_IF_NOT_EXISTS;
}
@Nullable
@Override
protected KeyspacePopulator keyspacePopulator() {
return new ResourceKeyspacePopulator(new ByteArrayResource(CREATE_PERSON_TABLE_CQL.getBytes()));
}
@Override
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.singleton(Person.class);
}
}
@Configuration
static class RecreateSchemaActionWithExistingTableConfiguration extends IntegrationTestConfig {
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE;
}
@Nullable
@Override
protected List<String> getStartupScripts() {
return Collections.singletonList(CREATE_PERSON_TABLE_CQL);
protected KeyspacePopulator keyspacePopulator() {
return new ResourceKeyspacePopulator(new ByteArrayResource(CREATE_PERSON_TABLE_CQL.getBytes()));
}
}
@Configuration
static abstract class CassandraConfiguration extends AbstractCassandraConfiguration {
@Override
protected Set<Class<?>> getInitialEntitySet() {
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.singleton(Person.class);
}
@Override
protected String getKeyspaceName() {
return keyspaceRule.getKeyspaceName();
}
}
}

View File

@@ -204,7 +204,7 @@ public class AsyncCassandraTemplateIntegrationTests extends AbstractKeyspaceCrea
}
@Test // DATACASS-292
public void updateShouldUpdateEntityWithLwt() {
public void updateShouldUpdateEntityWithLwt() throws InterruptedException {
UpdateOptions lwtOptions = UpdateOptions.builder().withIfExists().build();
@@ -217,6 +217,10 @@ public class AsyncCassandraTemplateIntegrationTests extends AbstractKeyspaceCrea
assertThat(getUninterruptibly(updated).wasApplied()).isTrue();
assertThat(getUninterruptibly(updated).getEntity()).isSameAs(user);
// Cassandra requires a while to apply that change...
Thread.sleep(200);
assertThat(getUser(user.getId()).getFirstname()).isEqualTo("Walter Hartwell");
}

View File

@@ -46,12 +46,14 @@ import org.springframework.data.cassandra.domain.VersionedUser;
import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.util.concurrent.ListenableFuture;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.core.type.DataTypes;
@@ -69,7 +71,7 @@ public class AsyncCassandraTemplateUnitTests {
@Mock ColumnDefinition columnDefinition;
@Mock ColumnDefinitions columnDefinitions;
@Captor ArgumentCaptor<Statement> statementCaptor;
@Captor ArgumentCaptor<SimpleStatement> statementCaptor;
AsyncCassandraTemplate template;
@@ -108,7 +110,7 @@ public class AsyncCassandraTemplateUnitTests {
public void selectUsingCqlShouldReturnMappedResults() {
when(resultSet.currentPage()).thenReturn(Collections.singleton(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
@@ -125,15 +127,14 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(list)).hasSize(1).contains(new User("myid", "Walter", "White"));
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users");
}
@Test // DATACASS-292
public void selectUsingCqlShouldInvokeCallbackWithMappedResults() {
when(resultSet.currentPage()).thenReturn(Collections.singletonList(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
when(columnDefinitions.firstIndexOf("firstname")).thenReturn(1);
@@ -152,7 +153,7 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(result)).isNull();
assertThat(list).hasSize(1).contains(new User("myid", "Walter", "White"));
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users");
}
@Test // DATACASS-292
@@ -176,7 +177,7 @@ public class AsyncCassandraTemplateUnitTests {
public void selectOneShouldReturnMappedResults() {
when(resultSet.currentPage()).thenReturn(Collections.singleton(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
@@ -189,18 +190,18 @@ public class AsyncCassandraTemplateUnitTests {
when(row.getObject(1)).thenReturn("Walter");
when(row.getObject(2)).thenReturn("White");
ListenableFuture<User> future = template.selectOne("SELECT * FROM users WHERE id='myid';", User.class);
ListenableFuture<User> future = template.selectOne("SELECT * FROM users WHERE id='myid'", User.class);
assertThat(getUninterruptibly(future)).isEqualTo(new User("myid", "Walter", "White"));
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid'");
}
@Test // DATACASS-292
public void selectOneByIdShouldReturnMappedResults() {
when(resultSet.currentPage()).thenReturn(Collections.singleton(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
when(columnDefinitions.firstIndexOf("firstname")).thenReturn(1);
@@ -216,7 +217,7 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(new User("myid", "Walter", "White"));
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-696
@@ -224,7 +225,7 @@ public class AsyncCassandraTemplateUnitTests {
when(resultSet.currentPage()).thenReturn(Collections.singleton(row));
ListenableFuture<String> future = template.selectOne("SELECT id FROM users WHERE id='myid';", String.class);
ListenableFuture<String> future = template.selectOne("SELECT id FROM users WHERE id='myid'", String.class);
assertThat(getUninterruptibly(future)).isNull();
}
@@ -232,37 +233,35 @@ public class AsyncCassandraTemplateUnitTests {
@Test // DATACASS-292
public void existsShouldReturnExistingElement() {
when(resultSet.currentPage()).thenReturn(Collections.singleton(row));
when(resultSet.one()).thenReturn(row);
ListenableFuture<Boolean> future = template.exists("myid", User.class);
assertThat(getUninterruptibly(future)).isTrue();
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-292
public void existsShouldReturnNonExistingElement() {
when(resultSet.currentPage()).thenReturn(Collections.emptyList());
ListenableFuture<Boolean> future = template.exists("myid", User.class);
assertThat(getUninterruptibly(future)).isFalse();
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-512
public void existsByQueryShouldReturnExistingElement() {
when(resultSet.currentPage()).thenReturn(Collections.singleton(row));
when(resultSet.one()).thenReturn(row);
ListenableFuture<Boolean> future = template.exists(Query.empty(), User.class);
assertThat(getUninterruptibly(future)).isTrue();
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users LIMIT 1;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users LIMIT 1");
}
@Test // DATACASS-292
@@ -276,7 +275,7 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(42L);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT count(*) FROM users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT count(1) FROM users");
}
@Test // DATACASS-292
@@ -290,7 +289,7 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(42L);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT COUNT(1) FROM users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT count(1) FROM users");
}
@Test // DATACASS-292, DATACASS-618
@@ -304,8 +303,8 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(user);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White');");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White')");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -321,8 +320,8 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(user);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','heisenberg','White',0) IF NOT EXISTS;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','heisenberg','White',0) IF NOT EXISTS");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -357,8 +356,8 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(user);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg'");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -375,8 +374,8 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(user);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE vusers SET firstname='Walter',lastname='White',version=1 WHERE id='heisenberg' IF version=0;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"UPDATE vusers SET firstname='Walter', lastname='White', version=1 WHERE id='heisenberg' IF version=0");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -390,8 +389,8 @@ public class AsyncCassandraTemplateUnitTests {
template.update(user, updateOptions);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF EXISTS;");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg' IF EXISTS");
}
@Test // DATACASS-575
@@ -403,8 +402,8 @@ public class AsyncCassandraTemplateUnitTests {
template.update(user, options);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-575
@@ -416,7 +415,8 @@ public class AsyncCassandraTemplateUnitTests {
template.update(query, update, User.class);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("UPDATE users SET firstname='Walter' WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter' WHERE id='heisenberg'");
}
@Test // DATACASS-575
@@ -432,8 +432,8 @@ public class AsyncCassandraTemplateUnitTests {
template.update(query, update, User.class);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE users SET firstname='Walter' WHERE id='heisenberg' IF firstname='Walter' AND lastname='White';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"UPDATE users SET firstname='Walter' WHERE id='heisenberg' IF firstname='Walter' AND lastname='White'");
}
@Test // DATACASS-292
@@ -466,7 +466,7 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isTrue();
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("DELETE FROM users WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("DELETE FROM users WHERE id='heisenberg'");
}
@Test // DATACASS-292
@@ -480,7 +480,7 @@ public class AsyncCassandraTemplateUnitTests {
assertThat(getUninterruptibly(future)).isEqualTo(user);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("DELETE FROM users WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("DELETE FROM users WHERE id='heisenberg'");
}
@Test // DATACASS-575
@@ -492,8 +492,8 @@ public class AsyncCassandraTemplateUnitTests {
template.delete(user, options);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-575
@@ -505,8 +505,8 @@ public class AsyncCassandraTemplateUnitTests {
template.delete(query, User.class);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-292
@@ -534,7 +534,7 @@ public class AsyncCassandraTemplateUnitTests {
template.truncate(User.class);
verify(session).executeAsync(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("TRUNCATE users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("TRUNCATE users");
}
private static <T> T getUninterruptibly(Future<T> future) {

View File

@@ -110,7 +110,8 @@ public class CassandraPersistentEntitySchemaDropperUnitTests extends CassandraPe
context.setInitialEntitySet(Collections.singleton(Person.class));
context.afterPropertiesSet();
when(metadata.getTables()).thenReturn(createTables(person, contact));
Map<CqlIdentifier, TableMetadata> tables = createTables(person, contact);
when(metadata.getTables()).thenReturn(tables);
CassandraPersistentEntitySchemaDropper schemaDropper = new CassandraPersistentEntitySchemaDropper(context,
operations);
@@ -129,7 +130,8 @@ public class CassandraPersistentEntitySchemaDropperUnitTests extends CassandraPe
context.setInitialEntitySet(Collections.singleton(Person.class));
context.afterPropertiesSet();
when(metadata.getTables()).thenReturn(createTables(person, contact));
Map<CqlIdentifier, TableMetadata> tables = createTables(person, contact);
when(metadata.getTables()).thenReturn(tables);
CassandraPersistentEntitySchemaDropper schemaDropper = new CassandraPersistentEntitySchemaDropper(context,
operations);

View File

@@ -316,7 +316,7 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI
}
@Test // DATACASS-292
public void updateShouldUpdateEntityWithLwt() {
public void updateShouldUpdateEntityWithLwt() throws InterruptedException {
UpdateOptions lwtOptions = UpdateOptions.builder().withIfExists().build();
@@ -329,6 +329,9 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI
WriteResult lwt = template.update(user, lwtOptions);
assertThat(lwt.wasApplied()).isTrue();
// Await until Cassandra has persisted the change
Thread.sleep(300);
assertThat(template.selectOneById(user.getId(), User.class).getFirstname()).isEqualTo("Walter Hartwell");
}

View File

@@ -24,7 +24,6 @@ import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -42,12 +41,14 @@ import org.springframework.data.cassandra.domain.User;
import org.springframework.data.cassandra.domain.VersionedUser;
import org.springframework.data.mapping.callback.EntityCallbacks;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
import com.datastax.oss.driver.api.core.cql.ResultSet;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.core.type.DataTypes;
@@ -65,7 +66,7 @@ public class CassandraTemplateUnitTests {
@Mock ColumnDefinition columnDefinition;
@Mock ColumnDefinitions columnDefinitions;
@Captor ArgumentCaptor<Statement<?>> statementCaptor;
@Captor ArgumentCaptor<SimpleStatement> statementCaptor;
CassandraTemplate template;
@@ -104,7 +105,7 @@ public class CassandraTemplateUnitTests {
public void selectUsingCqlShouldReturnMappedResults() {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
@@ -121,7 +122,7 @@ public class CassandraTemplateUnitTests {
assertThat(list).hasSize(1).contains(new User("myid", "Walter", "White"));
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users");
}
@Test // DATACASS-292
@@ -142,7 +143,7 @@ public class CassandraTemplateUnitTests {
public void selectOneShouldReturnMappedResults() {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
when(columnDefinitions.firstIndexOf("firstname")).thenReturn(1);
@@ -154,11 +155,11 @@ public class CassandraTemplateUnitTests {
when(row.getObject(1)).thenReturn("Walter");
when(row.getObject(2)).thenReturn("White");
User user = template.selectOne("SELECT * FROM users WHERE id='myid';", User.class);
User user = template.selectOne("SELECT * FROM users WHERE id='myid'", User.class);
assertThat(user).isEqualTo(new User("myid", "Walter", "White"));
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid'");
}
@Test // DATACASS-696
@@ -166,7 +167,7 @@ public class CassandraTemplateUnitTests {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
String nullValue = template.selectOne("SELECT id FROM users WHERE id='myid';", String.class);
String nullValue = template.selectOne("SELECT id FROM users WHERE id='myid'", String.class);
assertThat(nullValue).isNull();
}
@@ -175,7 +176,7 @@ public class CassandraTemplateUnitTests {
public void selectOneByIdShouldReturnMappedResults() {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
when(columnDefinitions.firstIndexOf("firstname")).thenReturn(1);
@@ -191,14 +192,14 @@ public class CassandraTemplateUnitTests {
assertThat(user).isEqualTo(new User("myid", "Walter", "White"));
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-313
public void selectProjectedOneShouldReturnMappedResults() {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
@@ -210,43 +211,41 @@ public class CassandraTemplateUnitTests {
assertThat(user.getFirstname()).isEqualTo("Walter");
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT firstname FROM users LIMIT 2;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT firstname FROM users LIMIT 2");
}
@Test // DATACASS-292
public void existsShouldReturnExistingElement() {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
when(resultSet.one()).thenReturn(row);
boolean exists = template.exists("myid", User.class);
assertThat(exists).isTrue();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-292
public void existsShouldReturnNonExistingElement() {
when(resultSet.iterator()).thenReturn(Collections.emptyIterator());
boolean exists = template.exists("myid", User.class);
assertThat(exists).isFalse();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-512
public void existsByQueryShouldReturnExistingElement() {
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
when(resultSet.one()).thenReturn(row);
boolean exists = template.exists(Query.empty(), User.class);
assertThat(exists).isTrue();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users LIMIT 1;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users LIMIT 1");
}
@Test // DATACASS-292
@@ -260,7 +259,7 @@ public class CassandraTemplateUnitTests {
assertThat(count).isEqualTo(42L);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT count(*) FROM users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT count(1) FROM users");
}
@Test // DATACASS-512
@@ -274,7 +273,7 @@ public class CassandraTemplateUnitTests {
assertThat(count).isEqualTo(42L);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT COUNT(1) FROM users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT count(1) FROM users");
}
@Test // DATACASS-292, DATACASS-618
@@ -287,8 +286,8 @@ public class CassandraTemplateUnitTests {
template.insert(user);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White');");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White')");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -303,8 +302,8 @@ public class CassandraTemplateUnitTests {
template.insert(user);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','heisenberg','White',0) IF NOT EXISTS;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','heisenberg','White',0) IF NOT EXISTS");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -321,8 +320,8 @@ public class CassandraTemplateUnitTests {
template.insert(user, insertOptions);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White') IF NOT EXISTS;");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White') IF NOT EXISTS");
}
@Test // DATACASS-560
@@ -337,8 +336,8 @@ public class CassandraTemplateUnitTests {
template.insert(user, insertOptions);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("INSERT INTO users (firstname,id,lastname) VALUES (null,'heisenberg',null);");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES (NULL,'heisenberg',NULL)");
}
@Test // DATACASS-292
@@ -378,8 +377,8 @@ public class CassandraTemplateUnitTests {
template.update(user);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg'");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -395,8 +394,8 @@ public class CassandraTemplateUnitTests {
template.update(user);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE vusers SET firstname='Walter',lastname='White',version=1 WHERE id='heisenberg' IF version=0;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"UPDATE vusers SET firstname='Walter', lastname='White', version=1 WHERE id='heisenberg' IF version=0");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -414,8 +413,8 @@ public class CassandraTemplateUnitTests {
assertThat(writeResult.wasApplied()).isTrue();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF EXISTS;");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg' IF EXISTS");
}
@Test // DATACASS-575
@@ -427,8 +426,8 @@ public class CassandraTemplateUnitTests {
template.update(user, options);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-575
@@ -440,7 +439,8 @@ public class CassandraTemplateUnitTests {
template.update(query, update, User.class);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("UPDATE users SET firstname='Walter' WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter' WHERE id='heisenberg'");
}
@Test // DATACASS-575
@@ -456,8 +456,8 @@ public class CassandraTemplateUnitTests {
template.update(query, update, User.class);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE users SET firstname='Walter' WHERE id='heisenberg' IF firstname='Walter' AND lastname='White';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"UPDATE users SET firstname='Walter' WHERE id='heisenberg' IF firstname='Walter' AND lastname='White'");
}
@Test // DATACASS-292
@@ -486,7 +486,7 @@ public class CassandraTemplateUnitTests {
assertThat(deleted).isTrue();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("DELETE FROM users WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("DELETE FROM users WHERE id='heisenberg'");
}
@Test // DATACASS-292
@@ -497,7 +497,7 @@ public class CassandraTemplateUnitTests {
template.delete(user);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("DELETE FROM users WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("DELETE FROM users WHERE id='heisenberg'");
}
@Test // DATACASS-575
@@ -509,8 +509,8 @@ public class CassandraTemplateUnitTests {
template.delete(user, options);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-575
@@ -522,8 +522,8 @@ public class CassandraTemplateUnitTests {
template.delete(query, User.class);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-292
@@ -547,16 +547,7 @@ public class CassandraTemplateUnitTests {
template.truncate(User.class);
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("TRUNCATE users;");
}
@Test // DATACASS-292
@Ignore
public void batchOperationsShouldCallSession() {
template.batchOps().insert(new User()).execute();
verifyNoInteractions(session);
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("TRUNCATE users");
}
interface UserProjection {

View File

@@ -19,8 +19,6 @@ import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
@@ -33,35 +31,33 @@ import com.datastax.oss.driver.api.querybuilder.select.Select;
*/
public class EntityQueryUtilsUnitTests {
private final MappingCassandraConverter converter = new MappingCassandraConverter();
@Test // DATACASS-106
public void shouldRetrieveTableNameFromSelect() {
Select select = QueryBuilder.selectFrom("keyspace", "table").all().where();
Select select = QueryBuilder.selectFrom("ks", "tbl").all().where();
CqlIdentifier tableName = EntityQueryUtils.getTableName(select.build());
assertThat(tableName).isEqualTo(CqlIdentifier.fromCql("table"));
assertThat(tableName).isEqualTo(CqlIdentifier.fromInternal("tbl"));
}
@Test // DATACASS-642
public void shouldRetrieveQuotedTableNameFromSelect() {
Select select = QueryBuilder.selectFrom("keyspace", "\"table\"").all().where();
Select select = QueryBuilder.selectFrom(CqlIdentifier.fromCql("\"table\"")).all().where();
CqlIdentifier tableName = EntityQueryUtils.getTableName(select.build());
assertThat(tableName).isEqualTo(CqlIdentifier.fromCql("table"));
assertThat(tableName).isEqualTo(CqlIdentifier.fromInternal("table"));
}
@Test // DATACASS-106
public void shouldRetrieveTableNameFromSimpleStatement() {
assertThat(EntityQueryUtils.getTableName(SimpleStatement.newInstance("SELECT * FROM table")))
.isEqualTo(CqlIdentifier.fromCql("table"));
.isEqualTo(CqlIdentifier.fromInternal("table"));
assertThat(EntityQueryUtils.getTableName(SimpleStatement.newInstance("SELECT * FROM foo.table where")))
.isEqualTo(CqlIdentifier.fromCql("table"));
.isEqualTo(CqlIdentifier.fromInternal("table"));
}
@Test // DATACASS-106
@@ -69,6 +65,6 @@ public class EntityQueryUtilsUnitTests {
CqlIdentifier tableName = EntityQueryUtils.getTableName(SimpleStatement.newInstance("SELECT * from \"table\""));
assertThat(tableName).isEqualTo(CqlIdentifier.fromCql("table"));
assertThat(tableName).isEqualTo(CqlIdentifier.fromInternal("table"));
}
}

View File

@@ -43,10 +43,12 @@ import org.springframework.data.cassandra.domain.User;
import org.springframework.data.cassandra.domain.VersionedUser;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.core.type.DataTypes;
@@ -64,7 +66,7 @@ public class ReactiveCassandraTemplateUnitTests {
@Mock ColumnDefinition columnDefinition;
@Mock ColumnDefinitions columnDefinitions;
@Captor ArgumentCaptor<Statement<?>> statementCaptor;
@Captor ArgumentCaptor<SimpleStatement> statementCaptor;
ReactiveCassandraTemplate template;
@@ -103,7 +105,7 @@ public class ReactiveCassandraTemplateUnitTests {
public void selectUsingCqlShouldReturnMappedResults() {
when(reactiveResultSet.rows()).thenReturn(Flux.just(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
@@ -121,7 +123,7 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users");
}
@Test // DATACASS-335
@@ -139,7 +141,7 @@ public class ReactiveCassandraTemplateUnitTests {
public void selectOneByIdShouldReturnMappedResults() {
when(reactiveResultSet.rows()).thenReturn(Flux.just(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
when(columnDefinitions.firstIndexOf("firstname")).thenReturn(1);
@@ -156,14 +158,14 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-313
public void selectProjectedOneShouldReturnMappedResults() {
when(reactiveResultSet.rows()).thenReturn(Flux.just(row));
when(columnDefinitions.contains(anyString())).thenReturn(true);
when(columnDefinitions.contains(any(CqlIdentifier.class))).thenReturn(true);
when(columnDefinitions.get(anyInt())).thenReturn(columnDefinition);
when(columnDefinitions.firstIndexOf("id")).thenReturn(0);
@@ -179,7 +181,7 @@ public class ReactiveCassandraTemplateUnitTests {
}).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT firstname FROM users LIMIT 1;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT firstname FROM users LIMIT 1");
}
@Test // DATACASS-696
@@ -187,7 +189,7 @@ public class ReactiveCassandraTemplateUnitTests {
when(reactiveResultSet.rows()).thenReturn(Flux.just(row));
template.selectOne("SELECT id FROM users WHERE id='myid';", String.class).as(StepVerifier::create) //
template.selectOne("SELECT id FROM users WHERE id='myid'", String.class).as(StepVerifier::create) //
.verifyComplete();
}
@@ -199,7 +201,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.exists("myid", User.class).as(StepVerifier::create).expectNext(true).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-335
@@ -210,7 +212,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.exists("myid", User.class).as(StepVerifier::create).expectNext(false).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users WHERE id='myid';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users WHERE id='myid' LIMIT 1");
}
@Test // DATACASS-512
@@ -221,7 +223,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.exists(Query.empty(), User.class).as(StepVerifier::create).expectNext(true).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users LIMIT 1;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users LIMIT 1");
}
@Test // DATACASS-512
@@ -232,7 +234,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.exists(Query.empty(), User.class).as(StepVerifier::create).expectNext(false).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT * FROM users LIMIT 1;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT * FROM users LIMIT 1");
}
@Test // DATACASS-335
@@ -245,7 +247,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.count(User.class).as(StepVerifier::create).expectNext(42L).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT count(*) FROM users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT count(1) FROM users");
}
@Test // DATACASS-512
@@ -258,7 +260,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.count(Query.empty(), User.class).as(StepVerifier::create).expectNext(42L).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("SELECT COUNT(1) FROM users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("SELECT count(1) FROM users");
}
@Test // DATACASS-335, DATACASS-618
@@ -271,8 +273,8 @@ public class ReactiveCassandraTemplateUnitTests {
template.insert(user).as(StepVerifier::create).expectNext(user).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White');");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White')");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -287,8 +289,8 @@ public class ReactiveCassandraTemplateUnitTests {
StepVerifier.create(template.insert(user)).expectNext(user).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','heisenberg','White',0) IF NOT EXISTS;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','heisenberg','White',0) IF NOT EXISTS");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -317,8 +319,8 @@ public class ReactiveCassandraTemplateUnitTests {
template.update(user).as(StepVerifier::create).expectNext(user).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg'");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -335,8 +337,8 @@ public class ReactiveCassandraTemplateUnitTests {
StepVerifier.create(template.update(user)).expectNext(user).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE vusers SET firstname='Walter',lastname='White',version=1 WHERE id='heisenberg' IF version=0;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"UPDATE vusers SET firstname='Walter', lastname='White', version=1 WHERE id='heisenberg' IF version=0");
assertThat(beforeConvert).isSameAs(user);
assertThat(beforeSave).isSameAs(user);
}
@@ -355,8 +357,8 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF EXISTS;");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg' IF EXISTS");
}
@Test // DATACASS-575
@@ -373,8 +375,8 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter', lastname='White' WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-575
@@ -391,7 +393,8 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("UPDATE users SET firstname='Walter' WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("UPDATE users SET firstname='Walter' WHERE id='heisenberg'");
}
@Test // DATACASS-575
@@ -412,8 +415,8 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString(
"UPDATE users SET firstname='Walter' WHERE id='heisenberg' IF firstname='Walter' AND lastname='White';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo(
"UPDATE users SET firstname='Walter' WHERE id='heisenberg' IF firstname='Walter' AND lastname='White'");
}
@Test // DATACASS-335
@@ -427,7 +430,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.delete(user).as(StepVerifier::create).expectNext(user).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("DELETE FROM users WHERE id='heisenberg';");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("DELETE FROM users WHERE id='heisenberg'");
}
@Test // DATACASS-575
@@ -444,8 +447,8 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-575
@@ -462,8 +465,8 @@ public class ReactiveCassandraTemplateUnitTests {
.verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue())
.hasToString("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter';");
assertThat(statementCaptor.getValue().getQuery())
.isEqualTo("DELETE FROM users WHERE id='heisenberg' IF firstname='Walter'");
}
@Test // DATACASS-335
@@ -472,7 +475,7 @@ public class ReactiveCassandraTemplateUnitTests {
template.truncate(User.class).as(StepVerifier::create).verifyComplete();
verify(session).execute(statementCaptor.capture());
assertThat(statementCaptor.getValue()).hasToString("TRUNCATE users;");
assertThat(statementCaptor.getValue().getQuery()).isEqualTo("TRUNCATE users");
}
interface UserProjection {

View File

@@ -17,17 +17,22 @@ package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.convert.UpdateMapper;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder.ParameterHandling;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.Column;
import org.springframework.data.cassandra.core.query.Columns;
@@ -38,6 +43,7 @@ import org.springframework.data.cassandra.domain.Group;
import org.springframework.data.domain.Sort;
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
import com.datastax.oss.driver.api.querybuilder.select.Select;
/**
@@ -62,7 +68,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> select = statementFactory.select(Query.empty(),
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(select.build().toString()).isEqualTo("SELECT * FROM group;");
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT * FROM group");
}
@Test // DATACASS-343
@@ -72,7 +78,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> select = statementFactory.select(query, groupEntity);
assertThat(select.build().toString()).isEqualTo("SELECT age FROM group WHERE foo='bar';");
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT age FROM group WHERE foo='bar'");
}
@Test // DATACASS-549
@@ -82,7 +88,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> select = statementFactory.select(query, groupEntity);
assertThat(select.build().toString()).isEqualTo("SELECT age FROM group WHERE foo!='bar';");
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT age FROM group WHERE foo!='bar'");
}
@Test // DATACASS-549
@@ -92,7 +98,8 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> select = statementFactory.select(query, groupEntity);
assertThat(select.build().toString()).isEqualTo("SELECT age FROM group WHERE foo IS NOT NULL;");
assertThat(select.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("SELECT age FROM group WHERE foo IS NOT NULL");
}
@Test // DATACASS-343
@@ -103,7 +110,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> select = statementFactory.select(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(select.toString()).isEqualTo("SELECT TTL(email) FROM group;");
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT ttl(email) FROM group");
}
@Test // DATACASS-343
@@ -114,8 +121,8 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> select = statementFactory.select(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(select.build().toString())
.isEqualTo("SELECT * FROM group ORDER BY hash_prefix ASC LIMIT 10 ALLOW FILTERING;");
assertThat(select.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("SELECT * FROM group ORDER BY hash_prefix ASC LIMIT 10 ALLOW FILTERING");
}
@Test // DATACASS-343
@@ -126,18 +133,83 @@ public class StatementFactoryUnitTests {
StatementBuilder<Delete> delete = statementFactory.delete(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(delete.build().toString()).isEqualTo("DELETE age FROM group;");
assertThat(delete.build(ParameterHandling.INLINE).getQuery()).isEqualTo("DELETE age FROM group");
}
@Test // DATACASS-343
public void shouldMapDeleteQueryWithTtlColumns() {
public void shouldMapDeleteQueryWithTimestampColumns() {
Query query = Query.query(Criteria.where("foo").is("bar"));
DeleteOptions options = DeleteOptions.builder().timestamp(1234).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
StatementBuilder<Delete> delete = statementFactory.delete(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(delete.build().toString()).isEqualTo("DELETE FROM group WHERE foo='bar';");
assertThat(delete.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("DELETE FROM group USING TIMESTAMP 1234 WHERE foo='bar'");
}
@Test // DATACASS-656
public void shouldCreateInsert() {
Person person = new Person();
person.id = "foo";
StatementBuilder<RegularInsert> insert = statementFactory.insert(person, WriteOptions.empty());
assertThat(insert.build(ParameterHandling.INLINE).getQuery()).isEqualTo("INSERT INTO person (id) VALUES ('foo')");
}
@Test // DATACASS-656
public void shouldCreateInsertIfNotExists() {
InsertOptions options = InsertOptions.builder().withIfNotExists().build();
Person person = new Person();
person.id = "foo";
StatementBuilder<RegularInsert> insert = statementFactory.insert(person, options);
assertThat(insert.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("INSERT INTO person (id) VALUES ('foo') IF NOT EXISTS");
}
@Test // DATACASS-656
public void shouldCreateSetInsertNulls() {
InsertOptions options = InsertOptions.builder().withInsertNulls().build();
Person person = new Person();
person.id = "foo";
StatementBuilder<RegularInsert> insert = statementFactory.insert(person, options);
assertThat(insert.build(ParameterHandling.INLINE).getQuery()).isEqualTo(
"INSERT INTO person (first_name,id,list,map,number,set_col) VALUES (NULL,'foo',NULL,NULL,NULL,NULL)");
}
@Test // DATACASS-656
public void shouldCreateSetInsertWithTtl() {
WriteOptions options = WriteOptions.builder().ttl(Duration.ofMinutes(1)).build();
Person person = new Person();
person.id = "foo";
StatementBuilder<RegularInsert> insert = statementFactory.insert(person, options);
assertThat(insert.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("INSERT INTO person (id) VALUES ('foo') USING TTL 60");
}
@Test // DATACASS-656
public void shouldCreateSetInsertWithTimestamp() {
WriteOptions options = WriteOptions.builder().timestamp(1234).build();
Person person = new Person();
person.id = "foo";
StatementBuilder<RegularInsert> insert = statementFactory.insert(person, options);
assertThat(insert.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("INSERT INTO person (id) VALUES ('foo') USING TIMESTAMP 1234");
}
@Test // DATACASS-343
@@ -148,16 +220,44 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz").set("boo", "baa"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET first_name='baz',boo='baa' WHERE foo='bar';");
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET first_name='baz', boo='baa' WHERE foo='bar'");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateWithTtl() {
WriteOptions options = WriteOptions.builder().ttl(Duration.ofMinutes(1)).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person USING TTL 60 SET first_name='baz' WHERE foo='bar'");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateWithTimestamp() {
WriteOptions options = WriteOptions.builder().timestamp(1234).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person USING TIMESTAMP 1234 SET first_name='baz' WHERE foo='bar'");
}
@Test // DATACASS-343
@Ignore("No operator for set at index yet")
public void shouldCreateSetAtIndexUpdate() {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().set("list").atIndex(10).to("Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET list[10]='Euro';");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET list[10]='Euro'");
}
@Test // DATACASS-343
@@ -166,7 +266,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().set("map").atKey("baz").to("Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET map['baz']='Euro';");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET map['baz']='Euro'");
}
@Test // DATACASS-343
@@ -175,25 +275,28 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().addTo("map").entry("foo", "Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET map=map+{'foo':'Euro'};");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET map+={'foo':'Euro'}");
}
@Test // DATACASS-343
@Ignore("Missing operator")
public void shouldPrependAllToList() {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().addTo("list").prependAll("foo", "Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET list=['foo','Euro']+list;");
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET list=['foo','Euro']+list");
}
@Test // DATACASS-343
@Ignore("Missing operator")
public void shouldAppendAllToList() {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().addTo("list").appendAll("foo", "Euro"), personEntity);
assertThat(update.toString()).isEqualTo("UPDATE person SET list=list+['foo','Euro'];");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET list+=['foo','Euro']");
}
@Test // DATACASS-343
@@ -202,7 +305,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().remove("list", "Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET list=list-['Euro'];");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET list-=['Euro']");
}
@Test // DATACASS-343
@@ -211,16 +314,18 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().clear("list"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET list=[];");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET list=[]");
}
@Test // DATACASS-343
@Ignore("Missing operator")
public void shouldAddAllToSet() {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().addTo("set").appendAll("foo", "Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET set_col=set_col+{'foo','Euro'};");
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET set_col+={'foo','Euro'}");
}
@Test // DATACASS-343
@@ -229,7 +334,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().remove("set", "Euro"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET set_col=set_col-{'Euro'};");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET set_col-={'Euro'}");
}
@Test // DATACASS-343
@@ -238,7 +343,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().clear("set"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET set_col={};");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET set_col={}");
}
@Test // DATACASS-343
@@ -247,7 +352,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().increment("number"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET number=number+1;");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET number+=1");
}
@Test // DATACASS-343
@@ -256,7 +361,7 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory
.update(Query.empty(), Update.empty().decrement("number"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET number=number-1;");
assertThat(update.build(ParameterHandling.INLINE).getQuery()).isEqualTo("UPDATE person SET number-=1");
}
@Test // DATACASS-569
@@ -268,7 +373,104 @@ public class StatementFactoryUnitTests {
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
assertThat(update.build().toString()).isEqualTo("UPDATE person SET first_name='baz' WHERE foo='bar' IF EXISTS;");
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET first_name='baz' WHERE foo='bar' IF EXISTS");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateIfCondition() {
Query query = Query.query(Criteria.where("foo").is("bar"))
.queryOptions(UpdateOptions.builder().ifCondition(Criteria.where("foo").is("baz")).build());
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET first_name='baz' WHERE foo='bar' IF foo='baz'");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateFromObject() {
Person person = new Person();
person.id = "foo";
person.firstName = "bar";
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(person,
WriteOptions.empty());
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET first_name='bar', list=NULL, map=NULL, number=NULL, set_col=NULL WHERE id='foo'");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateFromObjectIfExists() {
UpdateOptions options = UpdateOptions.builder().withIfExists().build();
Person person = new Person();
person.id = "foo";
person.firstName = "bar";
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(person,
options);
assertThat(update.build(ParameterHandling.INLINE).getQuery()).endsWith("IF EXISTS");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateFromObjectIfCondition() {
UpdateOptions options = UpdateOptions.builder().ifCondition(Criteria.where("foo").is("bar")).build();
Person person = new Person();
person.id = "foo";
person.firstName = "bar";
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(person,
options);
assertThat(update.build(ParameterHandling.INLINE).getQuery()).endsWith("IF foo='bar'");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateFromObjectWithTtl() {
WriteOptions options = WriteOptions.builder().ttl(Duration.ofMinutes(1)).build();
Person person = new Person();
person.id = "foo";
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(person,
options);
assertThat(update.build(ParameterHandling.INLINE).getQuery()).startsWith("UPDATE person USING TTL 60 SET");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateFromObjectWithTimestamp() {
WriteOptions options = WriteOptions.builder().timestamp(1234).build();
Person person = new Person();
person.id = "foo";
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(person,
options);
assertThat(update.build(ParameterHandling.INLINE).getQuery()).startsWith("UPDATE person USING TIMESTAMP 1234 SET");
}
@Test // DATACASS-656
public void shouldCreateSetUpdateFromObjectWithEmptyCollections() {
Person person = new Person();
person.id = "foo";
person.set = Collections.emptySet();
person.list = Collections.emptyList();
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(person,
WriteOptions.empty());
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE person SET first_name=NULL, list=[], map=NULL, number=NULL, set_col={} WHERE id='foo'");
}
@Test // DATACASS-512
@@ -279,7 +481,8 @@ public class StatementFactoryUnitTests {
StatementBuilder<Select> count = statementFactory.count(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(count.build().toString()).isEqualTo("SELECT COUNT(1) FROM group WHERE foo='bar';");
assertThat(count.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("SELECT count(1) FROM group WHERE foo='bar'");
}
static class Person {

View File

@@ -70,6 +70,7 @@ import com.datastax.oss.driver.api.core.type.TupleType;
public class CassandraTypeMappingIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest {
static final Version VERSION_3_10 = Version.parse("3.10");
static boolean initialized = false;
CassandraOperations operations;
Version cassandraVersion;
@@ -83,9 +84,12 @@ public class CassandraTypeMappingIntegrationTests extends AbstractKeyspaceCreati
SchemaTestUtils.potentiallyCreateTableFor(AllPossibleTypes.class, operations);
SchemaTestUtils.potentiallyCreateTableFor(TimeEntity.class, operations);
operations.getCqlOperations().execute("DROP TABLE IF EXISTS ListOfTuples;");
operations.getCqlOperations()
.execute("CREATE TABLE ListOfTuples (id varchar PRIMARY KEY, tuples frozen<list<tuple<varchar, bigint>>>);");
if (!initialized) {
initialized = true;
operations.getCqlOperations().execute("DROP TABLE IF EXISTS ListOfTuples;");
operations.getCqlOperations()
.execute("CREATE TABLE ListOfTuples (id varchar PRIMARY KEY, tuples frozen<list<tuple<varchar, bigint>>>);");
}
SchemaTestUtils.truncate(AllPossibleTypes.class, operations);
SchemaTestUtils.truncate(TimeEntity.class, operations);
@@ -569,7 +573,7 @@ public class CassandraTypeMappingIntegrationTests extends AbstractKeyspaceCreati
ResultSet resultSet = session.execute("SELECT localTime FROM AllPossibleTypes WHERE id = '1'");
Row row = resultSet.one();
assertThat(row.getLocalTime(0).getNano()).isEqualTo(3_723_000_000_000L);
assertThat(row.getLocalTime(0)).isEqualTo(entity.getLocalTime());
}
@Test // DATACASS-694
@@ -644,6 +648,7 @@ public class CassandraTypeMappingIntegrationTests extends AbstractKeyspaceCreati
}
@Test // DATACASS-296
@Ignore("DATACASS-656 - Custom Conversions lookup order")
public void shouldReadAndWriteJodaDateTime() {
AllPossibleTypes entity = new AllPossibleTypes("1");
@@ -702,6 +707,7 @@ public class CassandraTypeMappingIntegrationTests extends AbstractKeyspaceCreati
}
@Test // DATACASS-296
@Ignore("DATACASS-656 - Custom Conversions lookup order")
public void shouldReadAndWriteBpInstant() {
AllPossibleTypes entity = new AllPossibleTypes("1");
@@ -712,7 +718,7 @@ public class CassandraTypeMappingIntegrationTests extends AbstractKeyspaceCreati
AllPossibleTypes loaded = load(entity);
assertThat(loaded.getBpZoneId()).isEqualTo(entity.getBpZoneId());
assertThat(loaded.getBpInstant()).isEqualTo(entity.getBpInstant());
}
@Test // DATACASS-296

View File

@@ -140,7 +140,7 @@ public class CustomConversionIntegrationTests extends AbstractKeyspaceCreatingIn
public void shouldLoadCustomConvertedObject() {
cassandraOperations.getCqlOperations().execute(
"INSERT INTO employee (id, person) VALUES('employee-id, '{\"firstname\":\"Homer\",\"lastname\":\"Simpson\"}");
"INSERT INTO employee (id, person) VALUES('employee-id', '{\"firstname\":\"Homer\",\"lastname\":\"Simpson\"}')");
Employee employee = cassandraOperations.selectOne("SELECT id, person FROM employee", Employee.class);
@@ -154,7 +154,7 @@ public class CustomConversionIntegrationTests extends AbstractKeyspaceCreatingIn
public void shouldLoadCustomConvertedWithCollectionsObject() {
cassandraOperations.getCqlOperations().execute(
"INSERT INTO employee (id, people) VALUES('employee-id, '[{\"firstname\":\"Apu\",\"lastname\":\"Nahasapeemapetilon\"}]");
"INSERT INTO employee (id, people) VALUES('employee-id', {'{\"firstname\":\"Apu\",\"lastname\":\"Nahasapeemapetilon\"}'})");
Employee employee = cassandraOperations.selectOne("SELECT id, people FROM employee", Employee.class);
@@ -174,7 +174,7 @@ public class CustomConversionIntegrationTests extends AbstractKeyspaceCreatingIn
cassandraOperations = new CassandraTemplate(session, converter);
cassandraOperations.getCqlOperations().execute(
"INSERT INTO employee (id, people) VALUES('employee-id, '[{\"firstname\":\"Apu\",\"lastname\":\"Nahasapeemapetilon\"}]");
"INSERT INTO employee (id, people) VALUES('employee-id', {'{\"firstname\":\"Apu\",\"lastname\":\"Nahasapeemapetilon\"}'})");
Employee employee = cassandraOperations.selectOne("SELECT id, people FROM employee", Employee.class);

View File

@@ -69,10 +69,8 @@ public class MappingCassandraConverterMappedTupleUnitTests {
TupleValue value = entity.getTupleType().newValue("hello", 1);
this.rowMock = RowMockUtil.newRowMock(
column("name", "Jon Doe", DataTypes.TEXT),
column("tuple", value, entity.getTupleType())
);
this.rowMock = RowMockUtil.newRowMock(column("name", "Jon Doe", DataTypes.TEXT),
column("tuple", value, entity.getTupleType()));
Person person = this.mappingCassandraConverter.read(Person.class, rowMock);
@@ -95,7 +93,8 @@ public class MappingCassandraConverterMappedTupleUnitTests {
this.mappingCassandraConverter.write(person, insert);
assertThat(insert.toString()).contains("VALUES ('Jon Doe',('hello',1))");
TupleValue tupleValue = (TupleValue) insert.get(CqlIdentifier.fromCql("tuple"));
assertThat(tupleValue.getFormattedContents()).contains("('hello',1)");
}
@Data

View File

@@ -247,7 +247,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
SimpleStatement statement = new StatementFactory(converter).insert(withUdtId, WriteOptions.empty()).build();
assertThat(statement.getQuery()).isEqualTo(
"INSERT INTO addressbook (id) " + "VALUES ({zip:'69469',city:'Weinheim',streetlines:['Heckenpfad','14']})");
"INSERT INTO withmappedudtid (id) " + "VALUES ({zip:'69469',city:'Weinheim',streetlines:['Heckenpfad','14']})");
}
@Test // DATACASS-172
@@ -255,6 +255,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
CassandraPersistentEntity<?> persistentEntity = converter.getMappingContext()
.getRequiredPersistentEntity(AddressUserType.class);
UdtValue udtValue = persistentEntity.getUserType().newValue();
udtValue.setString("zip", "69469");
udtValue.setString("city", "Weinheim");
@@ -266,7 +267,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
SimpleStatement statement = new StatementFactory(converter).insert(withUdtId, WriteOptions.empty()).build();
assertThat(statement.getQuery()).isEqualTo(
"INSERT INTO addressbook (id) " + "VALUES ({zip:'69469',city:'Weinheim',streetlines:['Heckenpfad','14']})");
"INSERT INTO withudtid (id) " + "VALUES ({zip:'69469',city:'Weinheim',streetlines:['Heckenpfad','14']})");
}
@Test // DATACASS-172
@@ -311,7 +312,9 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
Where where = new Where();
converter.write(money, where);
assertThat(where.toString()).isEqualTo("currency={currency:'EUR'}");
assertThat((UdtValue) where.get(CqlIdentifier.fromCql("currency"))) //
.extracting(UdtValue::getFormattedContents) //
.isEqualTo("{currency:'EUR'}");
}
@Test // DATACASS-172, DATACASS-400
@@ -321,7 +324,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
SimpleStatement statement = new StatementFactory(converter).update(money, WriteOptions.empty()).build();
assertThat(statement.getQuery()).isEqualTo("UPDATE money SET currency={currency:'EUR'} WHERE id='1'");
assertThat(statement.getQuery()).isEqualTo("UPDATE moneytransfer SET currency={currency:'EUR'} WHERE id='1'");
}
@Test // DATACASS-172, DATACASS-400

View File

@@ -115,8 +115,16 @@ public class MappingCassandraConverterUDTUnitTests {
mappingCassandraConverter.write(supplier, insert);
assertThat(insert.toString())
.contains("VALUES ({{name:'a good one',displayname:NULL}:[{currency:'EUR'},{currency:'USD'}]}");
Map<UdtValue, List<UdtValue>> acceptedcurrencies = (Map) insert.get(CqlIdentifier.fromCql("acceptedcurrencies"));
assertThat(acceptedcurrencies).hasSize(1);
Map.Entry<UdtValue, List<UdtValue>> entry = acceptedcurrencies.entrySet().iterator().next();
assertThat(entry.getKey().getFormattedContents()).contains("{name:'a good one',displayname:NULL}");
assertThat(entry.getValue()).hasSize(2) //
.extracting(UdtValue::getFormattedContents) //
.contains("{currency:'EUR'}", "{currency:'USD'}");
}
@UserDefinedType

View File

@@ -31,11 +31,13 @@ import java.net.UnknownHostException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.annotation.Id;
@@ -51,6 +53,7 @@ import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.core.mapping.Table;
import org.springframework.data.cassandra.domain.AllPossibleTypes;
import org.springframework.data.cassandra.domain.CompositeKey;
import org.springframework.data.cassandra.domain.TypeWithCompositeKey;
import org.springframework.data.cassandra.domain.TypeWithKeyClass;
@@ -99,6 +102,19 @@ public class MappingCassandraConverterUnitTests {
assertThat(getValues(insert)).contains("MINT");
}
@Test // DATACASS-260
public void shouldWriteEnumSet() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setSetOfEnum(Collections.singleton(CassandraTypeMappingIntegrationTests.Condition.MINT));
Map<CqlIdentifier, Object> insert = new LinkedHashMap<>();
mappingCassandraConverter.write(entity, insert);
assertThat(insert.get(CqlIdentifier.fromCql("setofenum"))).isInstanceOf(Set.class);
}
@Test // DATACASS-255
public void insertEnumMapsToOrdinal() {
@@ -290,13 +306,72 @@ public class MappingCassandraConverterUnitTests {
@Test // DATACASS-280, DATACASS-271
public void shouldReadTimestampCorrectly() {
Date date = new Date(1);
Instant instant = Instant.now();
rowMock = RowMockUtil.newRowMock(column("foo", date, DataTypes.TIMESTAMP));
rowMock = RowMockUtil.newRowMock(column("foo", instant, DataTypes.TIMESTAMP));
Date result = mappingCassandraConverter.readRow(Date.class, rowMock);
assertThat(result).isEqualTo(date);
assertThat(result).isEqualTo(Date.from(instant));
}
@Test // DATACASS-280, DATACASS-271
public void shouldReadInstantTimestampCorrectly() {
Instant instant = Instant.now();
rowMock = RowMockUtil.newRowMock(column("foo", instant, DataTypes.TIMESTAMP));
Instant result = mappingCassandraConverter.readRow(Instant.class, rowMock);
assertThat(result).isEqualTo(instant);
}
@Test // DATACASS-656
public void shouldReadAndWriteTimestampFromObject() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setInstant(Instant.now());
entity.setTimestamp(new Date(1));
Map<CqlIdentifier, Object> insert = new LinkedHashMap<>();
mappingCassandraConverter.write(entity, insert);
assertThat(insert.get(CqlIdentifier.fromCql("instant"))).isInstanceOf(Instant.class);
assertThat(insert.get(CqlIdentifier.fromCql("timestamp"))).isInstanceOf(Instant.class);
}
@Test // DATACASS-656
@Ignore("Fails because of reverse custom conversion registration order")
public void shouldReadAndWriteTimestampFromObjectWithConversion() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setInstant(Instant.now());
entity.setTimestamp(new Date(1));
entity.setJodaDateTime(new org.joda.time.DateTime(2010, 7, 4, 1, 2, 3));
entity.setBpInstant(org.threeten.bp.Instant.now());
Map<CqlIdentifier, Object> insert = new LinkedHashMap<>();
mappingCassandraConverter.write(entity, insert);
assertThat(insert.get(CqlIdentifier.fromCql("jodadatetime"))).isInstanceOf(Instant.class);
assertThat(insert.get(CqlIdentifier.fromCql("bpinstant"))).isInstanceOf(Instant.class);
}
@Test // DATACASS-656
public void shouldReadAndWriteTimeFromObjectWithConversion() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setJodaLocalTime(org.joda.time.LocalTime.fromMillisOfDay(50000));
Map<CqlIdentifier, Object> insert = new LinkedHashMap<>();
mappingCassandraConverter.write(entity, insert);
assertThat(insert.get(CqlIdentifier.fromCql("jodalocaltime"))).isInstanceOf(LocalTime.class);
}
@Test // DATACASS-271

View File

@@ -26,6 +26,7 @@ import java.util.Collections;
import java.util.Currency;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.joda.time.LocalDate;
@@ -188,10 +189,11 @@ public class QueryMapperUnitTests {
Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity);
CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next();
CriteriaDefinition.Predicate predicate = mappedCriteriaDefinition.getPredicate();
assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.EQ);
assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(UdtValue.class);
assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("{street:'21 Jump-Street'}");
assertThat(predicate.getOperator()).isEqualTo(Operators.EQ);
assertThat(predicate.getValue()).isInstanceOf(UdtValue.class);
assertThat(predicate.as(UdtValue.class::cast).getFormattedContents()).isEqualTo("{street:'21 Jump-Street'}");
}
@Test // DATACASS-343
@@ -203,9 +205,12 @@ public class QueryMapperUnitTests {
CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next();
assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.IN);
assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(Collection.class);
assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("[{street:'21 Jump-Street'}]");
CriteriaDefinition.Predicate predicate = mappedCriteriaDefinition.getPredicate();
assertThat(predicate.getOperator()).isEqualTo(Operators.IN);
assertThat(predicate.getValue()).isInstanceOf(Collection.class);
assertThat((List<UdtValue>) predicate.getValue()).extracting(UdtValue::getFormattedContents)
.contains("{street:'21 Jump-Street'}");
}
@Test // DATACASS-343
@@ -216,10 +221,12 @@ public class QueryMapperUnitTests {
Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity);
CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next();
CriteriaDefinition.Predicate predicate = mappedCriteriaDefinition.getPredicate();
assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.IN);
assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(Collection.class);
assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("[{street:'21 Jump-Street'}]");
assertThat(predicate.getOperator()).isEqualTo(Operators.IN);
assertThat(predicate.getValue()).isInstanceOf(Collection.class);
assertThat((List<UdtValue>) predicate.getValue()).extracting(UdtValue::getFormattedContents)
.contains("{street:'21 Jump-Street'}");
}
@Test // DATACASS-487
@@ -233,7 +240,8 @@ public class QueryMapperUnitTests {
assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.CONTAINS_KEY);
assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(UdtValue.class);
assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("{street:'21 Jump-Street'}");
assertThat(((UdtValue) mappedCriteriaDefinition.getPredicate().getValue()).getFormattedContents())
.isEqualTo("{street:'21 Jump-Street'}");
}
@Test // DATACASS-487
@@ -247,7 +255,8 @@ public class QueryMapperUnitTests {
assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.CONTAINS);
assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(UdtValue.class);
assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("{street:'21 Jump-Street'}");
assertThat(((UdtValue) mappedCriteriaDefinition.getPredicate().getValue()).getFormattedContents())
.isEqualTo("{street:'21 Jump-Street'}");
}
@Test // DATACASS-343
@@ -354,12 +363,13 @@ public class QueryMapperUnitTests {
@Test // DATACASS-302
public void shouldMapTime() {
Filter filter = Filter.from(Criteria.where("localDate").gt(LocalTime.fromMillisOfDay(1000)));
Filter filter = Filter.from(Criteria.where("localTime").gt(LocalTime.fromMillisOfDay(1000)));
Filter mappedObject = this.queryMapper.getMappedObject(filter,
this.mappingContext.getRequiredPersistentEntity(Person.class));
assertThat(mappedObject).contains(Criteria.where("localdate").gt(1000L));
assertThat(mappedObject)
.contains(Criteria.where("localtime").gt(java.time.LocalTime.ofNanoOfDay(TimeUnit.MILLISECONDS.toNanos(1000))));
}
@Test // DATACASS-523
@@ -382,6 +392,7 @@ public class QueryMapperUnitTests {
Integer number;
LocalDate localDate;
LocalTime localTime;
MappedTuple tuple;

View File

@@ -110,7 +110,7 @@ public class UpdateMapperUnitTests {
Update update = updateMapper.getMappedObject(Update.empty().set("manufacturers", map), persistentEntity);
assertThat(update.getUpdateOperations()).hasSize(1);
assertThat(update.toString()).isEqualTo("manufacturers = {{name:'foobar'}:'Euro'}");
assertThat(update.toString()).isEqualTo("manufacturers = { {name:'foobar'} : 'Euro' }");
}
@Test // DATACASS-343
@@ -161,7 +161,7 @@ public class UpdateMapperUnitTests {
persistentEntity);
assertThat(update.getUpdateOperations()).hasSize(1);
assertThat(update.toString()).isEqualTo("manufacturers = manufacturers + {{name:'foobar'}:'Euro'}");
assertThat(update.toString()).isEqualTo("manufacturers = manufacturers + { {name:'foobar'} : 'Euro' }");
}
@Test // DATACASS-343
@@ -246,7 +246,7 @@ public class UpdateMapperUnitTests {
this.persistentEntity);
assertThat(update.getUpdateOperations()).hasSize(1);
assertThat(update.toString()).isEqualTo("localtime = 3723000000000");
assertThat(update.toString()).startsWith("localtime = '01:02:03.");
}
@Test // DATACASS-523

View File

@@ -16,7 +16,6 @@
package org.springframework.data.cassandra.core.cql;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Constructor;
@@ -33,12 +32,12 @@ import org.springframework.data.cassandra.*;
import org.springframework.util.ClassUtils;
import com.datastax.oss.driver.api.core.DefaultConsistencyLevel;
import com.datastax.oss.driver.api.core.DriverException;
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
import com.datastax.oss.driver.api.core.ProtocolVersion;
import com.datastax.oss.driver.api.core.UnsupportedProtocolVersionException;
import com.datastax.oss.driver.api.core.auth.AuthenticationException;
import com.datastax.oss.driver.api.core.connection.BusyConnectionException;
import com.datastax.oss.driver.api.core.connection.FrameTooLongException;
import com.datastax.oss.driver.api.core.metadata.EndPoint;
import com.datastax.oss.driver.api.core.metadata.Node;
import com.datastax.oss.driver.api.core.servererrors.*;
@@ -66,7 +65,7 @@ public class CassandraExceptionTranslatorUnitTests {
DataAccessException result = sut.translateExceptionIfPossible(new AuthenticationException(endPoint, "message"));
assertThat(result).isInstanceOf(CassandraAuthenticationException.class)
.hasMessageStartingWith("Authentication error on host").hasCauseInstanceOf(AuthenticationException.class);
.hasMessageStartingWith("Authentication error").hasCauseInstanceOf(AuthenticationException.class);
}
@Test // DATACASS-402
@@ -74,8 +73,8 @@ public class CassandraExceptionTranslatorUnitTests {
DataAccessException result = sut.translateExceptionIfPossible(new NoNodeAvailableException());
assertThat(result).isInstanceOf(CassandraConnectionFailureException.class)
.hasMessageStartingWith("All host(s) tried").hasCauseInstanceOf(NoNodeAvailableException.class);
assertThat(result).isInstanceOf(CassandraConnectionFailureException.class).hasMessageStartingWith("No node was")
.hasCauseInstanceOf(NoNodeAvailableException.class);
}
@Test // DATACASS-402
@@ -142,7 +141,7 @@ public class CassandraExceptionTranslatorUnitTests {
DataAccessException result = sut.translateExceptionIfPossible(new BootstrappingException(node));
assertThat(result).isInstanceOf(TransientDataAccessResourceException.class).hasMessageStartingWith("Queried host")
assertThat(result).isInstanceOf(TransientDataAccessResourceException.class).hasMessageContaining("bootstrapping")
.hasCauseInstanceOf(BootstrappingException.class);
}
@@ -151,7 +150,7 @@ public class CassandraExceptionTranslatorUnitTests {
DataAccessException result = sut.translateExceptionIfPossible(new OverloadedException(node));
assertThat(result).isInstanceOf(TransientDataAccessResourceException.class).hasMessageStartingWith("Queried host")
assertThat(result).isInstanceOf(TransientDataAccessResourceException.class)
.hasCauseInstanceOf(OverloadedException.class);
}
@@ -209,23 +208,17 @@ public class CassandraExceptionTranslatorUnitTests {
DataAccessException result = sut.translateExceptionIfPossible(new BusyConnectionException(2));
assertThat(result).isInstanceOf(CassandraConnectionFailureException.class)
.hasMessageContaining("Connection has run out of stream").hasCauseInstanceOf(BusyConnectionException.class);
assertThat(result).isInstanceOf(CassandraConnectionFailureException.class).hasMessageContaining("simultaneous")
.hasCauseInstanceOf(BusyConnectionException.class);
}
@Test // DATACASS-402
@SuppressWarnings("unchecked")
public void shouldTranslateFrameTooLongException() throws Exception {
public void shouldTranslateFrameTooLongException() {
assumeTrue(
ClassUtils.isPresent("com.datastax.driver.core.exceptions.FrameTooLongException", getClass().getClassLoader()));
DataAccessException result = sut.translateExceptionIfPossible(new FrameTooLongException(socketAddress, "foo"));
DriverException exception = createInstance("com.datastax.driver.core.exceptions.FrameTooLongException",
new Class[] { Integer.TYPE }, 5);
DataAccessException result = sut.translateExceptionIfPossible(exception);
assertThat(result).isInstanceOf(CassandraUncategorizedException.class).hasCauseInstanceOf(exception.getClass());
assertThat(result).isInstanceOf(CassandraUncategorizedException.class)
.hasCauseInstanceOf(FrameTooLongException.class);
}
@Test // DATACASS-402
@@ -245,8 +238,8 @@ public class CassandraExceptionTranslatorUnitTests {
InvalidConfigurationInQueryException cx = new InvalidConfigurationInQueryException(node, "err");
DataAccessException dax = sut.translate("Query", "SELECT * FROM person", cx);
assertThat(dax).hasRootCauseInstanceOf(InvalidQueryException.class).hasMessage(
"Query; CQL [SELECT * FROM person]; err; nested exception is com.datastax.driver.core.exceptions.InvalidConfigurationInQueryException: err");
assertThat(dax).hasRootCauseInstanceOf(InvalidConfigurationInQueryException.class).hasMessage(
"Query; CQL [SELECT * FROM person]; err; nested exception is com.datastax.oss.driver.api.core.servererrors.InvalidConfigurationInQueryException: err");
}
@SuppressWarnings("unchecked")

View File

@@ -513,7 +513,7 @@ public class CqlTemplateUnitTests {
when(session.execute(boundStatement)).thenReturn(resultSet);
when(resultSet.iterator()).thenAnswer(it -> Collections.singleton(row).iterator());
when(resultSet.spliterator()).thenCallRealMethod();
when(resultSet.spliterator()).thenAnswer(it -> Collections.singleton(row).spliterator());
ResultSet resultSet = template.query(session -> preparedStatement, ps -> {
ps.bind("a", "b");

View File

@@ -37,7 +37,7 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatement;
@RunWith(MockitoJUnitRunner.class)
public class QueryOptionsUtilUnitTests {
@Mock(stubOnly = true) SimpleStatement simpleStatement;
@Mock SimpleStatement simpleStatement;
@Test // DATACASS-202
public void addPreparedStatementOptionsShouldAddDriverQueryOptions() {
@@ -64,6 +64,10 @@ public class QueryOptionsUtilUnitTests {
@Test // DATACASS-202
public void addStatementQueryOptionsShouldAddGenericQueryOptions() {
when(simpleStatement.setPageSize(anyInt())).thenReturn(simpleStatement);
when(simpleStatement.setTimeout(any())).thenReturn(simpleStatement);
when(simpleStatement.setTracing(anyBoolean())).thenReturn(simpleStatement);
QueryOptions queryOptions = QueryOptions.builder() //
.pageSize(10) //
.readTimeout(1, TimeUnit.MINUTES) //

View File

@@ -123,6 +123,7 @@ public class SingleColumnRowMapperUnitTests {
public void mapRowSingleColumnWrongType() {
when(columnDefinitions.size()).thenReturn(1);
when(columnDefinitions.get(0)).thenReturn(columnDefinition);
when(row.getObject(0)).thenReturn("hello");

View File

@@ -132,7 +132,7 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea
execute(spec);
assertThat(getTableMetadata("addamsfamily").getColumn("gender")).isNull();
assertThat(getTableMetadata("addamsfamily").getColumn("gender")).isEmpty();
}
@Test // DATACASS-192
@@ -144,8 +144,8 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea
execute(spec);
assertThat(getTableMetadata("addamsfamily").getColumn("name")).isNull();
assertThat(getTableMetadata("addamsfamily").getColumn("newname")).isNotNull();
assertThat(getTableMetadata("addamsfamily").getColumn("name")).isEmpty();
assertThat(getTableMetadata("addamsfamily").getColumn("newname")).isPresent();
}
@Test // DATACASS-192
@@ -161,10 +161,8 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea
execute(spec);
/**
* TODO assertThat(getTableMetadata("users").getOptions().getCaching().get("keys")).isEqualTo("NONE");
* assertThat(getTableMetadata("users").getOptions().getCaching().get("rows_per_partition")).isEqualTo("15");
*/
assertThat(getTableMetadata("users").getOptions().toString())
.contains("caching={keys=NONE, rows_per_partition=15}");
}
private void execute(AlterTableSpecification spec) {
@@ -173,7 +171,7 @@ public class AlterTableCqlGeneratorIntegrationTests extends AbstractKeyspaceCrea
private TableMetadata getTableMetadata(String table) {
KeyspaceMetadata keyspace = session.getMetadata().getKeyspace(session.getKeyspace().get()).get();
KeyspaceMetadata keyspace = session.refreshSchema().getKeyspace(session.getKeyspace().get()).get();
return keyspace.getTable(table).get();
}
}

View File

@@ -61,7 +61,7 @@ public class AlterTableCqlGeneratorUnitTests {
AlterTableSpecification spec = AlterTableSpecification.alterTable("addamsFamily").add("gravesite", DataTypes.TEXT);
assertThat(toCql(spec)).isEqualTo("ALTER TABLE addamsfamily ADD gravesite varchar;");
assertThat(toCql(spec)).isEqualTo("ALTER TABLE addamsfamily ADD gravesite text;");
}
@Test // DATACASS-192

View File

@@ -90,7 +90,7 @@ public class AlterUserTypeCqlGeneratorIntegrationTests extends AbstractKeyspaceC
@Test // DATACASS-172
public void generationFailsIfNameIsNotSet() {
assertThatIllegalArgumentException().isThrownBy(() -> toCql(AlterUserTypeSpecification.alterType(null)));
assertThatNullPointerException().isThrownBy(() -> toCql(AlterUserTypeSpecification.alterType(null)));
}
@Test // DATACASS-172

View File

@@ -37,7 +37,7 @@ public class AlterUserTypeCqlGeneratorUnitTests {
AlterUserTypeSpecification spec = AlterUserTypeSpecification.alterType("address") //
.add("zip", DataTypes.TEXT);
assertThat(toCql(spec)).isEqualTo("ALTER TYPE address ADD zip varchar;");
assertThat(toCql(spec)).isEqualTo("ALTER TYPE address ADD zip text;");
}
@Test // DATACASS-172
@@ -46,7 +46,7 @@ public class AlterUserTypeCqlGeneratorUnitTests {
AlterUserTypeSpecification spec = AlterUserTypeSpecification.alterType("address") //
.alter("zip", DataTypes.TEXT);
assertThat(toCql(spec)).isEqualTo("ALTER TYPE address ALTER zip TYPE varchar;");
assertThat(toCql(spec)).isEqualTo("ALTER TYPE address ALTER zip TYPE text;");
}
@Test // DATACASS-172

View File

@@ -59,7 +59,7 @@ public class CreateTableCqlGeneratorUnitTests {
String cql = toCql(table);
assertPreamble(name, cql);
assertColumns(String.format("%s %s, %s %s", partitionKey0, partitionKeyType0, column1, columnType1), cql);
assertColumns("partitionkey0 text, column1 text", cql);
assertPrimaryKey(partitionKey0.toString(), cql);
}
@@ -81,9 +81,7 @@ public class CreateTableCqlGeneratorUnitTests {
String cql = toCql(table);
assertPreamble(name, cql);
assertColumns(
String.format("%s %s, %s %s, %s %s", partKey0, partKeyType0, partKey1, partKeyType1, column0, columnType0),
cql);
assertColumns("partkey0 text, partkey1 text, column0 text", cql);
assertPrimaryKey(String.format("(%s, %s)", partKey0, partKey1), cql);
}
@@ -106,8 +104,7 @@ public class CreateTableCqlGeneratorUnitTests {
String cql = toCql(table);
assertPreamble(name, cql);
assertColumns(String.format("%s %s, %s %s, %s %s", partitionKey0, partitionKeyType0, partitionKey1,
partitionKeyType1, column1, columnType1), cql);
assertColumns("partitionkey0 text, create_timestamp timestamp, column1 text", cql);
assertPrimaryKey(String.format("(%s, %s)", partitionKey0, partitionKey1), cql);
assertDoubleOption(TableOption.READ_REPAIR_CHANCE.getName(), readRepairChance, cql);
}
@@ -155,8 +152,7 @@ public class CreateTableCqlGeneratorUnitTests {
String cql = toCql(table);
assertPreamble(name, cql);
assertColumns(String.format("%s %s, %s %s, %s %s", partitionKey0, partitionKeyType0, partitionKey1,
partitionKeyType1, column1, columnType1), cql);
assertColumns("tid timeuuid, create_timestamp timestamp, data_point text", cql);
assertPrimaryKey(String.format("(%s, %s)", partitionKey0, partitionKey1), cql);
assertNullOption(TableOption.COMPACT_STORAGE.getName(), cql);
assertDoubleOption(TableOption.READ_REPAIR_CHANCE.getName(), readRepairChance, cql);
@@ -196,7 +192,7 @@ public class CreateTableCqlGeneratorUnitTests {
* Asserts that the preamble is first & correctly formatted in the given CQL string.
*/
private static void assertPreamble(CqlIdentifier tableName, String cql) {
assertThat(cql.startsWith("CREATE TABLE " + tableName + " ")).isTrue();
assertThat(cql).startsWith("CREATE TABLE " + tableName + " ");
}
/**
@@ -205,7 +201,7 @@ public class CreateTableCqlGeneratorUnitTests {
* @param primaryKeyString IE, "foo", "foo, bar, baz", "(foo, bar), baz", etc
*/
private static void assertPrimaryKey(String primaryKeyString, String cql) {
assertThat(cql.contains(", PRIMARY KEY (" + primaryKeyString + "))")).isTrue();
assertThat(cql).contains(", PRIMARY KEY (" + primaryKeyString + "))");
}
/**
@@ -214,31 +210,31 @@ public class CreateTableCqlGeneratorUnitTests {
* @param columnSpec IE, "foo text, bar blob"
*/
private static void assertColumns(String columnSpec, String cql) {
assertThat(cql.contains("(" + columnSpec + ",")).isTrue();
assertThat(cql).contains("(" + columnSpec + ",");
}
/**
* Asserts that the read repair change is set properly
*/
private static void assertStringOption(String name, String value, String cql) {
assertThat(cql.contains(name + " = '" + value + "'")).isTrue();
assertThat(cql).contains(name + " = '" + value + "'");
}
/**
* Asserts that the option is set
*/
private static void assertDoubleOption(String name, Double value, String cql) {
assertThat(cql.contains(name + " = " + value)).isTrue();
assertThat(cql).contains(name + " = " + value);
}
private static void assertLongOption(String name, Long value, String cql) {
assertThat(cql.contains(name + " = " + value)).isTrue();
assertThat(cql).contains(name + " = " + value);
}
/**
* Asserts that the read repair change is set properly
*/
private static void assertNullOption(String name, String cql) {
assertThat(cql.contains(" " + name + " ")).isTrue();
assertThat(cql).contains(" " + name + " ");
}
}

View File

@@ -38,7 +38,7 @@ public class CreateUserTypeCqlGeneratorUnitTests {
.createType("address") //
.field("city", DataTypes.TEXT);
assertThat(toCql(spec)).isEqualTo("CREATE TYPE address (city varchar);");
assertThat(toCql(spec)).isEqualTo("CREATE TYPE address (city text);");
}
@Test // DATACASS-172
@@ -49,7 +49,7 @@ public class CreateUserTypeCqlGeneratorUnitTests {
.field("zip", DataTypes.ASCII) //
.field("city", DataTypes.TEXT);
assertThat(toCql(spec)).isEqualTo("CREATE TYPE address (zip ascii, city varchar);");
assertThat(toCql(spec)).isEqualTo("CREATE TYPE address (zip ascii, city text);");
}
@Test // DATACASS-172
@@ -59,7 +59,7 @@ public class CreateUserTypeCqlGeneratorUnitTests {
.createType("address").ifNotExists().field("zip", DataTypes.ASCII) //
.field("city", DataTypes.TEXT);
assertThat(toCql(spec)).isEqualTo("CREATE TYPE IF NOT EXISTS address (zip ascii, city varchar);");
assertThat(toCql(spec)).isEqualTo("CREATE TYPE IF NOT EXISTS address (zip ascii, city text);");
}
@Test // DATACASS-172

View File

@@ -52,8 +52,9 @@ public class CachedPreparedStatementCreatorUnitTests {
@Before
public void before() {
when(session.getKeyspace()).thenReturn(Optional.of(CqlIdentifier.fromCql("keyspace")));
when(otherSession.getKeyspace()).thenReturn(Optional.of(CqlIdentifier.fromCql("other")));
when(session.getKeyspace()).thenReturn(Optional.of(CqlIdentifier.fromCql("mykeyspace")));
when(otherSession.getKeyspace()).thenReturn(Optional.of(CqlIdentifier.fromCql("mykeyspace")));
when(otherKeyspaceSession.getKeyspace()).thenReturn(Optional.of(CqlIdentifier.fromCql("other")));
when(session.prepare(any(SimpleStatement.class))).thenReturn(preparedStatement);
}

View File

@@ -87,7 +87,7 @@ public class BasicCassandraPersistentPropertyUnitTests {
CassandraPersistentProperty persistentProperty = getPropertyFor(TypeWithComposedPrimaryKeyAnnotation.class,
"column");
assertThat(persistentProperty.getRequiredColumnName()).isEqualTo(CqlIdentifier.fromCql("primary-key"));
assertThat(persistentProperty.getRequiredColumnName()).isEqualTo(CqlIdentifier.fromInternal("primary-key"));
assertThat(persistentProperty.isIdProperty()).isTrue();
}

View File

@@ -101,7 +101,7 @@ public class CassandraMappingContextUnitTests {
assertThat(idProperty).satisfies(actual -> {
assertThat(actual.getColumnName().toString()).isEqualTo("foo");
assertThat(actual.getColumnName()).hasToString("foo");
});
}

View File

@@ -56,7 +56,6 @@ public class CassandraPersistentEntityOrderPropertiesUnitTests {
entity.doWithProperties((PropertyHandler<CassandraPersistentProperty>) actual::add);
assertThat(actual).isEqualTo(expected);
}
@Test

View File

@@ -56,7 +56,6 @@ public class CassandraUserTypePersistentEntityUnitTests {
CassandraUserTypePersistentEntity<MappedUdt> type = getEntity(MappedUdt.class);
assertThat(type.getTableName()).isEqualTo(CqlIdentifier.fromCql("mappedudt"));
assertThat(type.getTableName()).isEqualTo(CqlIdentifier.fromCql("Mappedudt"));
}
@Test // DATACASS-172
@@ -65,7 +64,6 @@ public class CassandraUserTypePersistentEntityUnitTests {
CassandraUserTypePersistentEntity<WithName> type = getEntity(WithName.class);
assertThat(type.getTableName()).isEqualTo(CqlIdentifier.fromCql("withname"));
assertThat(type.getTableName()).isEqualTo(CqlIdentifier.fromCql("Withname"));
}
@Test // DATACASS-172
@@ -73,8 +71,7 @@ public class CassandraUserTypePersistentEntityUnitTests {
CassandraUserTypePersistentEntity<WithForceQuote> type = getEntity(WithForceQuote.class);
assertThat(type.getTableName()).isNotEqualTo(CqlIdentifier.fromCql("upperCase"));
assertThat(type.getTableName()).isEqualTo(CqlIdentifier.fromCql("UpperCase"));
assertThat(type.getTableName()).isEqualTo(CqlIdentifier.fromInternal("UpperCase"));
}
@Test // DATACASS-259

View File

@@ -62,7 +62,7 @@ public class CreateTableSpecificationBasicCassandraMappingContextUnitTests {
private CassandraMappingContext ctx = new CassandraMappingContext();
@Before
public void setUp() throws Exception {
public void setUp() {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new PersonReadConverter());
@@ -248,21 +248,21 @@ public class CreateTableSpecificationBasicCassandraMappingContextUnitTests {
@Test // DATACASS-172
public void columnsShouldMapToUdt() {
UserDefinedType human_udt = mock(UserDefinedType.class, "human_udt");
UserDefinedType species_udt = mock(UserDefinedType.class, "species_udt");
UserDefinedType peeps_udt = mock(UserDefinedType.class, "peeps_udt");
UserDefinedType human_udt = new CassandraMappingContext.ShallowUserDefinedType("human_udt", false);
UserDefinedType species_udt = new CassandraMappingContext.ShallowUserDefinedType("species_udt", false);
UserDefinedType peeps_udt = new CassandraMappingContext.ShallowUserDefinedType("peeps_udt", false);
ctx.setUserTypeResolver(typeName -> {
if (typeName.toString().equals(human_udt.toString())) {
if (typeName.equals(human_udt.getName())) {
return human_udt;
}
if (typeName.toString().equals(species_udt.toString())) {
if (typeName.equals(species_udt.getName())) {
return species_udt;
}
if (typeName.toString().equals(peeps_udt.toString())) {
if (typeName.equals(peeps_udt.getName())) {
return peeps_udt;
}
return null;
@@ -270,19 +270,19 @@ public class CreateTableSpecificationBasicCassandraMappingContextUnitTests {
CreateTableSpecification specification = getCreateTableSpecificationFor(WithUdtFields.class);
assertThat(getColumnType("human", specification)).isEqualTo(human_udt);
assertThat(getColumnType("friends", specification)).isEqualTo(DataTypes.listOf(species_udt));
assertThat(getColumnType("people", specification)).isEqualTo(DataTypes.setOf(peeps_udt));
assertThat(getColumnType("human", specification).asCql(false, true)).isEqualTo("human_udt");
assertThat(getColumnType("friends", specification).asCql(false, true)).isEqualTo("list<species_udt>");
assertThat(getColumnType("people", specification).asCql(false, true)).isEqualTo("set<peeps_udt>");
}
@Test // DATACASS-172
public void columnsShouldMapToMappedUserType() {
UserDefinedType mappedUdt = mock(UserDefinedType.class, "mappedudt");
UserDefinedType mappedUdt = new CassandraMappingContext.ShallowUserDefinedType("mappedudt", true);
ctx.setUserTypeResolver(typeName -> {
if (typeName.toString().equals(mappedUdt.toString())) {
if (typeName.equals(mappedUdt.getName())) {
return mappedUdt;
}
return null;
@@ -303,8 +303,11 @@ public class CreateTableSpecificationBasicCassandraMappingContextUnitTests {
UserDefinedType mappedUdt = mock(UserDefinedType.class, "mappedudt");
UserDefinedType human_udt = mock(UserDefinedType.class, "human_udt");
when(mappedUdt.toString()).thenReturn("mappedudt");
when(human_udt.toString()).thenReturn("human_udt");
when(human_udt.copy(true)).thenReturn(human_udt);
when(mappedUdt.copy(true)).thenReturn(mappedUdt);
when(mappedUdt.asCql(anyBoolean(), anyBoolean())).thenReturn("mappedudt");
when(human_udt.asCql(anyBoolean(), anyBoolean())).thenReturn("human_udt");
ctx.setUserTypeResolver(typeName -> {

View File

@@ -48,7 +48,7 @@ public class ForceQuotedEntitiesSimpleUnitTests {
BasicCassandraPersistentEntity<ExplicitTableNameForceQuoted> entity = new BasicCassandraPersistentEntity<>(
ClassTypeInformation.from(ExplicitTableNameForceQuoted.class));
assertThat(entity.getTableName().asCql(false)).isEqualTo("\"" + EXPLICIT_TABLE_NAME + "\"");
assertThat(entity.getTableName().asCql(true)).isEqualTo("\"" + EXPLICIT_TABLE_NAME + "\"");
assertThat(entity.getTableName().asInternal()).isEqualTo(EXPLICIT_TABLE_NAME);
}
@@ -60,7 +60,7 @@ public class ForceQuotedEntitiesSimpleUnitTests {
BasicCassandraPersistentEntity<DefaultTableNameForceQuoted> entity = new BasicCassandraPersistentEntity<>(
ClassTypeInformation.from(DefaultTableNameForceQuoted.class));
assertThat(entity.getTableName().asCql(false))
assertThat(entity.getTableName().asCql(true))
.isEqualTo(DefaultTableNameForceQuoted.class.getSimpleName().toLowerCase());
assertThat(entity.getTableName().asInternal())
.isEqualTo(DefaultTableNameForceQuoted.class.getSimpleName().toLowerCase());

View File

@@ -171,8 +171,7 @@ public class ForceQuotedPropertiesSimpleUnitTests {
CassandraPersistentProperty stringOne = key.getRequiredPersistentProperty("stringOne");
assertThat(stringZero.getColumnName()) //
.isEqualTo(CqlIdentifier.fromCql("TheFirstKeyField")) //
.isNotEqualTo(CqlIdentifier.fromCql("TheFirstKeyField"));
.isEqualTo(CqlIdentifier.fromInternal("TheFirstKeyField"));
assertThat(stringZero.getColumnName().asCql(false)).isEqualTo("\"" + EXPLICIT_KEY_0 + "\"");
assertThat(stringOne.getColumnName().asCql(false)).isEqualTo("\"" + EXPLICIT_KEY_1 + "\"");

View File

@@ -70,8 +70,8 @@ public class IndexCreationIntegrationTests extends AbstractKeyspaceCreatingInteg
TableMetadata metadata = getMetadata(createTable.getName());
assertThat(metadata.getIndexes().get("firstname_index")).isNotNull();
assertThat(metadata.getIndexes().get("withsecondaryindex_map_idx")).isNotNull();
assertThat(metadata.getIndexes().get(CqlIdentifier.fromCql("firstname_index"))).isNotNull();
assertThat(metadata.getIndexes().get(CqlIdentifier.fromCql("withsecondaryindex_map_idx"))).isNotNull();
}
@Test
@@ -88,11 +88,11 @@ public class IndexCreationIntegrationTests extends AbstractKeyspaceCreatingInteg
TableMetadata metadata = getMetadata(createTable.getName());
assertThat(metadata.getIndexes().get("withsasiindex_firstname_idx")).isNotNull();
assertThat(metadata.getIndexes().get(CqlIdentifier.fromCql("withsasiindex_firstname_idx"))).isNotNull();
}
private TableMetadata getMetadata(CqlIdentifier tableName) {
return session.getMetadata().getKeyspace(session.getKeyspace().get()).flatMap(it -> it.getTable(tableName)).get();
return session.refreshSchema().getKeyspace(session.getKeyspace().get()).flatMap(it -> it.getTable(tableName)).get();
}
static class WithSecondaryIndex {

View File

@@ -50,7 +50,7 @@ public class ColumnNameUnitTests {
ColumnName first = ColumnName.from(CqlIdentifier.fromCql("foo"));
ColumnName second = ColumnName.from(CqlIdentifier.fromCql("Foo"));
ColumnName different = ColumnName.from(CqlIdentifier.fromCql("Foo"));
ColumnName different = ColumnName.from(CqlIdentifier.fromInternal("bar"));
assertThat(first).isEqualTo(second);
assertThat(first.equals(second)).isTrue();

View File

@@ -55,9 +55,9 @@ public class ColumnsUnitTests {
@Test // DATACASS-343
public void shouldCreateFromCqlIdentifiers() {
Columns columns = Columns.from(CqlIdentifier.fromCql("Foo"), CqlIdentifier.fromCql("bar"));
Columns columns = Columns.from(CqlIdentifier.fromInternal("Foo"), CqlIdentifier.fromInternal("bar"));
assertThat(columns.toString()).contains("\"Foo\"").contains("bar");
assertThat(columns.toString()).contains("Foo").contains("bar");
}
@Test // DATACASS-343

View File

@@ -84,6 +84,6 @@ public class QueryUnitTests {
assertThat(query.getSort()).isEqualTo(Sort.by(asc("foo")));
assertThat(query.getPagingState()).contains(pagingState);
assertThat(query.getQueryOptions())
.hasValueSatisfying(actual -> assertThat(actual).extracting("fetchSize").isEqualTo(42));
.hasValueSatisfying(actual -> assertThat(actual).extracting("pageSize").isEqualTo(42));
}
}

View File

@@ -38,8 +38,8 @@ import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.domain.User;
import org.springframework.data.cassandra.repository.config.EnableReactiveCassandraRepositories;
import org.springframework.data.cassandra.repository.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.repository.support.IntegrationTestConfig;
import org.springframework.data.cassandra.test.util.AbstractKeyspaceCreatingIntegrationTest;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.data.repository.reactive.RxJava2CrudRepository;
import org.springframework.stereotype.Repository;
@@ -58,7 +58,7 @@ import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConvertingReactiveCassandraRepositoryTests.Config.class)
public class ConvertingReactiveCassandraRepositoryTests extends AbstractKeyspaceCreatingIntegrationTest {
public class ConvertingReactiveCassandraRepositoryTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@EnableReactiveCassandraRepositories(includeFilters = @Filter(value = Repository.class),
considerNestedRepositories = true)

View File

@@ -40,10 +40,10 @@ import org.springframework.data.cassandra.core.query.CassandraPageRequest;
import org.springframework.data.cassandra.domain.Group;
import org.springframework.data.cassandra.domain.GroupKey;
import org.springframework.data.cassandra.domain.User;
import org.springframework.data.cassandra.repository.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.repository.support.IntegrationTestConfig;
import org.springframework.data.cassandra.repository.support.ReactiveCassandraRepositoryFactory;
import org.springframework.data.cassandra.repository.support.SimpleReactiveCassandraRepository;
import org.springframework.data.cassandra.test.util.AbstractKeyspaceCreatingIntegrationTest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
@@ -63,7 +63,7 @@ import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ReactiveCassandraRepositoryIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest
public class ReactiveCassandraRepositoryIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest
implements BeanClassLoaderAware, BeanFactoryAware {
@Configuration
@@ -102,7 +102,7 @@ public class ReactiveCassandraRepositoryIntegrationTests extends AbstractKeyspac
TableMetadata users = session.getKeyspace().flatMap(it -> session.getMetadata().getKeyspace(it))
.flatMap(it -> it.getTable(CqlIdentifier.fromCql("users"))).get();
if (users.getIndexes().containsKey(CqlIdentifier.fromCql("IX_lastname"))) {
if (!users.getIndexes().containsKey(CqlIdentifier.fromCql("IX_lastname"))) {
session.execute("CREATE INDEX IX_lastname ON users (lastname);");
Thread.sleep(500);
}

View File

@@ -47,7 +47,7 @@ public class CompositeKeyCrudIntegrationTests extends AbstractKeyspaceCreatingIn
private CorrelationEntity correlationEntity1, correlationEntity2;
@Before
public void setUp() throws Throwable {
public void setUp() {
operations = new CassandraTemplate(session);

View File

@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
@@ -49,10 +50,14 @@ import org.springframework.util.ClassUtils;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.DefaultConsistencyLevel;
import com.datastax.oss.driver.api.core.ProtocolVersion;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.data.UdtValue;
import com.datastax.oss.driver.api.core.detach.AttachmentPoint;
import com.datastax.oss.driver.api.core.type.DataTypes;
import com.datastax.oss.driver.api.core.type.UserDefinedType;
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
import com.datastax.oss.driver.internal.core.data.DefaultUdtValue;
/**
* Unit tests for {@link PartTreeCassandraQuery}.
@@ -65,7 +70,8 @@ public class PartTreeCassandraQueryUnitTests {
@Mock CassandraOperations mockCassandraOperations;
@Mock UserTypeResolver userTypeResolverMock;
@Mock UserDefinedType userTypeMock;
@Mock UdtValue udtValueMock;
@Mock AttachmentPoint attachmentPoint;
DefaultUdtValue udtValue;
CassandraMappingContext mappingContext;
CassandraConverter converter;
@@ -75,11 +81,21 @@ public class PartTreeCassandraQueryUnitTests {
this.mappingContext = new CassandraMappingContext();
this.mappingContext.setUserTypeResolver(userTypeResolverMock);
when(userTypeResolverMock.resolveType(any())).thenReturn(userTypeMock);
this.converter = new MappingCassandraConverter(mappingContext);
when(mockCassandraOperations.getConverter()).thenReturn(converter);
when(udtValueMock.getType()).thenReturn(userTypeMock);
when(attachmentPoint.getCodecRegistry()).thenReturn(CodecRegistry.DEFAULT);
when(attachmentPoint.getProtocolVersion()).thenReturn(ProtocolVersion.DEFAULT);
when(userTypeMock.getAttachmentPoint()).thenReturn(attachmentPoint);
when(userTypeMock.getFieldNames())
.thenReturn(Arrays.asList("city", "country").stream().map(CqlIdentifier::fromCql).collect(Collectors.toList()));
when(userTypeMock.getFieldTypes()).thenReturn(Arrays.asList(DataTypes.TEXT, DataTypes.TEXT));
udtValue = new DefaultUdtValue(userTypeMock);
when(userTypeMock.newValue()).thenReturn(udtValue);
}
@Test // DATACASS-7
@@ -134,7 +150,7 @@ public class PartTreeCassandraQueryUnitTests {
public void shouldDeriveFieldInCollectionQuery() {
String query = deriveQueryFromMethod(Repo.class, "findByFirstnameIn", new Class[] { Collection.class },
Arrays.asList("Hank", "Walter")).toString();
Arrays.asList("Hank", "Walter")).getQuery();
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname IN ('Hank','Walter')");
}
@@ -142,29 +158,27 @@ public class PartTreeCassandraQueryUnitTests {
@Test // DATACASS-172
public void shouldDeriveSimpleQueryWithMappedUDT() {
when(userTypeResolverMock.resolveType(CqlIdentifier.fromCql("address"))).thenReturn(userTypeMock);
when(userTypeMock.newValue()).thenReturn(udtValueMock);
String query = deriveQueryFromMethod("findByMainAddress", new AddressType());
assertThat(query).isEqualTo("SELECT * FROM person WHERE mainaddress={}");
assertThat(query).isEqualTo("SELECT * FROM person WHERE mainaddress={city:NULL,country:NULL}");
}
@Test // DATACASS-172
public void shouldDeriveSimpleQueryWithUDTValue() {
String query = deriveQueryFromMethod("findByMainAddress", udtValueMock);
String query = deriveQueryFromMethod(Repo.class, "findByMainAddress", new Class[] { UdtValue.class }, udtValue)
.getQuery();
assertThat(query).isEqualTo("SELECT * FROM person WHERE mainaddress={}");
assertThat(query).isEqualTo("SELECT * FROM person WHERE mainaddress={city:NULL,country:NULL}");
}
@Test // DATACASS-357
public void shouldDeriveUdtInCollectionQuery() {
String query = deriveQueryFromMethod(Repo.class, "findByMainAddressIn", new Class[] { Collection.class },
Collections.singleton(udtValueMock)).toString();
Collections.singleton(udtValue)).getQuery();
assertThat(query).isEqualTo("SELECT * FROM person WHERE mainaddress IN ({})");
assertThat(query).isEqualTo("SELECT * FROM person WHERE mainaddress IN ({city:NULL,country:NULL})");
}
@Test // DATACASS-343
@@ -191,7 +205,7 @@ public class PartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "findByFirstname",
new Class[] { QueryOptions.class, String.class }, queryOptions, "Walter");
assertThat(statement.toString()).isEqualTo("SELECT * FROM person WHERE firstname='Walter'");
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM person WHERE firstname='Walter'");
assertThat(statement.getPageSize()).isEqualTo(777);
}
@@ -200,7 +214,7 @@ public class PartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "findPersonBy", new Class[0]);
assertThat(statement.toString()).isEqualTo("SELECT * FROM person");
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM person");
assertThat(statement.getConsistencyLevel()).isEqualTo(DefaultConsistencyLevel.LOCAL_ONE);
}
@@ -209,7 +223,7 @@ public class PartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "countBy", new Class[0]);
assertThat(statement.toString()).isEqualTo("SELECT COUNT(1) FROM person");
assertThat(statement.getQuery()).isEqualTo("SELECT count(1) FROM person");
}
@Test // DATACASS-611
@@ -218,7 +232,7 @@ public class PartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "deleteAllByLastname", new Class[] { String.class },
"Walter");
assertThat(statement.toString()).isEqualTo("DELETE FROM person WHERE lastname='Walter'");
assertThat(statement.getQuery()).isEqualTo("DELETE FROM person WHERE lastname='Walter'");
}
@Test // DATACASS-512
@@ -226,7 +240,7 @@ public class PartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "existsBy", new Class[0]);
assertThat(statement.toString()).isEqualTo("SELECT * FROM person LIMIT 1");
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM person LIMIT 1");
}
private String deriveQueryFromMethod(String method, Object... args) {
@@ -237,7 +251,7 @@ public class PartTreeCassandraQueryUnitTests {
types[i] = ClassUtils.getUserClass(args[i].getClass());
}
return deriveQueryFromMethod(Repo.class, method, types, args).toString();
return deriveQueryFromMethod(Repo.class, method, types, args).getQuery();
}
private SimpleStatement deriveQueryFromMethod(Class<?> repositoryInterface, String method, Class<?>[] types,

View File

@@ -118,7 +118,7 @@ public class ReactivePartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "findByFirstname",
new Class[] { QueryOptions.class, String.class }, queryOptions, "Walter");
assertThat(statement.toString()).isEqualTo("SELECT * FROM person WHERE firstname='Walter'");
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM person WHERE firstname='Walter'");
assertThat(statement.getPageSize()).isEqualTo(777);
}
@@ -127,7 +127,7 @@ public class ReactivePartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(Repo.class, "findPersonBy", new Class[0]);
assertThat(statement.toString()).isEqualTo("SELECT * FROM person");
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM person");
assertThat(statement.getConsistencyLevel()).isEqualTo(DefaultConsistencyLevel.LOCAL_ONE);
}
@@ -137,7 +137,7 @@ public class ReactivePartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(PartTreeCassandraQueryUnitTests.Repo.class, "countBy",
new Class[0]);
assertThat(statement.toString()).isEqualTo("SELECT COUNT(1) FROM person");
assertThat(statement.getQuery()).isEqualTo("SELECT count(1) FROM person");
}
@Test // DATACASS-611
@@ -146,7 +146,7 @@ public class ReactivePartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(PartTreeCassandraQueryUnitTests.Repo.class, "deleteAllByLastname",
new Class[] { String.class }, "Walter");
assertThat(statement.toString()).isEqualTo("DELETE FROM person WHERE lastname='Walter'");
assertThat(statement.getQuery()).isEqualTo("DELETE FROM person WHERE lastname='Walter'");
}
@Test // DATACASS-512
@@ -155,7 +155,7 @@ public class ReactivePartTreeCassandraQueryUnitTests {
SimpleStatement statement = deriveQueryFromMethod(PartTreeCassandraQueryUnitTests.Repo.class, "existsBy",
new Class[0]);
assertThat(statement.toString()).isEqualTo("SELECT * FROM person LIMIT 1");
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM person LIMIT 1");
}
private String deriveQueryFromMethod(String method, Object... args) {

View File

@@ -366,7 +366,7 @@ public class StringBasedCassandraQueryUnitTests {
SimpleStatement actual = cassandraQuery.createQuery(accessor);
assertThat(actual.getQuery()).isEqualTo("SELECT * FROM person WHERE address=?;");
assertThat(actual.getPositionalValues().get(0).toString()).isEqualTo("UdtValue");
assertThat(actual.getPositionalValues().get(0).toString()).isEqualTo("udtValue");
}
@Test // DATACASS-146

View File

@@ -20,8 +20,11 @@ import static org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspac
import java.util.Collections;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.ReactiveSession;
import org.springframework.data.cassandra.config.AbstractReactiveCassandraConfiguration;
import org.springframework.data.cassandra.config.CqlSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.DropKeyspaceSpecification;
@@ -48,6 +51,31 @@ public class IntegrationTestConfig extends AbstractReactiveCassandraConfiguratio
return PORT;
}
@Bean
@Override
public CqlSessionFactoryBean session() {
SharedCqlSessionFactoryBean bean = new SharedCqlSessionFactoryBean();
bean.setContactPoints(getContactPoints());
bean.setPort(getPort());
bean.setKeyspaceCreations(getKeyspaceCreations());
bean.setKeyspaceDrops(getKeyspaceDrops());
bean.setKeyspaceName(getKeyspaceName());
bean.setKeyspaceStartupScripts(getStartupScripts());
bean.setKeyspaceShutdownScripts(getShutdownScripts());
return bean;
}
@Bean(destroyMethod = "")
@Override
public ReactiveSession reactiveSession() {
return super.reactiveSession();
}
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE;

View File

@@ -50,7 +50,7 @@ public class SchemaTestUtils {
Optional<TableMetadata> table = session.getKeyspace().flatMap(it -> session.getMetadata().getKeyspace(it))
.flatMap(it -> it.getTable(persistentEntity.getTableName()));
if (table.isPresent()) {
if (!table.isPresent()) {
CreateTableSpecification tableSpecification = mappingContext.getCreateTableSpecificationFor(persistentEntity);
operations.getCqlOperations().execute(new CreateTableCqlGenerator(tableSpecification).toCql());
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.data.cassandra.repository.support;
import org.springframework.data.cassandra.config.CqlSessionFactoryBean;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
/**
* @author Mark Paluch
*/
class SharedCqlSessionFactoryBean extends CqlSessionFactoryBean {
@Override
protected CqlSession buildSystemSession(CqlSessionBuilder sessionBuilder) {
return AbstractSpringDataEmbeddedCassandraIntegrationTest.cassandraEnvironment.getSystemSession();
}
@Override
protected CqlSession buildSession(CqlSessionBuilder sessionBuilder) {
CqlSession session = AbstractSpringDataEmbeddedCassandraIntegrationTest.cassandraEnvironment.getSession();
session.execute("USE " + getKeyspaceName());
return session;
}
@Override
protected void closeSession() {}
@Override
protected void closeSystemSession() {}
}

View File

@@ -29,6 +29,7 @@ import java.util.stream.IntStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
@@ -45,7 +46,7 @@ import org.springframework.data.cassandra.core.query.CassandraPageRequest;
import org.springframework.data.cassandra.domain.User;
import org.springframework.data.cassandra.domain.UserToken;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.test.util.AbstractKeyspaceCreatingIntegrationTest;
import org.springframework.data.cassandra.test.util.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
@@ -61,7 +62,7 @@ import org.springframework.util.ClassUtils;
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
public class SimpleCassandraRepositoryIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest
public class SimpleCassandraRepositoryIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest
implements BeanClassLoaderAware, BeanFactoryAware {
@Configuration

View File

@@ -44,7 +44,7 @@ import org.springframework.data.cassandra.core.query.CassandraPageRequest;
import org.springframework.data.cassandra.domain.User;
import org.springframework.data.cassandra.domain.UserToken;
import org.springframework.data.cassandra.repository.ReactiveCassandraRepository;
import org.springframework.data.cassandra.test.util.AbstractKeyspaceCreatingIntegrationTest;
import org.springframework.data.cassandra.test.util.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
@@ -60,7 +60,7 @@ import org.springframework.test.context.junit4.SpringRunner;
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
public class SimpleReactiveCassandraRepositoryIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest
public class SimpleReactiveCassandraRepositoryIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest
implements BeanClassLoaderAware, BeanFactoryAware {
@Configuration

View File

@@ -123,7 +123,7 @@ public class UserDefinedTypeBuilder {
@Override
@NonNull
public UserDefinedType copy(boolean newFrozen) {
return delegate.copy(newFrozen);
return new UserDefinedTypeWrapper(delegate.copy(newFrozen));
}
@Override

View File

@@ -137,7 +137,16 @@ public class CassandraRule extends ExternalResource {
}
/**
* Returns the {@link Session}. The session state can be initialized and pointing to a keyspace other than
* Returns the system {@link CqlSession}.
*
* @return the Session
*/
public CqlSession getSystemSession() {
return this.system;
}
/**
* Returns the {@link CqlSession}. The session state can be initialized and pointing to a keyspace other than
* {@code system}.
*
* @return the Session
@@ -282,6 +291,7 @@ public class CassandraRule extends ExternalResource {
this.sessionBuilder = this.parent.sessionBuilder;
}
this.system = resolveSystemSession();
this.session = resolveSession();
}
@@ -303,10 +313,16 @@ public class CassandraRule extends ExternalResource {
return isEmbedded() ? EmbeddedCassandraServerHelper.getNativeTransportPort() : this.properties.getCassandraPort();
}
private CqlSession resolveSystemSession() {
return isNotParent() ? this.parent.getSystemSession()
: resourceHolder != null ? resourceHolder.system : this.sessionBuilder.build();
}
private CqlSession resolveSession() {
return isNotParent() ? this.parent.getSession()
: resourceHolder != null ? resourceHolder.system : this.sessionBuilder.build();
: resourceHolder != null ? resourceHolder.toUse : this.sessionBuilder.build();
}
private void executeBeforeHooks() {
@@ -411,13 +427,16 @@ public class CassandraRule extends ExternalResource {
private static class ResourceHolder {
private final CqlSessionBuilder sessionBuilder;
private final CqlSession system;
final CqlSession system;
final CqlSession toUse;
private ResourceHolder(CqlSessionBuilder sessionBuilder) {
this.sessionBuilder = sessionBuilder;
this.system = sessionBuilder.build();
this.toUse = sessionBuilder.build();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
toUse.close();
system.close();
}));
}

View File

@@ -72,7 +72,7 @@ datastax-java-driver {
# Required: yes
# Modifiable at runtime: yes, the new value will be used for checks issued after the change.
# Overridable in a profile: no
interval = 200 milliseconds
interval = 100 seconds
# The timeout after which schema agreement fails.
# If this is set to 0, schema agreement is skipped and will always fail.
@@ -80,7 +80,7 @@ datastax-java-driver {
# Required: yes
# Modifiable at runtime: yes, the new value will be used for checks issued after the change.
# Overridable in a profile: no
timeout = 1 seconds
timeout = 100 seconds
# Whether to log a warning if schema agreement fails.
# You might want to change this if you've set the timeout to 0.

View File

@@ -14,9 +14,6 @@
value="#{T(org.springframework.data.cassandra.support.RandomKeyspaceName).create()}"/>
</bean>
<bean id="nettyOptions"
class="org.springframework.data.cassandra.support.IntegrationTestNettyOptions"/>
<context:property-placeholder
location="classpath:/config/cassandra-connection.properties"/>

View File

@@ -9,9 +9,6 @@
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
">
<bean id="nettyOptions"
class="org.springframework.data.cassandra.support.IntegrationTestNettyOptions"/>
<context:property-placeholder
location="classpath:/config/cassandra-connection.properties,classpath:/org/springframework/data/cassandra/config/cassandra.properties"/>