From 367b66f37e1e1cb6abdb5a80b151cca147234c19 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 26 Feb 2018 14:16:24 +0100 Subject: [PATCH] DATACASS-155 - Polishing. Add author and since tags. Add nullable annotations. Apply timestamp to DELETE statements. Extend tests. Original pull request: #122. --- .../data/cassandra/core/InsertOptions.java | 94 +++++++++++++++--- .../data/cassandra/core/QueryUtils.java | 9 +- .../data/cassandra/core/StatementFactory.java | 8 +- .../data/cassandra/core/UpdateOptions.java | 97 +++++++++++++++---- .../cassandra/core/cql/QueryOptionsUtil.java | 24 +++++ .../data/cassandra/core/cql/WriteOptions.java | 80 +++++++++------ .../CassandraTemplateIntegrationTests.java | 10 +- .../core/InsertOptionsUnitTests.java | 18 ++-- .../core/UpdateOptionsUnitTests.java | 12 +-- .../core/cql/QueryOptionsUtilUnitTests.java | 19 ++++ 10 files changed, 286 insertions(+), 85 deletions(-) diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/InsertOptions.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/InsertOptions.java index a4d735ed7..e6ac46588 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/InsertOptions.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/InsertOptions.java @@ -15,12 +15,12 @@ */ package org.springframework.data.cassandra.core; +import lombok.EqualsAndHashCode; + import java.time.Duration; import java.time.Instant; import java.util.concurrent.TimeUnit; -import lombok.EqualsAndHashCode; - import org.springframework.data.cassandra.core.cql.WriteOptions; import org.springframework.lang.Nullable; @@ -31,6 +31,7 @@ import com.datastax.driver.core.policies.RetryPolicy; * Extension to {@link WriteOptions} for use with {@code INSERT} operations. * * @author Mark Paluch + * @author Lukasz Antoniak * @since 2.0 */ @EqualsAndHashCode(callSuper = true) @@ -41,7 +42,8 @@ public class InsertOptions extends WriteOptions { private boolean ifNotExists; private InsertOptions(@Nullable ConsistencyLevel consistencyLevel, @Nullable RetryPolicy retryPolicy, - @Nullable Boolean tracing, @Nullable Integer fetchSize, Duration readTimeout, Duration ttl, Long timestamp, boolean ifNotExists) { + @Nullable Boolean tracing, @Nullable Integer fetchSize, Duration readTimeout, Duration ttl, + @Nullable Long timestamp, boolean ifNotExists) { super(consistencyLevel, retryPolicy, tracing, fetchSize, readTimeout, ttl, timestamp); @@ -88,6 +90,7 @@ public class InsertOptions extends WriteOptions { * Builder for {@link InsertOptions}. * * @author Mark Paluch + * @author Lukasz Antoniak * @since 2.0 */ public static class InsertOptionsBuilder extends WriteOptionsBuilder { @@ -103,64 +106,123 @@ public class InsertOptions extends WriteOptions { this.ifNotExists = insertOptions.ifNotExists; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#consistencyLevel(com.datastax.driver.core.ConsistencyLevel) + */ @Override public InsertOptionsBuilder consistencyLevel(com.datastax.driver.core.ConsistencyLevel consistencyLevel) { - return (InsertOptionsBuilder) super.consistencyLevel(consistencyLevel); + + super.consistencyLevel(consistencyLevel); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#retryPolicy(com.datastax.driver.core.policies.RetryPolicy) + */ @Override public InsertOptionsBuilder retryPolicy(com.datastax.driver.core.policies.RetryPolicy driverRetryPolicy) { - return (InsertOptionsBuilder) super.retryPolicy(driverRetryPolicy); + + super.retryPolicy(driverRetryPolicy); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#fetchSize(int) + */ @Override public InsertOptionsBuilder fetchSize(int fetchSize) { return (InsertOptionsBuilder) super.fetchSize(fetchSize); } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#readTimeout(long) + */ @Override public InsertOptionsBuilder readTimeout(long readTimeout) { - return (InsertOptionsBuilder) super.readTimeout(readTimeout); + + super.readTimeout(readTimeout); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#readTimeout(long, java.util.concurrent.TimeUnit) + */ @Override @Deprecated public InsertOptionsBuilder readTimeout(long readTimeout, TimeUnit timeUnit) { - return (InsertOptionsBuilder) super.readTimeout(readTimeout, timeUnit); + + super.readTimeout(readTimeout, timeUnit); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#readTimeout(java.time.Duration) + */ @Override public InsertOptionsBuilder readTimeout(Duration readTimeout) { - return (InsertOptionsBuilder) super.readTimeout(readTimeout); + + super.readTimeout(readTimeout); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#ttl(java.time.Duration) + */ @Override public InsertOptionsBuilder ttl(Duration ttl) { - return (InsertOptionsBuilder) super.ttl(ttl); + + super.ttl(ttl); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#tracing(boolean) + */ @Override public InsertOptionsBuilder tracing(boolean tracing) { - return (InsertOptionsBuilder) super.tracing(tracing); + + super.tracing(tracing); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#withTracing() + */ @Override public InsertOptionsBuilder withTracing() { - return (InsertOptionsBuilder) super.withTracing(); + + super.withTracing(); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#ttl(int) + */ + @Override public InsertOptionsBuilder ttl(int ttl) { - return (InsertOptionsBuilder) super.ttl(ttl); + + super.ttl(ttl); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#timestamp(long) + */ @Override public InsertOptionsBuilder timestamp(long timestamp) { - return (InsertOptionsBuilder) super.timestamp(timestamp); + + super.timestamp(timestamp); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#timestamp(java.time.Instant) + */ @Override public InsertOptionsBuilder timestamp(Instant timestamp) { - return (InsertOptionsBuilder) super.timestamp(timestamp); + + super.timestamp(timestamp); + return this; } /** @@ -191,8 +253,8 @@ public class InsertOptions extends WriteOptions { * @return a new {@link InsertOptions} with the configured values */ public InsertOptions build() { - return new InsertOptions(this.consistencyLevel, this.retryPolicy, this.tracing, - this.fetchSize, this.readTimeout, this.ttl, this.timestamp, this.ifNotExists); + return new InsertOptions(this.consistencyLevel, this.retryPolicy, this.tracing, this.fetchSize, this.readTimeout, + this.ttl, this.timestamp, this.ifNotExists); } } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java index ab5029c97..113a55c55 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java @@ -132,7 +132,14 @@ class QueryUtils { Delete.Selection deleteSelection = QueryBuilder.delete(); Delete delete = deleteSelection.from(tableName); - Where where = QueryOptionsUtil.addQueryOptions(delete.where(), options); + + if (options instanceof WriteOptions) { + QueryOptionsUtil.addWriteOptions(delete, (WriteOptions) options); + } else { + QueryOptionsUtil.addQueryOptions(delete, options); + } + + Where where = delete.where(); entityWriter.write(objectToDelete, where); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java index 765d137f3..9b2e13db8 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java @@ -458,7 +458,13 @@ public class StatementFactory { Delete delete = delete(columnNames, tableName, filter); - query.getQueryOptions().ifPresent(queryOptions -> QueryOptionsUtil.addQueryOptions(delete, queryOptions)); + query.getQueryOptions().ifPresent(queryOptions -> { + if (queryOptions instanceof WriteOptions) { + QueryOptionsUtil.addWriteOptions(delete, (WriteOptions) queryOptions); + } else { + QueryOptionsUtil.addQueryOptions(delete, queryOptions); + } + }); query.getPagingState().ifPresent(delete::setPagingState); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/UpdateOptions.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/UpdateOptions.java index d5c53b47c..4dc0e3b05 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/UpdateOptions.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/UpdateOptions.java @@ -15,12 +15,12 @@ */ package org.springframework.data.cassandra.core; +import lombok.EqualsAndHashCode; + import java.time.Duration; import java.time.Instant; import java.util.concurrent.TimeUnit; -import lombok.EqualsAndHashCode; - import org.springframework.data.cassandra.core.cql.WriteOptions; import org.springframework.lang.Nullable; @@ -31,6 +31,7 @@ import com.datastax.driver.core.policies.RetryPolicy; * Extension to {@link WriteOptions} for use with {@code UPDATE} operations. * * @author Mark Paluch + * @author Lukasz Antoniak * @since 2.0 */ @EqualsAndHashCode(callSuper = true) @@ -41,7 +42,8 @@ public class UpdateOptions extends WriteOptions { private boolean ifExists; private UpdateOptions(@Nullable ConsistencyLevel consistencyLevel, @Nullable RetryPolicy retryPolicy, - @Nullable Boolean tracing, @Nullable Integer fetchSize, Duration readTimeout, Duration ttl, Long timestamp, boolean ifExists) { + @Nullable Boolean tracing, @Nullable Integer fetchSize, Duration readTimeout, Duration ttl, + @Nullable Long timestamp, boolean ifExists) { super(consistencyLevel, retryPolicy, tracing, fetchSize, readTimeout, ttl, timestamp); @@ -88,6 +90,7 @@ public class UpdateOptions extends WriteOptions { * Builder for {@link UpdateOptions}. * * @author Mark Paluch + * @author Lukasz Antoniak * @since 2.0 */ public static class UpdateOptionsBuilder extends WriteOptionsBuilder { @@ -103,64 +106,124 @@ public class UpdateOptions extends WriteOptions { this.ifExists = updateOptions.ifExists; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#consistencyLevel(com.datastax.driver.core.ConsistencyLevel) + */ @Override public UpdateOptionsBuilder consistencyLevel(com.datastax.driver.core.ConsistencyLevel consistencyLevel) { - return (UpdateOptionsBuilder) super.consistencyLevel(consistencyLevel); + + super.consistencyLevel(consistencyLevel); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#retryPolicy(com.datastax.driver.core.policies.RetryPolicy) + */ @Override public UpdateOptionsBuilder retryPolicy(com.datastax.driver.core.policies.RetryPolicy driverRetryPolicy) { - return (UpdateOptionsBuilder) super.retryPolicy(driverRetryPolicy); + + super.retryPolicy(driverRetryPolicy); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#fetchSize(int) + */ @Override public UpdateOptionsBuilder fetchSize(int fetchSize) { - return (UpdateOptionsBuilder) super.fetchSize(fetchSize); + + super.fetchSize(fetchSize); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#readTimeout(long) + */ @Override public UpdateOptionsBuilder readTimeout(long readTimeout) { - return (UpdateOptionsBuilder) super.readTimeout(readTimeout); + + super.readTimeout(readTimeout); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#readTimeout(long, java.util.concurrent.TimeUnit) + */ @Override @Deprecated public UpdateOptionsBuilder readTimeout(long readTimeout, TimeUnit timeUnit) { - return (UpdateOptionsBuilder) super.readTimeout(readTimeout, timeUnit); + + super.readTimeout(readTimeout, timeUnit); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#readTimeout(java.time.Duration) + */ @Override public UpdateOptionsBuilder readTimeout(Duration readTimeout) { - return (UpdateOptionsBuilder) super.readTimeout(readTimeout); + + super.readTimeout(readTimeout); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#ttl(java.time.Duration) + */ @Override public UpdateOptionsBuilder ttl(Duration ttl) { - return (UpdateOptionsBuilder) super.ttl(ttl); + + super.ttl(ttl); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#tracing(boolean) + */ @Override public UpdateOptionsBuilder tracing(boolean tracing) { - return (UpdateOptionsBuilder) super.tracing(tracing); + + super.tracing(tracing); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#withTracing() + */ @Override public UpdateOptionsBuilder withTracing() { - return (UpdateOptionsBuilder) super.withTracing(); + + super.withTracing(); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#ttl(int) + */ public UpdateOptionsBuilder ttl(int ttl) { - return (UpdateOptionsBuilder) super.ttl(ttl); + + super.ttl(ttl); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#timestamp(long) + */ @Override public UpdateOptionsBuilder timestamp(long timestamp) { - return (UpdateOptionsBuilder) super.timestamp(timestamp); + + super.timestamp(timestamp); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.WriteOptions.WriteOptionsBuilder#timestamp(java.time.Instant) + */ @Override public UpdateOptionsBuilder timestamp(Instant timestamp) { - return (UpdateOptionsBuilder) super.timestamp(timestamp); + + super.timestamp(timestamp); + return this; } /** @@ -191,8 +254,8 @@ public class UpdateOptions extends WriteOptions { * @return a new {@link UpdateOptions} with the configured values */ public UpdateOptions build() { - return new UpdateOptions(this.consistencyLevel, this.retryPolicy, this.tracing, - this.fetchSize, this.readTimeout, this.ttl, this.timestamp, this.ifExists); + return new UpdateOptions(this.consistencyLevel, this.retryPolicy, this.tracing, this.fetchSize, this.readTimeout, + this.ttl, this.timestamp, this.ifExists); } } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtil.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtil.java index 567837e7e..41d1f4387 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtil.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtil.java @@ -19,6 +19,7 @@ import org.springframework.util.Assert; import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.Statement; +import com.datastax.driver.core.querybuilder.Delete; import com.datastax.driver.core.querybuilder.Insert; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Update; @@ -27,6 +28,7 @@ import com.datastax.driver.core.querybuilder.Update; * Utility class to associate {@link QueryOptions} and {@link WriteOptions} with QueryBuilder {@link Statement}s. * * @author Mark Paluch + * @author Lukasz Antoniak * @since 2.0 */ public abstract class QueryOptionsUtil { @@ -106,6 +108,7 @@ public abstract class QueryOptionsUtil { if (!writeOptions.getTtl().isNegative()) { insert.using(QueryBuilder.ttl(Math.toIntExact(writeOptions.getTtl().getSeconds()))); } + if (writeOptions.getTimestamp() != null) { insert.using(QueryBuilder.timestamp(writeOptions.getTimestamp())); } @@ -113,6 +116,27 @@ public abstract class QueryOptionsUtil { return insert; } + /** + * Add common {@link WriteOptions} options to {@link Delete} CQL statements. + * + * @param delete {@link Delete} CQL statement, must not be {@literal null}. + * @param writeOptions write options (e.g. consistency level) to add to the CQL statement. + * @return the given {@link Delete}. + * @since 2.1 + */ + public static Delete addWriteOptions(Delete delete, WriteOptions writeOptions) { + + Assert.notNull(delete, "Update must not be null"); + + addQueryOptions(delete, writeOptions); + + if (writeOptions.getTimestamp() != null) { + delete.using(QueryBuilder.timestamp(writeOptions.getTimestamp())); + } + + return delete; + } + /** * Add common {@link WriteOptions} options to {@link Update} CQL statements. * diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/WriteOptions.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/WriteOptions.java index a2ba691dc..735963512 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/WriteOptions.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/WriteOptions.java @@ -15,12 +15,12 @@ */ package org.springframework.data.cassandra.core.cql; +import lombok.EqualsAndHashCode; + import java.time.Duration; import java.time.Instant; import java.util.concurrent.TimeUnit; -import lombok.EqualsAndHashCode; - import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -33,6 +33,7 @@ import com.datastax.driver.core.policies.RetryPolicy; * * @author David Webb * @author Mark Paluch + * @author Lukasz Antoniak * @see QueryOptions */ @EqualsAndHashCode(callSuper = true) @@ -74,7 +75,8 @@ public class WriteOptions extends QueryOptions { } protected WriteOptions(@Nullable ConsistencyLevel consistencyLevel, @Nullable RetryPolicy retryPolicy, - @Nullable Boolean tracing, @Nullable Integer fetchSize, Duration readTimeout, Duration ttl, Long timestamp) { + @Nullable Boolean tracing, @Nullable Integer fetchSize, Duration readTimeout, Duration ttl, + @Nullable Long timestamp) { super(consistencyLevel, retryPolicy, tracing, fetchSize, readTimeout); @@ -122,7 +124,9 @@ public class WriteOptions extends QueryOptions { /** * @return mutation timestamp in microseconds. + * @since 2.1 */ + @Nullable public Long getTimestamp() { return this.timestamp; } @@ -131,6 +135,7 @@ public class WriteOptions extends QueryOptions { * Builder for {@link WriteOptions}. * * @author Mark Paluch + * @author Lukasz Antoniak * @since 1.5 */ public static class WriteOptionsBuilder extends QueryOptionsBuilder { @@ -148,73 +153,85 @@ public class WriteOptions extends QueryOptions { this.timestamp = writeOptions.timestamp; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#consistencyLevel(com.datastax.driver.core.ConsistencyLevel) */ @Override public WriteOptionsBuilder consistencyLevel(com.datastax.driver.core.ConsistencyLevel consistencyLevel) { - return (WriteOptionsBuilder) super.consistencyLevel(consistencyLevel); + + super.consistencyLevel(consistencyLevel); + return this; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#retryPolicy(org.springframework.data.cassandra.core.cql.RetryPolicy) */ @Override public WriteOptionsBuilder retryPolicy(com.datastax.driver.core.policies.RetryPolicy driverRetryPolicy) { - return (WriteOptionsBuilder) super.retryPolicy(driverRetryPolicy); + + super.retryPolicy(driverRetryPolicy); + return this; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#fetchSize(int) */ @Override public WriteOptionsBuilder fetchSize(int fetchSize) { - return (WriteOptionsBuilder) super.fetchSize(fetchSize); + + super.fetchSize(fetchSize); + return this; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#readTimeout(long) */ @Override public WriteOptionsBuilder readTimeout(long readTimeout) { - return (WriteOptionsBuilder) super.readTimeout(readTimeout); + + super.readTimeout(readTimeout); + return this; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#readTimeout(long, java.util.concurrent.TimeUnit) */ @Override @Deprecated public WriteOptionsBuilder readTimeout(long readTimeout, TimeUnit timeUnit) { - return (WriteOptionsBuilder) super.readTimeout(readTimeout, timeUnit); + + super.readTimeout(readTimeout, timeUnit); + return this; } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#readTimeout(java.time.Duration) + */ @Override public WriteOptionsBuilder readTimeout(Duration readTimeout) { - return (WriteOptionsBuilder) super.readTimeout(readTimeout); + + super.readTimeout(readTimeout); + return this; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#tracing(boolean) */ @Override public WriteOptionsBuilder tracing(boolean tracing) { - return (WriteOptionsBuilder) super.tracing(tracing); + + super.tracing(tracing); + return this; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.cql.QueryOptions.QueryOptionsBuilder#withTracing() */ @Override public WriteOptionsBuilder withTracing() { - return (WriteOptionsBuilder) super.withTracing(); + + super.withTracing(); + return this; } /** @@ -254,10 +271,15 @@ public class WriteOptions extends QueryOptions { * * @param timestamp mutation timestamp in microseconds. * @return {@code this} {@link WriteOptionsBuilder} + * @since 2.1 + * @see TimeUnit#MICROSECONDS */ public WriteOptionsBuilder timestamp(long timestamp) { + Assert.isTrue(timestamp >= 0, "Timestamp must be greater than equal to zero"); + this.timestamp = timestamp; + return this; } @@ -266,10 +288,14 @@ public class WriteOptions extends QueryOptions { * * @param timestamp mutation date time. * @return {@code this} {@link WriteOptionsBuilder} + * @since 2.1 */ public WriteOptionsBuilder timestamp(Instant timestamp) { + Assert.notNull(timestamp, "Timestamp must not be null"); + this.timestamp = TimeUnit.MILLISECONDS.toMicros(timestamp.toEpochMilli()); + return this; } @@ -279,8 +305,8 @@ public class WriteOptions extends QueryOptions { * @return a new {@link WriteOptions} with the configured values */ public WriteOptions build() { - return new WriteOptions(this.consistencyLevel, this.retryPolicy, this.tracing, - this.fetchSize, this.readTimeout, this.ttl, this.timestamp); + return new WriteOptions(this.consistencyLevel, this.retryPolicy, this.tracing, this.fetchSize, this.readTimeout, + this.ttl, this.timestamp); } } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java index 4735a484b..f7b058915 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java @@ -15,9 +15,9 @@ */ package org.springframework.data.cassandra.core; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assume.assumeTrue; -import static org.springframework.data.cassandra.core.query.Criteria.where; +import static org.assertj.core.api.Assertions.*; +import static org.junit.Assume.*; +import static org.springframework.data.cassandra.core.query.Criteria.*; import java.time.Instant; import java.time.LocalDateTime; @@ -33,7 +33,6 @@ import java.util.stream.Stream; import org.junit.Before; import org.junit.Test; - import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; import org.springframework.data.cassandra.core.cql.CqlTemplate; import org.springframework.data.cassandra.core.mapping.BasicMapId; @@ -196,6 +195,7 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI @Test // DATACASS-155 public void shouldNotOverrideLaterMutation() { + Instant now = LocalDateTime.now().atZone( ZoneId.systemDefault() ).toInstant(); User user = new User("heisenberg", "Walter", "White"); template.insert(user); @@ -206,7 +206,7 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI // previous mutation user.setFirstname("Greg"); - template.update(user, UpdateOptions.builder().timestamp(now.minusSeconds(10)).build()); + template.update(user, UpdateOptions.builder().timestamp(now.minusSeconds(120)).build()); User loaded = template.selectOneById(user.getId(), User.class); assertThat(loaded.getFirstname()).isEqualTo("John"); diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/InsertOptionsUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/InsertOptionsUnitTests.java index 78f787ec8..879697c05 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/InsertOptionsUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/InsertOptionsUnitTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.cassandra.core; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; import java.time.Duration; import java.time.Instant; @@ -28,18 +28,16 @@ import org.junit.Test; * Unit tests for {@link InsertOptions}. * * @author Mark Paluch + * @author Lukasz Antoniak */ public class InsertOptionsUnitTests { - @Test // DATACASS-250 + @Test // DATACASS-250, DATACASS-155 public void shouldConfigureInsertOptions() { + Instant now = LocalDateTime.now().toInstant(ZoneOffset.UTC); - InsertOptions insertOptions = InsertOptions.builder() - .ttl(10) - .timestamp(now) - .withIfNotExists() - .build(); + InsertOptions insertOptions = InsertOptions.builder().ttl(10).timestamp(now).withIfNotExists().build(); assertThat(insertOptions.getTtl()).isEqualTo(Duration.ofSeconds(10)); assertThat(insertOptions.getTimestamp()).isEqualTo(now.toEpochMilli() * 1000); @@ -49,11 +47,7 @@ public class InsertOptionsUnitTests { @Test // DATACASS-56 public void buildInsertOptionsMutate() { - InsertOptions insertOptions = InsertOptions.builder() - .ttl(10) - .timestamp(1519222753) - .withIfNotExists() - .build(); + InsertOptions insertOptions = InsertOptions.builder().ttl(10).timestamp(1519222753).withIfNotExists().build(); InsertOptions mutated = insertOptions.mutate().ttl(Duration.ofSeconds(5)).timestamp(1519200753).build(); diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/UpdateOptionsUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/UpdateOptionsUnitTests.java index 003942bdb..f0a2f19e3 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/UpdateOptionsUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/UpdateOptionsUnitTests.java @@ -15,12 +15,10 @@ */ package org.springframework.data.cassandra.core; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; import java.time.Duration; import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; import org.junit.Test; @@ -28,12 +26,14 @@ import org.junit.Test; * Unit tests for {@link UpdateOptions}. * * @author Mark Paluch + * @author Lukasz Antoniak */ public class UpdateOptionsUnitTests { - @Test // DATACASS-250 + @Test // DATACASS-250, DATACASS-155 public void shouldConfigureUpdateOptions() { - Instant now = LocalDateTime.now().toInstant(ZoneOffset.UTC); + + Instant now = Instant.ofEpochSecond(1234); UpdateOptions updateOptions = UpdateOptions.builder() .ttl(10) @@ -46,7 +46,7 @@ public class UpdateOptionsUnitTests { assertThat(updateOptions.isIfExists()).isTrue(); } - @Test // DATACASS-56 + @Test // DATACASS-56, DATACASS-155 public void buildUpdateOptionsMutate() { UpdateOptions updateOptions = UpdateOptions.builder() diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtilUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtilUnitTests.java index 088f41a91..f5c2a7ceb 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtilUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/QueryOptionsUtilUnitTests.java @@ -32,6 +32,7 @@ import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.Session; import com.datastax.driver.core.Statement; import com.datastax.driver.core.policies.FallthroughRetryPolicy; +import com.datastax.driver.core.querybuilder.Delete; import com.datastax.driver.core.querybuilder.Insert; import com.datastax.driver.core.querybuilder.Update; import com.datastax.driver.core.querybuilder.Using; @@ -53,6 +54,7 @@ public class QueryOptionsUtilUnitTests { @Mock Session mockSession; @Mock Statement mockStatement; @Mock Update mockUpdate; + @Mock Delete mockDelete; @Test // DATACASS-202 public void addPreparedStatementOptionsShouldAddDriverQueryOptions() { @@ -165,4 +167,21 @@ public class QueryOptionsUtilUnitTests { verify(mockUpdate).using(Mockito.any(Using.class)); verify(mockUpdate).disableTracing(); } + + @Test // DATACASS-155 + public void addDeleteWriteOptionsShouldAddDriverQueryOptions() { + + WriteOptions writeOptions = WriteOptions.builder() // + .consistencyLevel(ConsistencyLevel.EACH_QUORUM) // + .retryPolicy(FallthroughRetryPolicy.INSTANCE) // + .timestamp(42) // + .tracing(false).build(); + + QueryOptionsUtil.addWriteOptions(mockDelete, writeOptions); + + verify(mockDelete).setConsistencyLevel(ConsistencyLevel.EACH_QUORUM); + verify(mockDelete).setRetryPolicy(FallthroughRetryPolicy.INSTANCE); + verify(mockDelete).using(Mockito.any(Using.class)); + verify(mockDelete).disableTracing(); + } }