Merge branch 'develop'

This commit is contained in:
Greg Burd 2017-10-30 15:59:38 -04:00
commit 9675c10772
116 changed files with 4576 additions and 3959 deletions

View file

@ -1,9 +1,9 @@
package net.helenus.core; package net.helenus.core;
import java.util.HashMap; import java.io.Serializable;
import java.util.Map; import java.util.*;
import java.util.Objects;
import java.util.Set; import org.apache.commons.lang3.SerializationUtils;
import com.google.common.primitives.Primitives; import com.google.common.primitives.Primitives;
@ -30,12 +30,12 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> T get(Getter<T> getter, Class<?> returnType) { public <T> T get(Getter<T> getter, Class<?> returnType) {
return (T) get(this.<T>methodNameFor(getter), returnType); return (T) get(this.<T>methodNameFor(getter), returnType);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> T get(String key, Class<?> returnType) { public <T> T get(String key, Class<?> returnType) {
T value = (T) backingMap.get(key); T value = (T) backingMap.get(key);
if (value == null) { if (value == null) {
@ -51,17 +51,27 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
return (T) type.getDefaultValue(); return (T) type.getDefaultValue();
} }
} else {
// Collections fetched from the entityMap
if (value instanceof Collection) {
try {
value = MappingUtil.<T>clone(value);
} catch (CloneNotSupportedException e) {
// TODO(gburd): deep?shallow? copy of List, Map, Set to a mutable collection.
value = (T) SerializationUtils.<Serializable>clone((Serializable) value);
}
}
} }
} }
return value; return value;
} }
protected <T> Object set(Getter<T> getter, Object value) { public <T> Object set(Getter<T> getter, Object value) {
return set(this.<T>methodNameFor(getter), value); return set(this.<T>methodNameFor(getter), value);
} }
protected Object set(String key, Object value) { public Object set(String key, Object value) {
if (key == null || value == null) { if (key == null || value == null) {
return null; return null;
} }
@ -71,11 +81,11 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> T mutate(Getter<T> getter, T value) { public <T> T mutate(Getter<T> getter, T value) {
return (T) mutate(this.<T>methodNameFor(getter), value); return (T) mutate(this.<T>methodNameFor(getter), value);
} }
protected Object mutate(String key, Object value) { public Object mutate(String key, Object value) {
Objects.requireNonNull(key); Objects.requireNonNull(key);
if (value == null) { if (value == null) {

View file

@ -24,14 +24,16 @@ import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.datastax.driver.core.*; import com.datastax.driver.core.*;
import com.datastax.driver.core.querybuilder.BuiltStatement; import com.google.common.base.Stopwatch;
import com.google.common.collect.Table; import com.google.common.collect.Table;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import brave.Tracer; import brave.Tracer;
import net.helenus.core.cache.Facet; import net.helenus.core.cache.Facet;
import net.helenus.core.operation.Operation;
import net.helenus.mapping.value.ColumnValuePreparer; import net.helenus.mapping.value.ColumnValuePreparer;
import net.helenus.mapping.value.ColumnValueProvider; import net.helenus.mapping.value.ColumnValueProvider;
import net.helenus.support.Either;
import net.helenus.support.HelenusException; import net.helenus.support.HelenusException;
public abstract class AbstractSessionOperations { public abstract class AbstractSessionOperations {
@ -60,7 +62,7 @@ public abstract class AbstractSessionOperations {
public PreparedStatement prepare(RegularStatement statement) { public PreparedStatement prepare(RegularStatement statement) {
try { try {
log(statement, false); logStatement(statement, false);
return currentSession().prepare(statement); return currentSession().prepare(statement);
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw translateException(e); throw translateException(e);
@ -69,7 +71,7 @@ public abstract class AbstractSessionOperations {
public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) { public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) {
try { try {
log(statement, false); logStatement(statement, false);
return currentSession().prepareAsync(statement); return currentSession().prepareAsync(statement);
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw translateException(e); throw translateException(e);
@ -77,37 +79,47 @@ public abstract class AbstractSessionOperations {
} }
public ResultSet execute(Statement statement, boolean showValues) { public ResultSet execute(Statement statement, boolean showValues) {
return executeAsync(statement, showValues).getUninterruptibly(); return execute(statement, null, null, showValues);
}
public ResultSet execute(Statement statement, Stopwatch timer, boolean showValues) {
return execute(statement, null, timer, showValues);
}
public ResultSet execute(Statement statement, UnitOfWork uow, boolean showValues) {
return execute(statement, uow, null, showValues);
}
public ResultSet execute(Statement statement, UnitOfWork uow, Stopwatch timer, boolean showValues) {
return executeAsync(statement, uow, timer, showValues).getUninterruptibly();
} }
public ResultSetFuture executeAsync(Statement statement, boolean showValues) { public ResultSetFuture executeAsync(Statement statement, boolean showValues) {
return executeAsync(statement, null, null, showValues);
}
public ResultSetFuture executeAsync(Statement statement, Stopwatch timer, boolean showValues) {
return executeAsync(statement, null, timer, showValues);
}
public ResultSetFuture executeAsync(Statement statement, UnitOfWork uow, boolean showValues) {
return executeAsync(statement, uow, null, showValues);
}
public ResultSetFuture executeAsync(Statement statement, UnitOfWork uow, Stopwatch timer, boolean showValues) {
try { try {
log(statement, showValues); logStatement(statement, showValues);
return currentSession().executeAsync(statement); return currentSession().executeAsync(statement);
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw translateException(e); throw translateException(e);
} }
} }
void log(Statement statement, boolean showValues) { private void logStatement(Statement statement, boolean showValues) {
if (LOG.isInfoEnabled()) {
LOG.info("Execute statement " + statement);
}
if (isShowCql()) { if (isShowCql()) {
if (statement instanceof BuiltStatement) { printCql(Operation.queryString(statement, showValues));
BuiltStatement builtStatement = (BuiltStatement) statement; } else if (LOG.isInfoEnabled()) {
if (showValues) { LOG.info("CQL> " + Operation.queryString(statement, showValues));
RegularStatement regularStatement = builtStatement.setForceNoValues(true);
printCql(regularStatement.getQueryString());
} else {
printCql(builtStatement.getQueryString());
}
} else if (statement instanceof RegularStatement) {
RegularStatement regularStatement = (RegularStatement) statement;
printCql(regularStatement.getQueryString());
} else {
printCql(statement.toString());
}
} }
} }
@ -119,7 +131,7 @@ public abstract class AbstractSessionOperations {
return null; return null;
} }
public void mergeCache(Table<String, String, Object> cache) { public void mergeCache(Table<String, String, Either<Object, List<Facet>>> uowCache) {
} }
RuntimeException translateException(RuntimeException e) { RuntimeException translateException(RuntimeException e) {
@ -139,4 +151,7 @@ public abstract class AbstractSessionOperations {
void printCql(String cql) { void printCql(String cql) {
getPrintStream().println(cql); getPrintStream().println(cql);
} }
public void cacheEvict(List<Facet> facets) {
}
} }

View file

@ -15,8 +15,11 @@
*/ */
package net.helenus.core; package net.helenus.core;
import static net.helenus.core.HelenusSession.deleted;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -29,6 +32,7 @@ import com.google.common.collect.TreeTraverser;
import net.helenus.core.cache.CacheUtil; import net.helenus.core.cache.CacheUtil;
import net.helenus.core.cache.Facet; import net.helenus.core.cache.Facet;
import net.helenus.support.Either;
/** Encapsulates the concept of a "transaction" as a unit-of-work. */ /** Encapsulates the concept of a "transaction" as a unit-of-work. */
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork<E>, AutoCloseable { public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork<E>, AutoCloseable {
@ -38,15 +42,18 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>(); private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
private final HelenusSession session; private final HelenusSession session;
private final AbstractUnitOfWork<E> parent; private final AbstractUnitOfWork<E> parent;
// Cache: private final Table<String, String, Either<Object, List<Facet>>> cache = HashBasedTable.create();
private final Table<String, String, Object> cache = HashBasedTable.create(); protected String purpose;
protected List<String> nestedPurposes = new ArrayList<String>();
protected int cacheHits = 0;
protected int cacheMisses = 0;
protected int databaseLookups = 0;
protected Stopwatch elapsedTime;
protected Map<String, Double> databaseTime = new HashMap<>();
protected double cacheLookupTime = 0.0;
private List<CommitThunk> postCommit = new ArrayList<CommitThunk>(); private List<CommitThunk> postCommit = new ArrayList<CommitThunk>();
private boolean aborted = false; private boolean aborted = false;
private boolean committed = false; private boolean committed = false;
private String purpose_;
private Stopwatch elapsedTime_;
private Stopwatch databaseTime_ = Stopwatch.createUnstarted();
private Stopwatch cacheLookupTime_ = Stopwatch.createUnstarted();
protected AbstractUnitOfWork(HelenusSession session, AbstractUnitOfWork<E> parent) { protected AbstractUnitOfWork(HelenusSession session, AbstractUnitOfWork<E> parent) {
Objects.requireNonNull(session, "containing session cannot be null"); Objects.requireNonNull(session, "containing session cannot be null");
@ -56,13 +63,18 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
} }
@Override @Override
public Stopwatch getExecutionTimer() { public void addDatabaseTime(String name, Stopwatch amount) {
return databaseTime_; Double time = databaseTime.get(name);
if (time == null) {
databaseTime.put(name, (double) amount.elapsed(TimeUnit.MICROSECONDS));
} else {
databaseTime.put(name, time + amount.elapsed(TimeUnit.MICROSECONDS));
}
} }
@Override @Override
public Stopwatch getCacheLookupTimer() { public void addCacheLookupTime(Stopwatch amount) {
return cacheLookupTime_; cacheLookupTime += amount.elapsed(TimeUnit.MICROSECONDS);
} }
@Override @Override
@ -73,26 +85,72 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
} }
@Override @Override
public UnitOfWork<E> begin() { public synchronized UnitOfWork<E> begin() {
elapsedTime_ = Stopwatch.createStarted(); if (LOG.isInfoEnabled()) {
elapsedTime = Stopwatch.createStarted();
}
// log.record(txn::start) // log.record(txn::start)
return this; return this;
} }
@Override
public String getPurpose() {
return purpose;
}
@Override @Override
public UnitOfWork setPurpose(String purpose) { public UnitOfWork setPurpose(String purpose) {
purpose_ = purpose; this.purpose = purpose;
return this; return this;
} }
public void logTimers(String what) { @Override
double e = (double) elapsedTime_.elapsed(TimeUnit.MICROSECONDS) / 1000.0; public void recordCacheAndDatabaseOperationCount(int cache, int ops) {
double d = (double) databaseTime_.elapsed(TimeUnit.MICROSECONDS) / 1000.0; if (cache > 0) {
double c = (double) cacheLookupTime_.elapsed(TimeUnit.MICROSECONDS) / 1000.0; cacheHits += cache;
double fd = (d / (e - c)) * 100.0; } else {
double fc = (c / (e - d)) * 100.0; cacheMisses += Math.abs(cache);
LOG.info(String.format("UOW(%s)%s %s (total: %.3fms cache: %.3fms %2.2f%% db: %.3fms %2.2f%%)", hashCode(), }
(purpose_ == null ? "" : " " + purpose_), what, e, c, fc, d, fd)); if (ops > 0) {
databaseLookups += ops;
}
}
public String logTimers(String what) {
double e = (double) elapsedTime.elapsed(TimeUnit.MICROSECONDS) / 1000.0;
double d = 0.0;
double c = cacheLookupTime / 1000.0;
double fc = (c / e) * 100.0;
String database = "";
if (databaseTime.size() > 0) {
List<String> dbt = new ArrayList<>(databaseTime.size());
for (String name : databaseTime.keySet()) {
double t = databaseTime.get(name) / 1000.0;
d += t;
dbt.add(String.format("%s took %,.3fms %,2.2f%%", name, t, (t / e) * 100.0));
}
double fd = (d / e) * 100.0;
database = String.format(", %d quer%s (%,.3fms %,2.2f%% - %s)", databaseLookups,
(databaseLookups > 1) ? "ies" : "y", d, fd, String.join(", ", dbt));
}
String cache = "";
if (cacheLookupTime > 0) {
int cacheLookups = cacheHits + cacheMisses;
cache = String.format(" with %d cache lookup%s (%,.3fms %,2.2f%% - %,d hit, %,d miss)", cacheLookups,
cacheLookups > 1 ? "s" : "", c, fc, cacheHits, cacheMisses);
}
String da = "";
if (databaseTime.size() > 0 || cacheLookupTime > 0) {
double dat = d + c;
double daf = (dat / e) * 100;
da = String.format(" consuming %,.3fms for data access, or %,2.2f%% of total UOW time.", dat, daf);
}
String x = nestedPurposes.stream().distinct().collect(Collectors.joining(", "));
String n = nested.stream().map(uow -> String.valueOf(uow.hashCode())).collect(Collectors.joining(", "));
String s = String.format(Locale.US, "UOW(%s%s) %s in %,.3fms%s%s%s%s%s", hashCode(),
(nested.size() > 0 ? ", [" + n + "]" : ""), what, e, cache, database, da,
(purpose == null ? "" : " " + purpose), (nestedPurposes.isEmpty()) ? "" : ", " + x);
return s;
} }
private void applyPostCommitFunctions() { private void applyPostCommitFunctions() {
@ -101,7 +159,9 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
f.apply(); f.apply();
} }
} }
logTimers("committed"); if (LOG.isInfoEnabled()) {
LOG.info(logTimers("committed"));
}
} }
@Override @Override
@ -111,15 +171,14 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
for (Facet facet : facets) { for (Facet facet : facets) {
if (!facet.fixed()) { if (!facet.fixed()) {
String columnName = facet.name() + "==" + facet.value(); String columnName = facet.name() + "==" + facet.value();
Object value = cache.get(tableName, columnName); Either<Object, List<Facet>> eitherValue = cache.get(tableName, columnName);
if (value != null) { if (eitherValue != null) {
if (result.isPresent() && result.get() != value) { Object value = deleted;
// One facet matched, but another did not. if (eitherValue.isLeft()) {
result = Optional.empty(); value = eitherValue.getLeft();
break;
} else {
result = Optional.of(value);
} }
result = Optional.of(value);
break;
} }
} }
} }
@ -133,12 +192,45 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
} }
@Override @Override
public void cacheUpdate(Object value, List<Facet> facets) { public List<Facet> cacheEvict(List<Facet> facets) {
Facet table = facets.remove(0); Either<Object, List<Facet>> deletedObjectFacets = Either.right(facets);
String tableName = table.value().toString(); String tableName = CacheUtil.schemaName(facets);
Optional<Object> optionalValue = cacheLookup(facets);
if (optionalValue.isPresent()) {
Object value = optionalValue.get();
for (Facet facet : facets) { for (Facet facet : facets) {
if (!facet.fixed()) {
String columnKey = facet.name() + "==" + facet.value();
// mark the value identified by the facet to `deleted`
cache.put(tableName, columnKey, deletedObjectFacets);
}
}
// look for other row/col pairs that referenced the same object, mark them
// `deleted`
cache.columnKeySet().forEach(columnKey -> {
Either<Object, List<Facet>> eitherCachedValue = cache.get(tableName, columnKey);
if (eitherCachedValue.isLeft()) {
Object cachedValue = eitherCachedValue.getLeft();
if (cachedValue == value) {
cache.put(tableName, columnKey, deletedObjectFacets);
String[] parts = columnKey.split("==");
facets.add(new Facet<String>(parts[0], parts[1]));
}
}
});
}
return facets;
}
@Override
public void cacheUpdate(Object value, List<Facet> facets) {
String tableName = CacheUtil.schemaName(facets);
for (Facet facet : facets) {
if (!facet.fixed()) {
String columnName = facet.name() + "==" + facet.value(); String columnName = facet.name() + "==" + facet.value();
cache.put(tableName, columnName, value); cache.put(tableName, columnName, Either.left(value));
}
} }
} }
@ -178,21 +270,37 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
aborted = false; aborted = false;
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit)); nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
elapsedTime.stop();
// Merge UOW cache into parent's cache.
if (parent != null) {
parent.mergeCache(cache);
} else {
session.mergeCache(cache);
}
elapsedTime_.stop();
// Apply all post-commit functions for
if (parent == null) { if (parent == null) {
// Apply all post-commit functions, this is the outter-most UnitOfWork.
traverser.postOrderTraversal(this).forEach(uow -> { traverser.postOrderTraversal(this).forEach(uow -> {
uow.applyPostCommitFunctions(); uow.applyPostCommitFunctions();
}); });
// Merge our cache into the session cache.
session.mergeCache(cache);
return new PostCommitFunction(this, null); return new PostCommitFunction(this, null);
} else {
// Merge cache and statistics into parent if there is one.
parent.mergeCache(cache);
if (purpose != null) {
parent.nestedPurposes.add(purpose);
}
parent.cacheHits += cacheHits;
parent.cacheMisses += cacheMisses;
parent.databaseLookups += databaseLookups;
parent.cacheLookupTime += cacheLookupTime;
for (String name : databaseTime.keySet()) {
if (parent.databaseTime.containsKey(name)) {
double t = parent.databaseTime.get(name);
parent.databaseTime.put(name, t + databaseTime.get(name));
} else {
parent.databaseTime.put(name, databaseTime.get(name));
}
}
} }
} }
// else { // else {
@ -203,7 +311,7 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
} }
/* Explicitly discard the work and mark it as as such in the log. */ /* Explicitly discard the work and mark it as as such in the log. */
public void abort() { public synchronized void abort() {
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes); TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes);
traverser.postOrderTraversal(this).forEach(uow -> { traverser.postOrderTraversal(this).forEach(uow -> {
uow.committed = false; uow.committed = false;
@ -211,18 +319,22 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
}); });
// log.record(txn::abort) // log.record(txn::abort)
// cache.invalidateSince(txn::start time) // cache.invalidateSince(txn::start time)
if (!hasAborted()) { if (LOG.isInfoEnabled()) {
elapsedTime_.stop(); if (elapsedTime.isRunning()) {
logTimers("aborted"); elapsedTime.stop();
}
LOG.info(logTimers("aborted"));
} }
} }
private void mergeCache(Table<String, String, Object> from) { private void mergeCache(Table<String, String, Either<Object, List<Facet>>> from) {
Table<String, String, Object> to = this.cache; Table<String, String, Either<Object, List<Facet>>> to = this.cache;
from.rowMap().forEach((rowKey, columnMap) -> { from.rowMap().forEach((rowKey, columnMap) -> {
columnMap.forEach((columnKey, value) -> { columnMap.forEach((columnKey, value) -> {
if (to.contains(rowKey, columnKey)) { if (to.contains(rowKey, columnKey)) {
to.put(rowKey, columnKey, CacheUtil.merge(to.get(rowKey, columnKey), from.get(rowKey, columnKey))); // TODO(gburd):...
to.put(rowKey, columnKey, Either.left(CacheUtil.merge(to.get(rowKey, columnKey).getLeft(),
from.get(rowKey, columnKey).getLeft())));
} else { } else {
to.put(rowKey, columnKey, from.get(rowKey, columnKey)); to.put(rowKey, columnKey, from.get(rowKey, columnKey));
} }

View file

@ -1,3 +1,19 @@
/*
* Copyright (C) 2015 The Helenus 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.helenus.core; package net.helenus.core;
public class ConflictingUnitOfWorkException extends Exception { public class ConflictingUnitOfWorkException extends Exception {

View file

@ -23,39 +23,38 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.*;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.datastax.driver.core.*; import com.datastax.driver.core.*;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Table; import com.google.common.collect.Table;
import brave.Tracer; import brave.Tracer;
import net.helenus.core.cache.CacheUtil; import net.helenus.core.cache.CacheUtil;
import net.helenus.core.cache.Facet; import net.helenus.core.cache.Facet;
import net.helenus.core.cache.SessionCache;
import net.helenus.core.cache.UnboundFacet; import net.helenus.core.cache.UnboundFacet;
import net.helenus.core.operation.*; import net.helenus.core.operation.*;
import net.helenus.core.reflect.Drafted; import net.helenus.core.reflect.Drafted;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.HelenusProperty;
import net.helenus.mapping.MappingUtil; import net.helenus.mapping.MappingUtil;
import net.helenus.mapping.value.*; import net.helenus.mapping.value.*;
import net.helenus.support.DslPropertyException; import net.helenus.support.*;
import net.helenus.support.Fun;
import net.helenus.support.Fun.Tuple1; import net.helenus.support.Fun.Tuple1;
import net.helenus.support.Fun.Tuple2; import net.helenus.support.Fun.Tuple2;
import net.helenus.support.Fun.Tuple6; import net.helenus.support.Fun.Tuple6;
import net.helenus.support.HelenusException;
import net.helenus.support.HelenusMappingException;
public final class HelenusSession extends AbstractSessionOperations implements Closeable { public final class HelenusSession extends AbstractSessionOperations implements Closeable {
private final int MAX_CACHE_SIZE = 10000; public static final Object deleted = new Object();
private final int MAX_CACHE_EXPIRE_SECONDS = 600; private static final Logger LOG = LoggerFactory.getLogger(HelenusSession.class);
private final Session session; private final Session session;
private final CodecRegistry registry; private final CodecRegistry registry;
@ -68,7 +67,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
private final SessionRepository sessionRepository; private final SessionRepository sessionRepository;
private final Executor executor; private final Executor executor;
private final boolean dropSchemaOnClose; private final boolean dropSchemaOnClose;
private final Cache sessionCache; private final SessionCache<String, Object> sessionCache;
private final RowColumnValueProvider valueProvider; private final RowColumnValueProvider valueProvider;
private final StatementColumnValuePreparer valuePreparer; private final StatementColumnValuePreparer valuePreparer;
private final Metadata metadata; private final Metadata metadata;
@ -78,7 +77,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
HelenusSession(Session session, String usingKeyspace, CodecRegistry registry, boolean showCql, HelenusSession(Session session, String usingKeyspace, CodecRegistry registry, boolean showCql,
PrintStream printStream, SessionRepositoryBuilder sessionRepositoryBuilder, Executor executor, PrintStream printStream, SessionRepositoryBuilder sessionRepositoryBuilder, Executor executor,
boolean dropSchemaOnClose, ConsistencyLevel consistencyLevel, boolean defaultQueryIdempotency, boolean dropSchemaOnClose, ConsistencyLevel consistencyLevel, boolean defaultQueryIdempotency,
Class<? extends UnitOfWork> unitOfWorkClass, MetricRegistry metricRegistry, Tracer tracer) { Class<? extends UnitOfWork> unitOfWorkClass, SessionCache sessionCache, MetricRegistry metricRegistry,
Tracer tracer) {
this.session = session; this.session = session;
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry; this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
this.usingKeyspace = Objects.requireNonNull(usingKeyspace, this.usingKeyspace = Objects.requireNonNull(usingKeyspace,
@ -94,8 +94,11 @@ public final class HelenusSession extends AbstractSessionOperations implements C
this.metricRegistry = metricRegistry; this.metricRegistry = metricRegistry;
this.zipkinTracer = tracer; this.zipkinTracer = tracer;
this.sessionCache = CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE) if (sessionCache == null) {
.expireAfterAccess(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS).recordStats().build(); this.sessionCache = SessionCache.<String, Object>defaultCache();
} else {
this.sessionCache = sessionCache;
}
this.valueProvider = new RowColumnValueProvider(this.sessionRepository); this.valueProvider = new RowColumnValueProvider(this.sessionRepository);
this.valuePreparer = new StatementColumnValuePreparer(this.sessionRepository); this.valuePreparer = new StatementColumnValuePreparer(this.sessionRepository);
@ -184,7 +187,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
Object result = null; Object result = null;
for (String[] combination : facetCombinations) { for (String[] combination : facetCombinations) {
String cacheKey = tableName + "." + Arrays.toString(combination); String cacheKey = tableName + "." + Arrays.toString(combination);
result = sessionCache.getIfPresent(cacheKey); result = sessionCache.get(cacheKey);
if (result != null) { if (result != null) {
return result; return result;
} }
@ -192,6 +195,16 @@ public final class HelenusSession extends AbstractSessionOperations implements C
return null; return null;
} }
@Override
public void cacheEvict(List<Facet> facets) {
String tableName = CacheUtil.schemaName(facets);
List<String[]> facetCombinations = CacheUtil.flattenFacets(facets);
for (String[] combination : facetCombinations) {
String cacheKey = tableName + "." + Arrays.toString(combination);
sessionCache.invalidate(cacheKey);
}
}
@Override @Override
public void updateCache(Object pojo, List<Facet> facets) { public void updateCache(Object pojo, List<Facet> facets) {
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null; Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
@ -200,14 +213,18 @@ public final class HelenusSession extends AbstractSessionOperations implements C
if (facet instanceof UnboundFacet) { if (facet instanceof UnboundFacet) {
UnboundFacet unboundFacet = (UnboundFacet) facet; UnboundFacet unboundFacet = (UnboundFacet) facet;
UnboundFacet.Binder binder = unboundFacet.binder(); UnboundFacet.Binder binder = unboundFacet.binder();
unboundFacet.getProperties().forEach(prop -> { for (HelenusProperty prop : unboundFacet.getProperties()) {
Object value;
if (valueMap == null) { if (valueMap == null) {
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false); value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
if (value != null) {
binder.setValueForProperty(prop, value.toString()); binder.setValueForProperty(prop, value.toString());
} else {
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
} }
}); } else {
value = valueMap.get(prop.getPropertyName());
binder.setValueForProperty(prop, value.toString());
}
}
if (binder.isBound()) { if (binder.isBound()) {
boundFacets.add(binder.bind()); boundFacets.add(binder.bind());
} }
@ -217,28 +234,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
} }
String tableName = CacheUtil.schemaName(facets); String tableName = CacheUtil.schemaName(facets);
List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets); List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets);
Object value = sessionCache.getIfPresent(pojo); mergeAndUpdateCacheValues(pojo, tableName, facetCombinations);
Object mergedValue = null;
for (String[] combination : facetCombinations) {
String cacheKey = tableName + "." + Arrays.toString(combination);
if (value == null) {
sessionCache.put(cacheKey, pojo);
} else {
if (mergedValue == null) {
mergedValue = pojo;
} else {
mergedValue = CacheUtil.merge(value, pojo);
}
sessionCache.put(mergedValue, pojo);
}
}
} }
@Override @Override
public void mergeCache(Table<String, String, Object> uowCache) { public void mergeCache(Table<String, String, Either<Object, List<Facet>>> uowCache) {
List<Object> pojos = uowCache.values().stream().distinct().collect(Collectors.toList()); List<Object> items = uowCache.values().stream().filter(Either::isLeft).map(Either::getLeft).distinct()
for (Object pojo : pojos) { .collect(Collectors.toList());
for (Object pojo : items) {
HelenusEntity entity = Helenus.resolve(MappingUtil.getMappingInterface(pojo)); HelenusEntity entity = Helenus.resolve(MappingUtil.getMappingInterface(pojo));
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null; Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
if (entity.isCacheable()) { if (entity.isCacheable()) {
@ -249,7 +252,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
UnboundFacet.Binder binder = unboundFacet.binder(); UnboundFacet.Binder binder = unboundFacet.binder();
unboundFacet.getProperties().forEach(prop -> { unboundFacet.getProperties().forEach(prop -> {
if (valueMap == null) { if (valueMap == null) {
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false); Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
binder.setValueForProperty(prop, value.toString()); binder.setValueForProperty(prop, value.toString());
} else { } else {
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString()); binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
@ -262,24 +265,39 @@ public final class HelenusSession extends AbstractSessionOperations implements C
boundFacets.add(facet); boundFacets.add(facet);
} }
} }
String tableName = entity.getName().toCql();
// NOTE: should equal `String tableName = CacheUtil.schemaName(facets);` // NOTE: should equal `String tableName = CacheUtil.schemaName(facets);`
List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets); List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets);
Object value = sessionCache.getIfPresent(pojo); String tableName = CacheUtil.schemaName(boundFacets);
Object mergedValue = null; mergeAndUpdateCacheValues(pojo, tableName, facetCombinations);
}
}
List<List<Facet>> deletedFacetSets = uowCache.values().stream().filter(Either::isRight).map(Either::getRight)
.collect(Collectors.toList());
for (List<Facet> facets : deletedFacetSets) {
String tableName = CacheUtil.schemaName(facets);
List<String[]> combinations = CacheUtil.flattenFacets(facets);
for (String[] combination : combinations) {
String cacheKey = tableName + "." + Arrays.toString(combination);
sessionCache.invalidate(cacheKey);
}
}
}
private void mergeAndUpdateCacheValues(Object pojo, String tableName, List<String[]> facetCombinations) {
Object merged = null;
for (String[] combination : facetCombinations) { for (String[] combination : facetCombinations) {
String cacheKey = tableName + "." + Arrays.toString(combination); String cacheKey = tableName + "." + Arrays.toString(combination);
Object value = sessionCache.get(cacheKey);
if (value == null) { if (value == null) {
sessionCache.put(cacheKey, pojo); sessionCache.put(cacheKey, pojo);
} else { } else {
if (mergedValue == null) { if (merged == null) {
mergedValue = pojo; merged = pojo;
} else { } else {
mergedValue = CacheUtil.merge(value, pojo); merged = CacheUtil.merge(value, pojo);
}
sessionCache.put(mergedValue, pojo);
}
} }
sessionCache.put(cacheKey, merged);
} }
} }
} }
@ -288,8 +306,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
return metadata; return metadata;
} }
public synchronized UnitOfWork begin() { public UnitOfWork begin() {
return begin(null); return this.begin(null);
} }
public synchronized UnitOfWork begin(UnitOfWork parent) { public synchronized UnitOfWork begin(UnitOfWork parent) {
@ -297,6 +315,20 @@ public final class HelenusSession extends AbstractSessionOperations implements C
Class<? extends UnitOfWork> clazz = unitOfWorkClass; Class<? extends UnitOfWork> clazz = unitOfWorkClass;
Constructor<? extends UnitOfWork> ctor = clazz.getConstructor(HelenusSession.class, UnitOfWork.class); Constructor<? extends UnitOfWork> ctor = clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
UnitOfWork uow = ctor.newInstance(this, parent); UnitOfWork uow = ctor.newInstance(this, parent);
if (LOG.isInfoEnabled() && uow.getPurpose() == null) {
StringBuilder purpose = null;
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
int frame = 2;
if (trace[2].getMethodName().equals("begin")) {
frame = 3;
} else if (trace[2].getClassName().equals(unitOfWorkClass.getName())) {
frame = 3;
}
purpose = new StringBuilder().append(trace[frame].getClassName()).append(".")
.append(trace[frame].getMethodName()).append("(").append(trace[frame].getFileName()).append(":")
.append(trace[frame].getLineNumber()).append(")");
uow.setPurpose(purpose.toString());
}
if (parent != null) { if (parent != null) {
parent.addNestedUnitOfWork(uow); parent.addNestedUnitOfWork(uow);
} }
@ -470,6 +502,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
return new UpdateOperation<ResultSet>(this); return new UpdateOperation<ResultSet>(this);
} }
public <E> UpdateOperation<E> update(Object pojo) {
if (pojo instanceof MapExportable == false) {
throw new HelenusMappingException(
"update of objects that don't implement MapExportable is not yet supported");
}
return new UpdateOperation<E>(this, pojo);
}
public <E> UpdateOperation<E> update(Drafted<E> drafted) { public <E> UpdateOperation<E> update(Drafted<E> drafted) {
if (drafted instanceof AbstractEntityDraft == false) { if (drafted instanceof AbstractEntityDraft == false) {
throw new HelenusMappingException( throw new HelenusMappingException(

View file

@ -27,6 +27,7 @@ import com.datastax.driver.core.*;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import brave.Tracer; import brave.Tracer;
import net.helenus.core.cache.SessionCache;
import net.helenus.core.reflect.DslExportable; import net.helenus.core.reflect.DslExportable;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.HelenusEntityType; import net.helenus.mapping.HelenusEntityType;
@ -56,6 +57,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
private boolean dropUnusedIndexes = false; private boolean dropUnusedIndexes = false;
private KeyspaceMetadata keyspaceMetadata; private KeyspaceMetadata keyspaceMetadata;
private AutoDdl autoDdl = AutoDdl.UPDATE; private AutoDdl autoDdl = AutoDdl.UPDATE;
private SessionCache sessionCache = null;
SessionInitializer(Session session) { SessionInitializer(Session session) {
this.session = Objects.requireNonNull(session, "empty session"); this.session = Objects.requireNonNull(session, "empty session");
@ -123,6 +125,11 @@ public final class SessionInitializer extends AbstractSessionOperations {
return this; return this;
} }
public SessionInitializer setSessionCache(SessionCache sessionCache) {
this.sessionCache = sessionCache;
return this;
}
public ConsistencyLevel getDefaultConsistencyLevel() { public ConsistencyLevel getDefaultConsistencyLevel() {
return consistencyLevel; return consistencyLevel;
} }
@ -243,8 +250,8 @@ public final class SessionInitializer extends AbstractSessionOperations {
public synchronized HelenusSession get() { public synchronized HelenusSession get() {
initialize(); initialize();
return new HelenusSession(session, usingKeyspace, registry, showCql, printStream, sessionRepository, executor, return new HelenusSession(session, usingKeyspace, registry, showCql, printStream, sessionRepository, executor,
autoDdl == AutoDdl.CREATE_DROP, consistencyLevel, idempotent, unitOfWorkClass, metricRegistry, autoDdl == AutoDdl.CREATE_DROP, consistencyLevel, idempotent, unitOfWorkClass, sessionCache,
zipkinTracer); metricRegistry, zipkinTracer);
} }
private void initialize() { private void initialize() {

View file

@ -25,8 +25,8 @@ import net.helenus.core.cache.Facet;
public interface UnitOfWork<X extends Exception> extends AutoCloseable { public interface UnitOfWork<X extends Exception> extends AutoCloseable {
/** /**
* Marks the beginning of a transactional section of work. Will write a record * Marks the beginning of a transactional section of work. Will write a
* to the shared write-ahead log. * recordCacheAndDatabaseOperationCount to the shared write-ahead log.
* *
* @return the handle used to commit or abort the work. * @return the handle used to commit or abort the work.
*/ */
@ -59,10 +59,15 @@ public interface UnitOfWork<X extends Exception> extends AutoCloseable {
void cacheUpdate(Object pojo, List<Facet> facets); void cacheUpdate(Object pojo, List<Facet> facets);
List<Facet> cacheEvict(List<Facet> facets);
String getPurpose();
UnitOfWork setPurpose(String purpose); UnitOfWork setPurpose(String purpose);
Stopwatch getExecutionTimer(); void addDatabaseTime(String name, Stopwatch amount);
void addCacheLookupTime(Stopwatch amount);
Stopwatch getCacheLookupTimer(); // Cache > 0 means "cache hit", < 0 means cache miss.
void recordCacheAndDatabaseOperationCount(int cache, int database);
} }

View file

@ -1,9 +1,26 @@
/*
* Copyright (C) 2015 The Helenus 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.helenus.core.annotation; package net.helenus.core.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.concurrent.TimeoutException;
import net.helenus.core.ConflictingUnitOfWorkException; import net.helenus.core.ConflictingUnitOfWorkException;
@ -11,7 +28,7 @@ import net.helenus.core.ConflictingUnitOfWorkException;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface Retry { public @interface Retry {
Class<? extends Exception>[] on() default ConflictingUnitOfWorkException.class; Class<? extends Exception>[] on() default {ConflictingUnitOfWorkException.class, TimeoutException.class};
int times() default 3; int times() default 3;
} }

View file

@ -1,3 +1,19 @@
/*
* Copyright (C) 2015 The Helenus 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.helenus.core.aspect; package net.helenus.core.aspect;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -73,7 +89,7 @@ public class RetryAspect {
return retryAnnotation; return retryAnnotation;
} }
Class[] argClasses = new Class[pjp.getArgs().length]; Class<?>[] argClasses = new Class[pjp.getArgs().length];
for (int i = 0; i < pjp.getArgs().length; i++) { for (int i = 0; i < pjp.getArgs().length; i++) {
argClasses[i] = pjp.getArgs()[i].getClass(); argClasses[i] = pjp.getArgs()[i].getClass();
} }

View file

@ -15,6 +15,7 @@
*/ */
package net.helenus.core.cache; package net.helenus.core.cache;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -23,7 +24,13 @@ import net.helenus.mapping.HelenusProperty;
public class BoundFacet extends Facet<String> { public class BoundFacet extends Facet<String> {
private final Map<HelenusProperty, Object> properties; private final Map<HelenusProperty, Object> properties;
BoundFacet(String name, Map<HelenusProperty, Object> properties) { public BoundFacet(HelenusProperty property, Object value) {
super(property.getPropertyName(), value == null ? null : value.toString());
this.properties = new HashMap<HelenusProperty, Object>(1);
this.properties.put(property, value);
}
public BoundFacet(String name, Map<HelenusProperty, Object> properties) {
super(name, super(name,
(properties.keySet().size() > 1) (properties.keySet().size() > 1)
? "[" + String.join(", ", ? "[" + String.join(", ",

View file

@ -38,7 +38,22 @@ public class CacheUtil {
} }
public static Object merge(Object to, Object from) { public static Object merge(Object to, Object from) {
return to; // TODO(gburd): yeah... if (to == from) {
return to;
} else {
return from;
}
/*
* // TODO(gburd): take ttl and writeTime into account when merging. Map<String,
* Object> toValueMap = to instanceof MapExportable ? ((MapExportable)
* to).toMap() : null; Map<String, Object> fromValueMap = to instanceof
* MapExportable ? ((MapExportable) from).toMap() : null;
*
* if (toValueMap != null && fromValueMap != null) { for (String key :
* fromValueMap.keySet()) { if (toValueMap.containsKey(key) &&
* toValueMap.get(key) != fromValueMap.get(key)) { toValueMap.put(key,
* fromValueMap.get(key)); } } } return to;
*/
} }
public static String schemaName(List<Facet> facets) { public static String schemaName(List<Facet> facets) {

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2015 The Helenus 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.helenus.core.cache;
import com.google.common.cache.Cache;
public class GuavaCache<K, V> implements SessionCache<K, V> {
final Cache<K, V> cache;
GuavaCache(Cache<K, V> cache) {
this.cache = cache;
}
@Override
public void invalidate(K key) {
cache.invalidate(key);
}
@Override
public V get(K key) {
return cache.getIfPresent(key);
}
@Override
public void put(K key, V value) {
cache.put(key, value);
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2015 The Helenus 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.helenus.core.cache;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.CacheBuilder;
public interface SessionCache<K, V> {
static <K, V> SessionCache<K, V> defaultCache() {
int MAX_CACHE_SIZE = 10000;
int MAX_CACHE_EXPIRE_SECONDS = 600;
return new GuavaCache<K, V>(CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE)
.expireAfterAccess(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS)
.expireAfterWrite(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS).recordStats().build());
}
void invalidate(K key);
V get(K key);
void put(K key, V value);
}

View file

@ -15,10 +15,12 @@
*/ */
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.LinkedList; import java.util.*;
import java.util.List;
import net.helenus.core.*; import net.helenus.core.*;
import net.helenus.core.cache.Facet;
import net.helenus.core.cache.UnboundFacet;
import net.helenus.mapping.HelenusProperty;
public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperation<E, O>> public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperation<E, O>>
extends extends
@ -107,4 +109,39 @@ public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperati
} }
ifFilters.add(filter); ifFilters.add(filter);
} }
protected List<Facet> bindFacetValues(List<Facet> facets) {
if (facets == null) {
return new ArrayList<Facet>();
}
List<Facet> boundFacets = new ArrayList<>();
Map<HelenusProperty, Filter> filterMap = new HashMap<>(filters.size());
filters.forEach(f -> filterMap.put(f.getNode().getProperty(), f));
for (Facet facet : facets) {
if (facet instanceof UnboundFacet) {
UnboundFacet unboundFacet = (UnboundFacet) facet;
UnboundFacet.Binder binder = unboundFacet.binder();
if (filters != null) {
for (HelenusProperty prop : unboundFacet.getProperties()) {
Filter filter = filterMap.get(prop);
if (filter != null) {
Object[] postulates = filter.postulateValues();
for (Object p : postulates) {
binder.setValueForProperty(prop, p.toString());
}
}
}
}
if (binder.isBound()) {
boundFacets.add(binder.bind());
}
} else {
boundFacets.add(facet);
}
}
return boundFacets;
}
} }

View file

@ -16,6 +16,8 @@
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeoutException;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
@ -31,15 +33,11 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
public abstract E transform(ResultSet resultSet); public abstract E transform(ResultSet resultSet);
public boolean cacheable() {
return false;
}
public PreparedOperation<E> prepare() { public PreparedOperation<E> prepare() {
return new PreparedOperation<E>(prepareStatement(), this); return new PreparedOperation<E>(prepareStatement(), this);
} }
public E sync() {// throws TimeoutException { public E sync() throws TimeoutException {
final Timer.Context context = requestLatency.time(); final Timer.Context context = requestLatency.time();
try { try {
ResultSet resultSet = this.execute(sessionOps, null, traceContext, queryExecutionTimeout, queryTimeoutUnits, ResultSet resultSet = this.execute(sessionOps, null, traceContext, queryExecutionTimeout, queryTimeoutUnits,
@ -50,7 +48,7 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
} }
} }
public E sync(UnitOfWork uow) {// throws TimeoutException { public E sync(UnitOfWork uow) throws TimeoutException {
if (uow == null) if (uow == null)
return sync(); return sync();
@ -67,11 +65,11 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
public CompletableFuture<E> async() { public CompletableFuture<E> async() {
return CompletableFuture.<E>supplyAsync(() -> { return CompletableFuture.<E>supplyAsync(() -> {
// try { try {
return sync(); return sync();
// } catch (TimeoutException ex) { } catch (TimeoutException ex) {
// throw new CompletionException(ex); throw new CompletionException(ex);
// } }
}); });
} }
@ -79,11 +77,11 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
if (uow == null) if (uow == null)
return async(); return async();
return CompletableFuture.<E>supplyAsync(() -> { return CompletableFuture.<E>supplyAsync(() -> {
// try { try {
return sync(); return sync();
// } catch (TimeoutException ex) { } catch (TimeoutException ex) {
// throw new CompletionException(ex); throw new CompletionException(ex);
// } }
}); });
} }
} }

View file

@ -15,9 +15,13 @@
*/ */
package net.helenus.core.operation; package net.helenus.core.operation;
import static net.helenus.core.HelenusSession.deleted;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeoutException;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.PreparedStatement;
@ -57,20 +61,25 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
}); });
} }
public Optional<E> sync() {// throws TimeoutException { public Optional<E> sync() throws TimeoutException {
final Timer.Context context = requestLatency.time(); final Timer.Context context = requestLatency.time();
try { try {
Optional<E> result = Optional.empty(); Optional<E> result = Optional.empty();
E cacheResult = null; E cacheResult = null;
boolean updateCache = isSessionCacheable(); boolean updateCache = isSessionCacheable() && checkCache;
if (enableCache && isSessionCacheable()) { if (checkCache && isSessionCacheable()) {
List<Facet> facets = bindFacetValues(); List<Facet> facets = bindFacetValues();
String tableName = CacheUtil.schemaName(facets); String tableName = CacheUtil.schemaName(facets);
cacheResult = (E) sessionOps.checkCache(tableName, facets); cacheResult = (E) sessionOps.checkCache(tableName, facets);
if (cacheResult != null) { if (cacheResult != null) {
result = Optional.of(cacheResult); result = Optional.of(cacheResult);
updateCache = false; updateCache = false;
sessionCacheHits.mark();
cacheHits.mark();
} else {
sessionCacheMiss.mark();
cacheMiss.mark();
} }
} }
@ -95,7 +104,7 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
} }
} }
public Optional<E> sync(UnitOfWork<?> uow) {// throws TimeoutException { public Optional<E> sync(UnitOfWork<?> uow) throws TimeoutException {
if (uow == null) if (uow == null)
return sync(); return sync();
@ -103,30 +112,59 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
try { try {
Optional<E> result = Optional.empty(); Optional<E> result = Optional.empty();
E cacheResult = null; E cachedResult = null;
boolean updateCache = true; final boolean updateCache;
if (enableCache) { if (checkCache) {
Stopwatch timer = uow.getCacheLookupTimer(); Stopwatch timer = Stopwatch.createStarted();
timer.start(); try {
List<Facet> facets = bindFacetValues(); List<Facet> facets = bindFacetValues();
cacheResult = checkCache(uow, facets); if (facets != null) {
if (cacheResult != null) { cachedResult = checkCache(uow, facets);
result = Optional.of(cacheResult); if (cachedResult != null) {
updateCache = false; updateCache = false;
result = Optional.of(cachedResult);
uowCacheHits.mark();
cacheHits.mark();
uow.recordCacheAndDatabaseOperationCount(1, 0);
} else { } else {
updateCache = true;
uowCacheMiss.mark();
if (isSessionCacheable()) { if (isSessionCacheable()) {
String tableName = CacheUtil.schemaName(facets); String tableName = CacheUtil.schemaName(facets);
cacheResult = (E) sessionOps.checkCache(tableName, facets); cachedResult = (E) sessionOps.checkCache(tableName, facets);
if (cacheResult != null) { if (cachedResult != null) {
result = Optional.of(cacheResult); result = Optional.of(cachedResult);
sessionCacheHits.mark();
cacheHits.mark();
uow.recordCacheAndDatabaseOperationCount(1, 0);
} else {
sessionCacheMiss.mark();
cacheMiss.mark();
uow.recordCacheAndDatabaseOperationCount(-1, 0);
} }
} }
} }
} else {
updateCache = false;
}
} finally {
timer.stop(); timer.stop();
uow.addCacheLookupTime(timer);
}
} else {
updateCache = false;
} }
if (!result.isPresent()) { // Check to see if we fetched the object from the cache
if (result.isPresent()) {
// If we fetched the `deleted` object then the result is null (really
// Optional.empty()).
if (result.get() == deleted) {
result = Optional.empty();
}
} else {
// Formulate the query and execute it against the Cassandra cluster. // Formulate the query and execute it against the Cassandra cluster.
ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits, ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits,
showValues, true); showValues, true);
@ -136,10 +174,9 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
} }
// If we have a result, it wasn't from the UOW cache, and we're caching things // If we have a result, it wasn't from the UOW cache, and we're caching things
// then we // then we need to put this result into the cache for future requests to find.
// need to put this result into the cache for future requests to find. if (updateCache && result.isPresent() && result.get() != deleted) {
if (updateCache && result.isPresent()) { cacheUpdate(uow, result.get(), getFacets());
updateCache(uow, result.get(), getFacets());
} }
return result; return result;
@ -150,11 +187,11 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
public CompletableFuture<Optional<E>> async() { public CompletableFuture<Optional<E>> async() {
return CompletableFuture.<Optional<E>>supplyAsync(() -> { return CompletableFuture.<Optional<E>>supplyAsync(() -> {
// try { try {
return sync(); return sync();
// } catch (TimeoutException ex) { } catch (TimeoutException ex) {
// throw new CompletionException(ex); throw new CompletionException(ex);
// } }
}); });
} }
@ -162,11 +199,11 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
if (uow == null) if (uow == null)
return async(); return async();
return CompletableFuture.<Optional<E>>supplyAsync(() -> { return CompletableFuture.<Optional<E>>supplyAsync(() -> {
// try { try {
return sync(); return sync();
// } catch (TimeoutException ex) { } catch (TimeoutException ex) {
// throw new CompletionException(ex); throw new CompletionException(ex);
// } }
}); });
} }
} }

View file

@ -21,9 +21,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.RegularStatement; import com.datastax.driver.core.RegularStatement;
@ -42,14 +39,13 @@ import net.helenus.core.UnitOfWork;
import net.helenus.core.cache.Facet; import net.helenus.core.cache.Facet;
import net.helenus.core.cache.UnboundFacet; import net.helenus.core.cache.UnboundFacet;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.HelenusProperty;
import net.helenus.mapping.value.BeanColumnValueProvider; import net.helenus.mapping.value.BeanColumnValueProvider;
import net.helenus.support.HelenusException; import net.helenus.support.HelenusException;
public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> extends Operation<E> { public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> extends Operation<E> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractStatementOperation.class); protected boolean checkCache = true;
protected boolean enableCache = true;
protected boolean showValues = true; protected boolean showValues = true;
protected TraceContext traceContext; protected TraceContext traceContext;
long queryExecutionTimeout = 10; long queryExecutionTimeout = 10;
@ -70,13 +66,13 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
public abstract Statement buildStatement(boolean cached); public abstract Statement buildStatement(boolean cached);
public O ignoreCache(boolean enabled) { public O uncached(boolean enabled) {
enableCache = enabled; checkCache = enabled;
return (O) this; return (O) this;
} }
public O ignoreCache() { public O uncached() {
enableCache = true; checkCache = false;
return (O) this; return (O) this;
} }
@ -326,21 +322,14 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
if (!facets.isEmpty()) { if (!facets.isEmpty()) {
optionalCachedResult = uow.cacheLookup(facets); optionalCachedResult = uow.cacheLookup(facets);
if (optionalCachedResult.isPresent()) { if (optionalCachedResult.isPresent()) {
uowCacheHits.mark();
LOG.info("UnitOfWork({}) cache hit using facets", uow.hashCode());
result = (E) optionalCachedResult.get(); result = (E) optionalCachedResult.get();
} }
} }
if (result == null) {
uowCacheMiss.mark();
LOG.info("UnitOfWork({}) cache miss", uow.hashCode());
}
return result; return result;
} }
protected void updateCache(UnitOfWork<?> uow, E pojo, List<Facet> identifyingFacets) { protected void cacheUpdate(UnitOfWork<?> uow, E pojo, List<Facet> identifyingFacets) {
List<Facet> facets = new ArrayList<>(); List<Facet> facets = new ArrayList<>();
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null; Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
@ -348,15 +337,23 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
if (facet instanceof UnboundFacet) { if (facet instanceof UnboundFacet) {
UnboundFacet unboundFacet = (UnboundFacet) facet; UnboundFacet unboundFacet = (UnboundFacet) facet;
UnboundFacet.Binder binder = unboundFacet.binder(); UnboundFacet.Binder binder = unboundFacet.binder();
unboundFacet.getProperties().forEach(prop -> { for (HelenusProperty prop : unboundFacet.getProperties()) {
Object value;
if (valueMap == null) { if (valueMap == null) {
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false); value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
if (value != null) {
binder.setValueForProperty(prop, value.toString()); binder.setValueForProperty(prop, value.toString());
} else {
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
} }
} else {
value = valueMap.get(prop.getPropertyName());
if (value != null) {
binder.setValueForProperty(prop, value.toString());
}
}
}
if (binder.isBound()) {
facets.add(binder.bind()); facets.add(binder.bind());
}); }
} else { } else {
facets.add(facet); facets.add(facet);
} }

View file

@ -15,9 +15,13 @@
*/ */
package net.helenus.core.operation; package net.helenus.core.operation;
import static net.helenus.core.HelenusSession.deleted;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeoutException;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
@ -58,20 +62,25 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
}); });
} }
public Stream<E> sync() {// throws TimeoutException { public Stream<E> sync() throws TimeoutException {
final Timer.Context context = requestLatency.time(); final Timer.Context context = requestLatency.time();
try { try {
Stream<E> resultStream = null; Stream<E> resultStream = null;
E cacheResult = null; E cacheResult = null;
boolean updateCache = isSessionCacheable(); boolean updateCache = isSessionCacheable();
if (enableCache && isSessionCacheable()) { if (checkCache && isSessionCacheable()) {
List<Facet> facets = bindFacetValues(); List<Facet> facets = bindFacetValues();
String tableName = CacheUtil.schemaName(facets); String tableName = CacheUtil.schemaName(facets);
cacheResult = (E) sessionOps.checkCache(tableName, facets); cacheResult = (E) sessionOps.checkCache(tableName, facets);
if (cacheResult != null) { if (cacheResult != null) {
resultStream = Stream.of(cacheResult); resultStream = Stream.of(cacheResult);
updateCache = false; updateCache = false;
sessionCacheHits.mark();
cacheHits.mark();
} else {
sessionCacheMiss.mark();
cacheMiss.mark();
} }
} }
@ -102,7 +111,7 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
} }
} }
public Stream<E> sync(UnitOfWork<?> uow) {// throws TimeoutException { public Stream<E> sync(UnitOfWork uow) throws TimeoutException {
if (uow == null) if (uow == null)
return sync(); return sync();
@ -110,20 +119,50 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
try { try {
Stream<E> resultStream = null; Stream<E> resultStream = null;
E cachedResult = null; E cachedResult = null;
boolean updateCache = true; final boolean updateCache;
if (enableCache) { if (checkCache) {
Stopwatch timer = uow.getCacheLookupTimer(); Stopwatch timer = Stopwatch.createStarted();
timer.start(); try {
List<Facet> facets = bindFacetValues(); List<Facet> facets = bindFacetValues();
if (facets != null) {
cachedResult = checkCache(uow, facets); cachedResult = checkCache(uow, facets);
if (cachedResult != null) { if (cachedResult != null) {
updateCache = false;
resultStream = Stream.of(cachedResult); resultStream = Stream.of(cachedResult);
uowCacheHits.mark();
cacheHits.mark();
uow.recordCacheAndDatabaseOperationCount(1, 0);
} else {
updateCache = true;
uowCacheMiss.mark();
if (isSessionCacheable()) {
String tableName = CacheUtil.schemaName(facets);
cachedResult = (E) sessionOps.checkCache(tableName, facets);
if (cachedResult != null) {
resultStream = Stream.of(cachedResult);
sessionCacheHits.mark();
cacheHits.mark();
uow.recordCacheAndDatabaseOperationCount(1, 0);
} else {
sessionCacheMiss.mark();
cacheMiss.mark();
uow.recordCacheAndDatabaseOperationCount(-1, 0);
}
}
}
} else {
updateCache = false; updateCache = false;
} }
} finally {
timer.stop(); timer.stop();
uow.addCacheLookupTime(timer);
}
} else {
updateCache = false;
} }
// Check to see if we fetched the object from the cache
if (resultStream == null) { if (resultStream == null) {
ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits, ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits,
showValues, true); showValues, true);
@ -132,12 +171,16 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
// If we have a result and we're caching then we need to put it into the cache // If we have a result and we're caching then we need to put it into the cache
// for future requests to find. // for future requests to find.
if (updateCache && resultStream != null) { if (resultStream != null) {
List<E> again = new ArrayList<>(); List<E> again = new ArrayList<>();
List<Facet> facets = getFacets(); List<Facet> facets = getFacets();
resultStream.forEach(result -> { resultStream.forEach(result -> {
updateCache(uow, result, facets); if (result != deleted) {
if (updateCache) {
cacheUpdate(uow, result, facets);
}
again.add(result); again.add(result);
}
}); });
resultStream = again.stream(); resultStream = again.stream();
} }
@ -150,23 +193,23 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
public CompletableFuture<Stream<E>> async() { public CompletableFuture<Stream<E>> async() {
return CompletableFuture.<Stream<E>>supplyAsync(() -> { return CompletableFuture.<Stream<E>>supplyAsync(() -> {
// try { try {
return sync(); return sync();
// } catch (TimeoutException ex) { } catch (TimeoutException ex) {
// throw new CompletionException(ex); throw new CompletionException(ex);
// } }
}); });
} }
public CompletableFuture<Stream<E>> async(UnitOfWork<?> uow) { public CompletableFuture<Stream<E>> async(UnitOfWork uow) {
if (uow == null) if (uow == null)
return async(); return async();
return CompletableFuture.<Stream<E>>supplyAsync(() -> { return CompletableFuture.<Stream<E>>supplyAsync(() -> {
// try { try {
return sync(); return sync();
// } catch (TimeoutException ex) { } catch (TimeoutException ex) {
// throw new CompletionException(ex); throw new CompletionException(ex);
// } }
}); });
} }
} }

View file

@ -15,6 +15,9 @@
*/ */
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.List;
import java.util.concurrent.TimeoutException;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.datastax.driver.core.querybuilder.Delete; import com.datastax.driver.core.querybuilder.Delete;
@ -23,6 +26,8 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
import net.helenus.core.AbstractSessionOperations; import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.Filter; import net.helenus.core.Filter;
import net.helenus.core.UnitOfWork;
import net.helenus.core.cache.Facet;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
import net.helenus.support.HelenusMappingException; import net.helenus.support.HelenusMappingException;
@ -122,4 +127,33 @@ public final class DeleteOperation extends AbstractFilterOperation<ResultSet, De
+ entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface()); + entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface());
} }
} }
public List<Facet> bindFacetValues() {
return bindFacetValues(getFacets());
}
@Override
public ResultSet sync() throws TimeoutException {
ResultSet result = super.sync();
if (entity.isCacheable()) {
sessionOps.cacheEvict(bindFacetValues());
}
return result;
}
@Override
public ResultSet sync(UnitOfWork uow) throws TimeoutException {
if (uow == null) {
return sync();
}
ResultSet result = super.sync(uow);
uow.cacheEvict(bindFacetValues());
return result;
}
@Override
public List<Facet> getFacets() {
return entity.getFacets();
}
} }

View file

@ -16,6 +16,7 @@
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeoutException;
import java.util.function.Function; import java.util.function.Function;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
@ -27,6 +28,7 @@ import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.Getter; import net.helenus.core.Getter;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
import net.helenus.core.cache.Facet;
import net.helenus.core.reflect.DefaultPrimitiveTypes; import net.helenus.core.reflect.DefaultPrimitiveTypes;
import net.helenus.core.reflect.Drafted; import net.helenus.core.reflect.Drafted;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
@ -235,15 +237,38 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
} }
@Override @Override
public T sync(UnitOfWork uow) {// throws TimeoutException { public T sync() throws TimeoutException {
T result = super.sync();
if (entity.isCacheable() && result != null) {
sessionOps.updateCache(result, entity.getFacets());
}
return result;
}
@Override
public T sync(UnitOfWork uow) throws TimeoutException {
if (uow == null) { if (uow == null) {
return sync(); return sync();
} }
T result = super.sync(uow); T result = super.sync(uow);
Class<?> iface = entity.getMappingInterface(); Class<?> iface = entity.getMappingInterface();
if (resultType == iface) { if (resultType == iface) {
updateCache(uow, result, entity.getFacets()); cacheUpdate(uow, result, entity.getFacets());
} else {
if (entity.isCacheable()) {
sessionOps.cacheEvict(bindFacetValues());
}
} }
return result; return result;
} }
@Override
public List<Facet> getFacets() {
if (entity != null) {
return entity.getFacets();
} else {
return new ArrayList<Facet>();
}
}
} }

View file

@ -15,15 +15,22 @@
*/ */
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.Meter; import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
import com.datastax.driver.core.RegularStatement;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture; import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Statement; import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import brave.Span; import brave.Span;
@ -35,21 +42,54 @@ import net.helenus.core.cache.Facet;
public abstract class Operation<E> { public abstract class Operation<E> {
private static final Logger LOG = LoggerFactory.getLogger(Operation.class);
protected final AbstractSessionOperations sessionOps; protected final AbstractSessionOperations sessionOps;
protected final Meter uowCacheHits; protected final Meter uowCacheHits;
protected final Meter uowCacheMiss; protected final Meter uowCacheMiss;
protected final Meter sessionCacheHits;
protected final Meter sessionCacheMiss;
protected final Meter cacheHits;
protected final Meter cacheMiss;
protected final Timer requestLatency; protected final Timer requestLatency;
Operation(AbstractSessionOperations sessionOperations) { Operation(AbstractSessionOperations sessionOperations) {
this.sessionOps = sessionOperations; this.sessionOps = sessionOperations;
MetricRegistry metrics = sessionOperations.getMetricRegistry(); MetricRegistry metrics = sessionOperations.getMetricRegistry();
if (metrics == null) {
metrics = new MetricRegistry();
}
this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits"); this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss"); this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
this.sessionCacheHits = metrics.meter("net.helenus.session-cache-hits");
this.sessionCacheMiss = metrics.meter("net.helenus.session-cache-miss");
this.cacheHits = metrics.meter("net.helenus.cache-hits");
this.cacheMiss = metrics.meter("net.helenus.cache-miss");
this.requestLatency = metrics.timer("net.helenus.request-latency"); this.requestLatency = metrics.timer("net.helenus.request-latency");
} }
public static String queryString(Statement statement, boolean includeValues) {
String query = null;
if (statement instanceof BuiltStatement) {
BuiltStatement builtStatement = (BuiltStatement) statement;
if (includeValues) {
RegularStatement regularStatement = builtStatement.setForceNoValues(true);
query = regularStatement.getQueryString();
} else {
query = builtStatement.getQueryString();
}
} else if (statement instanceof RegularStatement) {
RegularStatement regularStatement = (RegularStatement) statement;
query = regularStatement.getQueryString();
} else {
query = statement.toString();
}
return query;
}
public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, long timeout, public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, long timeout,
TimeUnit units, boolean showValues, boolean cached) { // throws TimeoutException { TimeUnit units, boolean showValues, boolean cached) throws TimeoutException {
// Start recording in a Zipkin sub-span our execution time to perform this // Start recording in a Zipkin sub-span our execution time to perform this
// operation. // operation.
@ -67,19 +107,21 @@ public abstract class Operation<E> {
} }
Statement statement = options(buildStatement(cached)); Statement statement = options(buildStatement(cached));
Stopwatch timer = null; Stopwatch timer = Stopwatch.createStarted();
if (uow != null) { try {
timer = uow.getExecutionTimer(); ResultSetFuture futureResultSet = session.executeAsync(statement, uow, timer, showValues);
timer.start();
}
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
ResultSet resultSet = futureResultSet.getUninterruptibly(); // TODO(gburd): (timeout, units);
if (uow != null) if (uow != null)
timer.stop(); uow.recordCacheAndDatabaseOperationCount(0, 1);
ResultSet resultSet = futureResultSet.getUninterruptibly(timeout, units);
return resultSet; return resultSet;
} finally {
timer.stop();
if (uow != null)
uow.addDatabaseTime("Cassandra", timer);
log(statement, uow, timer, showValues);
}
} finally { } finally {
if (span != null) { if (span != null) {
@ -88,6 +130,20 @@ public abstract class Operation<E> {
} }
} }
void log(Statement statement, UnitOfWork uow, Stopwatch timer, boolean showValues) {
if (LOG.isInfoEnabled()) {
String uowString = "";
if (uow != null) {
uowString = "UOW(" + uow.hashCode() + ")";
}
String timerString = "";
if (timer != null) {
timerString = String.format(" %s ", timer.toString());
}
LOG.info(String.format("%s%s%s", uowString, timerString, Operation.queryString(statement, false)));
}
}
public Statement options(Statement statement) { public Statement options(Statement statement) {
return statement; return statement;
} }
@ -97,7 +153,7 @@ public abstract class Operation<E> {
} }
public List<Facet> getFacets() { public List<Facet> getFacets() {
return null; return new ArrayList<Facet>();
} }
public List<Facet> bindFacetValues() { public List<Facet> bindFacetValues() {

View file

@ -38,6 +38,7 @@ import net.helenus.core.cache.Facet;
import net.helenus.core.cache.UnboundFacet; import net.helenus.core.cache.UnboundFacet;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.HelenusProperty;
import net.helenus.mapping.MappingUtil; import net.helenus.mapping.MappingUtil;
import net.helenus.mapping.OrderingDirection; import net.helenus.mapping.OrderingDirection;
import net.helenus.mapping.value.ColumnValueProvider; import net.helenus.mapping.value.ColumnValueProvider;
@ -206,7 +207,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
if (facet instanceof UnboundFacet) { if (facet instanceof UnboundFacet) {
UnboundFacet unboundFacet = (UnboundFacet) facet; UnboundFacet unboundFacet = (UnboundFacet) facet;
UnboundFacet.Binder binder = unboundFacet.binder(); UnboundFacet.Binder binder = unboundFacet.binder();
unboundFacet.getProperties().forEach(prop -> { for (HelenusProperty prop : unboundFacet.getProperties()) {
if (filters != null) {
Filter filter = filters.get(prop); Filter filter = filters.get(prop);
if (filter != null) { if (filter != null) {
Object[] postulates = filter.postulateValues(); Object[] postulates = filter.postulateValues();
@ -214,8 +216,9 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
binder.setValueForProperty(prop, p.toString()); binder.setValueForProperty(prop, p.toString());
} }
} }
}
}); }
if (binder.isBound()) { if (binder.isBound()) {
boundFacets.add(binder.bind()); boundFacets.add(binder.bind());
} }
@ -247,7 +250,9 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
+ entity.getMappingInterface() + " or " + prop.getEntity().getMappingInterface()); + entity.getMappingInterface() + " or " + prop.getEntity().getMappingInterface());
} }
if (cached) { // TODO(gburd): writeTime and ttl will be useful on merge() but cause object
// identity to fail.
if (false && cached) {
switch (prop.getProperty().getColumnType()) { switch (prop.getProperty().getColumnType()) {
case PARTITION_KEY : case PARTITION_KEY :
case CLUSTERING_COLUMN : case CLUSTERING_COLUMN :

View file

@ -16,7 +16,9 @@
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeoutException;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.querybuilder.Assignment; import com.datastax.driver.core.querybuilder.Assignment;
@ -25,19 +27,25 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update; import com.datastax.driver.core.querybuilder.Update;
import net.helenus.core.*; import net.helenus.core.*;
import net.helenus.core.cache.BoundFacet;
import net.helenus.core.cache.Facet;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.HelenusProperty; import net.helenus.mapping.HelenusProperty;
import net.helenus.mapping.MappingUtil; import net.helenus.mapping.MappingUtil;
import net.helenus.mapping.value.BeanColumnValueProvider;
import net.helenus.mapping.value.ValueProviderMap;
import net.helenus.support.HelenusMappingException; import net.helenus.support.HelenusMappingException;
import net.helenus.support.Immutables; import net.helenus.support.Immutables;
public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateOperation<E>> { public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateOperation<E>> {
private final List<Assignment> assignments = new ArrayList<Assignment>(); private final Map<Assignment, BoundFacet> assignments = new HashMap<>();
private final AbstractEntityDraft<E> draft; private final AbstractEntityDraft<E> draft;
private final Map<String, Object> draftMap; private final Map<String, Object> draftMap;
private HelenusEntity entity = null; private HelenusEntity entity = null;
private Object pojo;
private int[] ttl; private int[] ttl;
private long[] timestamp; private long[] timestamp;
@ -53,13 +61,21 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
this.draftMap = draft.toMap(); this.draftMap = draft.toMap();
} }
public UpdateOperation(AbstractSessionOperations sessionOperations, Object pojo) {
super(sessionOperations);
this.draft = null;
this.draftMap = null;
this.pojo = pojo;
this.entity = Helenus.resolve(MappingUtil.getMappingInterface(pojo));
}
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) { public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
super(sessionOperations); super(sessionOperations);
this.draft = null; this.draft = null;
this.draftMap = null; this.draftMap = null;
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty()); Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
assignments.add(QueryBuilder.set(p.getColumnName(), value)); assignments.put(QueryBuilder.set(p.getColumnName(), value), new BoundFacet(p.getProperty(), v));
addPropertyNode(p); addPropertyNode(p);
} }
@ -68,9 +84,29 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
Objects.requireNonNull(getter, "getter is empty"); Objects.requireNonNull(getter, "getter is empty");
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
HelenusProperty prop = p.getProperty();
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty()); Object value = sessionOps.getValuePreparer().prepareColumnValue(v, prop);
assignments.add(QueryBuilder.set(p.getColumnName(), value)); assignments.put(QueryBuilder.set(p.getColumnName(), value), new BoundFacet(prop, value));
if (draft != null) {
String key = prop.getPropertyName();
if (draft.get(key, value.getClass()) != value) {
draft.set(key, value);
}
}
if (entity != null) {
if (entity.isCacheable() && pojo != null && pojo instanceof MapExportable) {
String key = prop.getPropertyName();
Map<String, Object> map = ((MapExportable) pojo).toMap();
if (!(map instanceof ValueProviderMap)) {
if (map.get(key) != value) {
map.put(key, value);
}
}
}
}
addPropertyNode(p); addPropertyNode(p);
@ -95,15 +131,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
assignments.add(QueryBuilder.incr(p.getColumnName(), delta)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
Long value = (Long) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
if (draft != null) { facet = new BoundFacet(prop, value + delta);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
draftMap.put(key, (Long) draftMap.get(key) + delta); draftMap.put(key, (Long) draftMap.get(key) + delta);
} }
assignments.put(QueryBuilder.incr(p.getColumnName(), delta), facet);
addPropertyNode(p);
return this; return this;
} }
@ -117,15 +158,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
assignments.add(QueryBuilder.decr(p.getColumnName(), delta)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
Long value = (Long) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
if (draft != null) { facet = new BoundFacet(prop, value - delta);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
draftMap.put(key, (Long) draftMap.get(key) - delta); draftMap.put(key, (Long) draftMap.get(key) - delta);
} }
assignments.put(QueryBuilder.decr(p.getColumnName(), delta), facet);
addPropertyNode(p);
return this; return this;
} }
@ -144,16 +190,22 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
Object valueObj = prepareSingleListValue(p, value); Object valueObj = prepareSingleListValue(p, value);
assignments.add(QueryBuilder.prepend(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { list.add(0, value);
facet = new BoundFacet(prop, list);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.add(0, value); list.add(0, value);
} }
assignments.put(QueryBuilder.prepend(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -165,16 +217,22 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
List valueObj = prepareListValue(p, value); List valueObj = prepareListValue(p, value);
assignments.add(QueryBuilder.prependAll(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null && value.size() > 0) { list.addAll(0, value);
facet = new BoundFacet(prop, list);
} else if (draft != null && value.size() > 0) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.addAll(0, value); list.addAll(0, value);
} }
assignments.put(QueryBuilder.prependAll(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -186,13 +244,16 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
Object valueObj = prepareSingleListValue(p, value); Object valueObj = prepareSingleListValue(p, value);
assignments.add(QueryBuilder.setIdx(p.getColumnName(), idx, valueObj)); BoundFacet facet = null;
if (pojo != null || draft != null) {
addPropertyNode(p); List<V> list;
HelenusProperty prop = p.getProperty();
if (draft != null) { if (pojo != null) {
list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
} else {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); list = (List<V>) draftMap.get(key);
}
if (idx < 0) { if (idx < 0) {
list.add(0, value); list.add(0, value);
} else if (idx > list.size()) { } else if (idx > list.size()) {
@ -201,8 +262,13 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
list.add(idx, value); list.add(idx, value);
} }
list.add(0, value); list.add(0, value);
facet = new BoundFacet(prop, list);
} }
assignments.put(QueryBuilder.setIdx(p.getColumnName(), idx, valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -214,15 +280,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
Object valueObj = prepareSingleListValue(p, value); Object valueObj = prepareSingleListValue(p, value);
assignments.add(QueryBuilder.append(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { list.add(value);
facet = new BoundFacet(prop, list);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.add(value); list.add(value);
} }
assignments.put(QueryBuilder.append(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -235,15 +306,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
List valueObj = prepareListValue(p, value); List valueObj = prepareListValue(p, value);
assignments.add(QueryBuilder.appendAll(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null && value.size() > 0) { list.addAll(value);
facet = new BoundFacet(prop, list);
} else if (draft != null && value.size() > 0) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.addAll(value); list.addAll(value);
} }
assignments.put(QueryBuilder.appendAll(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -256,15 +332,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
Object valueObj = prepareSingleListValue(p, value); Object valueObj = prepareSingleListValue(p, value);
assignments.add(QueryBuilder.discard(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { list.remove(value);
facet = new BoundFacet(prop, list);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.remove(value); list.remove(value);
} }
assignments.put(QueryBuilder.discard(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -277,15 +358,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
List valueObj = prepareListValue(p, value); List valueObj = prepareListValue(p, value);
assignments.add(QueryBuilder.discardAll(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { list.removeAll(value);
facet = new BoundFacet(prop, list);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>) draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.removeAll(value); list.removeAll(value);
} }
assignments.put(QueryBuilder.discardAll(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -334,15 +420,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
Object valueObj = prepareSingleSetValue(p, value); Object valueObj = prepareSingleSetValue(p, value);
assignments.add(QueryBuilder.add(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { set.add(value);
facet = new BoundFacet(prop, set);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
Set<V> set = (Set<V>) draftMap.get(key); Set<V> set = (Set<V>) draftMap.get(key);
set.add(value); set.add(value);
} }
assignments.put(QueryBuilder.add(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -355,15 +446,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
Set valueObj = prepareSetValue(p, value); Set valueObj = prepareSetValue(p, value);
assignments.add(QueryBuilder.addAll(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { set.addAll(value);
facet = new BoundFacet(prop, set);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
Set<V> set = (Set<V>) draftMap.get(key); Set<V> set = (Set<V>) draftMap.get(key);
set.addAll(value); set.addAll(value);
} }
assignments.put(QueryBuilder.addAll(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -376,15 +472,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
Object valueObj = prepareSingleSetValue(p, value); Object valueObj = prepareSingleSetValue(p, value);
assignments.add(QueryBuilder.remove(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { set.remove(value);
facet = new BoundFacet(prop, set);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
Set<V> set = (Set<V>) draftMap.get(key); Set<V> set = (Set<V>) draftMap.get(key);
set.remove(value); set.remove(value);
} }
assignments.put(QueryBuilder.remove(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -397,15 +498,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
Set valueObj = prepareSetValue(p, value); Set valueObj = prepareSetValue(p, value);
assignments.add(QueryBuilder.removeAll(p.getColumnName(), valueObj)); BoundFacet facet = null;
if (pojo != null) {
addPropertyNode(p); HelenusProperty prop = p.getProperty();
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
if (draft != null) { set.removeAll(value);
facet = new BoundFacet(prop, set);
} else if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
Set<V> set = (Set<V>) draftMap.get(key); Set<V> set = (Set<V>) draftMap.get(key);
set.removeAll(value); set.removeAll(value);
} }
assignments.put(QueryBuilder.removeAll(p.getColumnName(), valueObj), facet);
addPropertyNode(p);
return this; return this;
} }
@ -453,23 +559,29 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
HelenusProperty prop = p.getProperty(); HelenusProperty prop = p.getProperty();
BoundFacet facet = null;
if (pojo != null) {
Map<K, V> map = new HashMap<K, V>(
(Map<K, V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
map.put(key, value);
facet = new BoundFacet(prop, map);
} else if (draft != null) {
((Map<K, V>) draftMap.get(prop.getPropertyName())).put(key, value);
}
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository()); Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
if (converter.isPresent()) { if (converter.isPresent()) {
Map<Object, Object> convertedMap = (Map<Object, Object>) converter.get() Map<Object, Object> convertedMap = (Map<Object, Object>) converter.get()
.apply(Immutables.mapOf(key, value)); .apply(Immutables.mapOf(key, value));
for (Map.Entry<Object, Object> e : convertedMap.entrySet()) { for (Map.Entry<Object, Object> e : convertedMap.entrySet()) {
assignments.add(QueryBuilder.put(p.getColumnName(), e.getKey(), e.getValue())); assignments.put(QueryBuilder.put(p.getColumnName(), e.getKey(), e.getValue()), facet);
} }
} else { } else {
assignments.add(QueryBuilder.put(p.getColumnName(), key, value)); assignments.put(QueryBuilder.put(p.getColumnName(), key, value), facet);
} }
addPropertyNode(p); addPropertyNode(p);
if (draft != null) {
((Map<K, V>) draftMap.get(prop.getPropertyName())).put(key, value);
}
return this; return this;
} }
@ -481,20 +593,26 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter); HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
HelenusProperty prop = p.getProperty(); HelenusProperty prop = p.getProperty();
BoundFacet facet = null;
if (pojo != null) {
Map<K, V> newMap = new HashMap<K, V>(
(Map<K, V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
newMap.putAll(map);
facet = new BoundFacet(prop, newMap);
} else if (draft != null) {
((Map<K, V>) draftMap.get(prop.getPropertyName())).putAll(map);
}
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository()); Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
if (converter.isPresent()) { if (converter.isPresent()) {
Map convertedMap = (Map) converter.get().apply(map); Map convertedMap = (Map) converter.get().apply(map);
assignments.add(QueryBuilder.putAll(p.getColumnName(), convertedMap)); assignments.put(QueryBuilder.putAll(p.getColumnName(), convertedMap), facet);
} else { } else {
assignments.add(QueryBuilder.putAll(p.getColumnName(), map)); assignments.put(QueryBuilder.putAll(p.getColumnName(), map), facet);
} }
addPropertyNode(p); addPropertyNode(p);
if (draft != null) {
((Map<K, V>) draftMap.get(prop.getPropertyName())).putAll(map);
}
return this; return this;
} }
@ -507,7 +625,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
Update update = QueryBuilder.update(entity.getName().toCql()); Update update = QueryBuilder.update(entity.getName().toCql());
for (Assignment assignment : assignments) { for (Assignment assignment : assignments.keySet()) {
update.with(assignment); update.with(assignment);
} }
@ -567,16 +685,48 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
} }
@Override @Override
public E sync(UnitOfWork uow) {// throws TimeoutException { public E sync() throws TimeoutException {
E result = super.sync();
if (entity.isCacheable()) {
if (draft != null) {
sessionOps.updateCache(draft, bindFacetValues());
} else if (pojo != null) {
sessionOps.updateCache(pojo, bindFacetValues());
} else {
sessionOps.cacheEvict(bindFacetValues());
}
}
return result;
}
@Override
public E sync(UnitOfWork uow) throws TimeoutException {
if (uow == null) { if (uow == null) {
return sync(); return sync();
} }
E result = super.sync(uow); E result = super.sync(uow);
// TODO(gburd): Only drafted entity objects are updated in the cache at this
// time.
if (draft != null) { if (draft != null) {
updateCache(uow, result, getFacets()); cacheUpdate(uow, result, bindFacetValues());
} else if (pojo != null) {
cacheUpdate(uow, (E) pojo, bindFacetValues());
} }
return result; return result;
} }
@Override
public List<Facet> bindFacetValues() {
List<Facet> facets = bindFacetValues(entity.getFacets());
facets.addAll(assignments.values().stream().distinct().filter(o -> o != null).collect(Collectors.toList()));
return facets;
}
@Override
public List<Facet> getFacets() {
if (entity != null) {
return entity.getFacets();
} else {
return new ArrayList<Facet>();
}
}
} }

View file

@ -18,6 +18,7 @@ package net.helenus.core.reflect;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -63,8 +64,9 @@ public class DslInvocationHandler<E> implements InvocationHandler {
private HelenusEntity init(Metadata metadata) { private HelenusEntity init(Metadata metadata) {
HelenusEntity entity = new HelenusMappingEntity(iface, metadata); HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
Collection<HelenusProperty> properties = entity.getOrderedProperties();
for (HelenusProperty prop : entity.getOrderedProperties()) { if (properties != null) {
for (HelenusProperty prop : properties) {
map.put(prop.getGetterMethod(), prop); map.put(prop.getGetterMethod(), prop);
@ -73,8 +75,8 @@ public class DslInvocationHandler<E> implements InvocationHandler {
if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) { if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
Object childDsl = Helenus.dsl(javaType, classLoader, Optional.of(new HelenusPropertyNode(prop, parent)), Object childDsl = Helenus.dsl(javaType, classLoader,
metadata); Optional.of(new HelenusPropertyNode(prop, parent)), metadata);
udtMap.put(prop.getGetterMethod(), childDsl); udtMap.put(prop.getGetterMethod(), childDsl);
} }
@ -91,6 +93,7 @@ public class DslInvocationHandler<E> implements InvocationHandler {
} }
} }
} }
}
return entity; return entity;
} }

View file

@ -15,17 +15,22 @@
*/ */
package net.helenus.core.reflect; package net.helenus.core.reflect;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable; import java.io.Serializable;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Collections; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.mapping.annotation.Transient; import net.helenus.mapping.annotation.Transient;
import net.helenus.mapping.value.ValueProviderMap;
import net.helenus.support.HelenusException; import net.helenus.support.HelenusException;
public class MapperInvocationHandler<E> implements InvocationHandler, Serializable { public class MapperInvocationHandler<E> implements InvocationHandler, Serializable {
@ -59,6 +64,13 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
return result; return result;
} }
private Object writeReplace() {
return new SerializationProxy<E>(this);
}
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required.");
}
@Override @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
@ -97,12 +109,20 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
return iface.getSimpleName() + ": " + src.toString(); return iface.getSimpleName() + ": " + src.toString();
} }
if ("writeReplace".equals(methodName)) {
return new SerializationProxy(this);
}
if ("readObject".equals(methodName)) {
throw new InvalidObjectException("Proxy required.");
}
if ("dsl".equals(methodName)) { if ("dsl".equals(methodName)) {
return Helenus.dsl(iface); return Helenus.dsl(iface);
} }
if (MapExportable.TO_MAP_METHOD.equals(methodName)) { if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
return Collections.unmodifiableMap(src); return src; // return Collections.unmodifiableMap(src);
} }
Object value = src.get(methodName); Object value = src.get(methodName);
@ -132,4 +152,30 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
return value; return value;
} }
static class SerializationProxy<E> implements Serializable {
private static final long serialVersionUID = -5617583940055969353L;
private final Class<E> iface;
private final Map<String, Object> src;
public SerializationProxy(MapperInvocationHandler mapper) {
this.iface = mapper.iface;
if (mapper.src instanceof ValueProviderMap) {
this.src = new HashMap<String, Object>(mapper.src.size());
Set<String> keys = mapper.src.keySet();
for (String key : keys) {
this.src.put(key, mapper.src.get(key));
}
} else {
this.src = mapper.src;
}
}
Object readResolve() throws ObjectStreamException {
return new MapperInvocationHandler(iface, src);
}
}
} }

View file

@ -15,6 +15,7 @@
*/ */
package net.helenus.core.reflect; package net.helenus.core.reflect;
import java.io.Serializable;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Map; import java.util.Map;
@ -28,7 +29,8 @@ public enum ReflectionMapperInstantiator implements MapperInstantiator {
public <E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) { public <E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
MapperInvocationHandler<E> handler = new MapperInvocationHandler<E>(iface, src); MapperInvocationHandler<E> handler = new MapperInvocationHandler<E>(iface, src);
E proxy = (E) Proxy.newProxyInstance(classLoader, new Class[]{iface, MapExportable.class}, handler); E proxy = (E) Proxy.newProxyInstance(classLoader, new Class[]{iface, MapExportable.class, Serializable.class},
handler);
return proxy; return proxy;
} }
} }

View file

@ -18,6 +18,8 @@ package net.helenus.mapping;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import javax.validation.ConstraintValidator;
import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.ClassUtils;
import com.datastax.driver.core.DefaultMetadata; import com.datastax.driver.core.DefaultMetadata;
@ -31,6 +33,7 @@ import net.helenus.core.annotation.Cacheable;
import net.helenus.core.cache.Facet; import net.helenus.core.cache.Facet;
import net.helenus.core.cache.UnboundFacet; import net.helenus.core.cache.UnboundFacet;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.*;
import net.helenus.mapping.validator.DistinctValidator;
import net.helenus.support.HelenusMappingException; import net.helenus.support.HelenusMappingException;
public final class HelenusMappingEntity implements HelenusEntity { public final class HelenusMappingEntity implements HelenusEntity {
@ -125,10 +128,12 @@ public final class HelenusMappingEntity implements HelenusEntity {
facetsBuilder.add(new UnboundFacet(primaryKeyProperties)); facetsBuilder.add(new UnboundFacet(primaryKeyProperties));
primaryKeyProperties = null; primaryKeyProperties = null;
} }
Optional<IdentityName> optionalIndexName = prop.getIndexName(); for (ConstraintValidator<?, ?> constraint : MappingUtil.getValidators(prop.getGetterMethod())) {
if (optionalIndexName.isPresent()) { if (constraint.getClass().isAssignableFrom(DistinctValidator.class)) {
UnboundFacet facet = new UnboundFacet(prop); UnboundFacet facet = new UnboundFacet(prop);
facetsBuilder.add(facet); facetsBuilder.add(facet);
break;
}
} }
} }
} }

View file

@ -16,6 +16,7 @@
package net.helenus.mapping; package net.helenus.mapping;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -282,4 +283,41 @@ public final class MappingUtil {
return e.getPropertyNode(); return e.getPropertyNode();
} }
} }
// https://stackoverflow.com/a/4882306/366692
public static <T> T clone(T object) throws CloneNotSupportedException {
Object clone = null;
// Use reflection, because there is no other way
try {
Method method = object.getClass().getMethod("clone");
clone = method.invoke(object);
} catch (InvocationTargetException e) {
rethrow(e.getCause());
} catch (Exception cause) {
rethrow(cause);
}
if (object.getClass().isInstance(clone)) {
@SuppressWarnings("unchecked") // clone class <= object class <= T
T t = (T) clone;
return t;
} else {
throw new ClassCastException(clone.getClass().getName());
}
}
private static void rethrow(Throwable cause) throws CloneNotSupportedException {
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
if (cause instanceof CloneNotSupportedException) {
throw (CloneNotSupportedException) cause;
}
CloneNotSupportedException e = new CloneNotSupportedException();
e.initCause(cause);
throw e;
}
} }

View file

@ -252,4 +252,29 @@ public final class Constraints {
*/ */
int flags(); int flags();
} }
/**
* Distinct annotation is used to signal, but not ensure that a value should be
* distinct in the database.
*
* <p>
* Can be used only for @java.lang.CharSequence
*
* <p>
* It does not have effect on selects and data retrieval operations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = DistinctValidator.class)
public @interface Distinct {
/**
* User defined Enum to further restrict the items in the set.
*
* @return Java
*/
Class<? extends Enum> value() default Enum.class;
}
} }

View file

@ -65,4 +65,10 @@ public @interface Index {
* @return true if the index should ignore case when comparing * @return true if the index should ignore case when comparing
*/ */
boolean caseSensitive() default true; boolean caseSensitive() default true;
/**
*
* @return
*/
boolean distinct() default false;
} }

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2015 The Helenus 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.helenus.mapping.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import net.helenus.mapping.annotation.Constraints;
public final class DistinctValidator implements ConstraintValidator<Constraints.Distinct, CharSequence> {
@Override
public void initialize(Constraints.Distinct constraintAnnotation) {
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
// TODO(gburd): if there is an Enum type supplied, check that value is valid
// Enum.name()
return true;
}
}

View file

@ -15,17 +15,19 @@
*/ */
package net.helenus.test.integration.build; package net.helenus.test.integration.build;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.KeyspaceMetadata;
import com.datastax.driver.core.Session;
import java.io.IOException; import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper; import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.KeyspaceMetadata;
import com.datastax.driver.core.Session;
/** AbstractEmbeddedCassandraTest */ /** AbstractEmbeddedCassandraTest */
public abstract class AbstractEmbeddedCassandraTest { public abstract class AbstractEmbeddedCassandraTest {
@ -61,22 +63,16 @@ public abstract class AbstractEmbeddedCassandraTest {
public static void startCassandraEmbeddedServer() public static void startCassandraEmbeddedServer()
throws TTransportException, IOException, InterruptedException, ConfigurationException { throws TTransportException, IOException, InterruptedException, ConfigurationException {
keyspace = "test" + UUID.randomUUID().toString().replace("-", ""); keyspace = "test" + UUID.randomUUID().toString().replace("-", "");
EmbeddedCassandraServerHelper.startEmbeddedCassandra( EmbeddedCassandraServerHelper.startEmbeddedCassandra(EmbeddedCassandraServerHelper.CASSANDRA_RNDPORT_YML_FILE);
EmbeddedCassandraServerHelper.CASSANDRA_RNDPORT_YML_FILE);
cluster = cluster = Cluster.builder().addContactPoint(EmbeddedCassandraServerHelper.getHost())
Cluster.builder() .withPort(EmbeddedCassandraServerHelper.getNativeTransportPort()).build();
.addContactPoint(EmbeddedCassandraServerHelper.getHost())
.withPort(EmbeddedCassandraServerHelper.getNativeTransportPort())
.build();
KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace); KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace);
if (kmd == null) { if (kmd == null) {
session = cluster.connect(); session = cluster.connect();
String cql = String cql = "CREATE KEYSPACE " + keyspace
"CREATE KEYSPACE "
+ keyspace
+ " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}" + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}"
+ " AND DURABLE_WRITES = false;"; + " AND DURABLE_WRITES = false;";
System.out.println(cql + "\n"); System.out.println(cql + "\n");

View file

@ -15,10 +15,11 @@
*/ */
package net.helenus.test.integration.core; package net.helenus.test.integration.core;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Test;
public class ContextInitTest extends AbstractEmbeddedCassandraTest { public class ContextInitTest extends AbstractEmbeddedCassandraTest {

View file

@ -1,5 +1,8 @@
package net.helenus.test.integration.core; package net.helenus.test.integration.core;
import org.junit.Before;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusValidator; import net.helenus.core.HelenusValidator;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
@ -10,21 +13,10 @@ import net.helenus.mapping.annotation.Table;
import net.helenus.support.HelenusException; import net.helenus.support.HelenusException;
import net.helenus.support.HelenusMappingException; import net.helenus.support.HelenusMappingException;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Before;
import org.junit.Test;
public class HelenusValidatorTest extends AbstractEmbeddedCassandraTest { public class HelenusValidatorTest extends AbstractEmbeddedCassandraTest {
@Table
interface ModelForValidation {
@Constraints.Email
@PartitionKey
String id();
}
HelenusEntity entity; HelenusEntity entity;
HelenusProperty prop; HelenusProperty prop;
@Before @Before
@ -49,4 +41,12 @@ public class HelenusValidatorTest extends AbstractEmbeddedCassandraTest {
public void testOk() { public void testOk() {
HelenusValidator.INSTANCE.validate(prop, "a@b.c"); HelenusValidator.INSTANCE.validate(prop, "a@b.c");
} }
@Table
interface ModelForValidation {
@Constraints.Email
@PartitionKey
String id();
}
} }

View file

@ -15,25 +15,19 @@
*/ */
package net.helenus.test.integration.core.collection; package net.helenus.test.integration.core.collection;
import static net.helenus.core.Query.eq; import static net.helenus.core.Query.*;
import static net.helenus.core.Query.get;
import static net.helenus.core.Query.getIdx;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
public class CollectionTest extends AbstractEmbeddedCassandraTest { public class CollectionTest extends AbstractEmbeddedCassandraTest {
static Customer customer; static Customer customer;
@ -68,8 +62,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full object // read full object
Customer actual = Customer actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(aliases, actual.aliases()); Assert.assertEquals(aliases, actual.aliases());
Assert.assertNull(actual.names()); Assert.assertNull(actual.names());
@ -77,8 +70,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full set // read full set
Set<String> actualSet = Set<String> actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst()
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; .get()._1;
Assert.assertEquals(aliases, actualSet); Assert.assertEquals(aliases, actualSet);
// UPDATE // UPDATE
@ -88,8 +81,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync(); session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
actual = actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(expected, actual.aliases()); Assert.assertEquals(expected, actual.aliases());
@ -101,16 +93,14 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.add("add"); expected.add("add");
session.update().add(customer::aliases, "add").where(customer::id, eq(id)).sync(); session.update().add(customer::aliases, "add").where(customer::id, eq(id)).sync();
actualSet = actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualSet); Assert.assertEquals(expected, actualSet);
// addAll operation // addAll operation
expected.addAll(aliases); expected.addAll(aliases);
session.update().addAll(customer::aliases, aliases).where(customer::id, eq(id)).sync(); session.update().addAll(customer::aliases, aliases).where(customer::id, eq(id)).sync();
actualSet = actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualSet); Assert.assertEquals(expected, actualSet);
// DELETE // DELETE
@ -120,8 +110,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.remove("add"); expected.remove("add");
session.update().remove(customer::aliases, "add").where(customer::id, eq(id)).sync(); session.update().remove(customer::aliases, "add").where(customer::id, eq(id)).sync();
actualSet = actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualSet); Assert.assertEquals(expected, actualSet);
// remove values // remove values
@ -129,16 +118,14 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.removeAll(aliases); expected.removeAll(aliases);
session.update().removeAll(customer::aliases, aliases).where(customer::id, eq(id)).sync(); session.update().removeAll(customer::aliases, aliases).where(customer::id, eq(id)).sync();
actualSet = actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualSet); Assert.assertEquals(expected, actualSet);
// remove full list // remove full list
session.update().set(customer::aliases, null).where(customer::id, eq(id)).sync(); session.update().set(customer::aliases, null).where(customer::id, eq(id)).sync();
actualSet = actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualSet); Assert.assertNull(actualSet);
// remove object // remove object
@ -165,8 +152,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full object // read full object
Customer actual = Customer actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(names, actual.names()); Assert.assertEquals(names, actual.names());
@ -175,8 +161,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full list // read full list
List<String> actualList = List<String> actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst()
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; .get()._1;
Assert.assertEquals(names, actualList); Assert.assertEquals(names, actualList);
// read single value by index // read single value by index
@ -192,8 +178,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
session.update().set(customer::names, expected).where(customer::id, eq(id)).sync(); session.update().set(customer::names, expected).where(customer::id, eq(id)).sync();
actual = actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(expected, actual.names()); Assert.assertEquals(expected, actual.names());
@ -205,8 +190,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.add(0, "prepend"); expected.add(0, "prepend");
session.update().prepend(customer::names, "prepend").where(customer::id, eq(id)).sync(); session.update().prepend(customer::names, "prepend").where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// append operation // append operation
@ -214,24 +198,21 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.add("append"); expected.add("append");
session.update().append(customer::names, "append").where(customer::id, eq(id)).sync(); session.update().append(customer::names, "append").where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// prependAll operation // prependAll operation
expected.addAll(0, names); expected.addAll(0, names);
session.update().prependAll(customer::names, names).where(customer::id, eq(id)).sync(); session.update().prependAll(customer::names, names).where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// appendAll operation // appendAll operation
expected.addAll(names); expected.addAll(names);
session.update().appendAll(customer::names, names).where(customer::id, eq(id)).sync(); session.update().appendAll(customer::names, names).where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// set by Index // set by Index
@ -239,8 +220,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.set(5, "inserted"); expected.set(5, "inserted");
session.update().setIdx(customer::names, 5, "inserted").where(customer::id, eq(id)).sync(); session.update().setIdx(customer::names, 5, "inserted").where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// DELETE // DELETE
@ -250,8 +230,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.remove("inserted"); expected.remove("inserted");
session.update().discard(customer::names, "inserted").where(customer::id, eq(id)).sync(); session.update().discard(customer::names, "inserted").where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// remove values // remove values
@ -259,16 +238,14 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.removeAll(names); expected.removeAll(names);
session.update().discardAll(customer::names, names).where(customer::id, eq(id)).sync(); session.update().discardAll(customer::names, names).where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertEquals(expected, actualList); Assert.assertEquals(expected, actualList);
// remove full list // remove full list
session.update().set(customer::names, null).where(customer::id, eq(id)).sync(); session.update().set(customer::names, null).where(customer::id, eq(id)).sync();
actualList = actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualList); Assert.assertNull(actualList);
// remove object // remove object
@ -295,8 +272,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full object // read full object
Customer actual = Customer actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(props, actual.properties()); Assert.assertEquals(props, actual.properties());
@ -305,20 +281,13 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full map // read full map
Map<String, String> actualMap = Map<String, String> actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync()
session .findFirst().get()._1;
.select(customer::properties)
.where(customer::id, eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(props, actualMap); Assert.assertEquals(props, actualMap);
// read single key-value in map // read single key-value in map
String cql = String cql = session.select(get(customer::properties, "key1")).where(customer::id, eq(id)).cql();
session.select(get(customer::properties, "key1")).where(customer::id, eq(id)).cql();
System.out.println("Still not supporting cql = " + cql); System.out.println("Still not supporting cql = " + cql);
@ -330,8 +299,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync(); session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync();
actual = actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(expected, actual.properties()); Assert.assertEquals(expected, actual.properties());
@ -342,28 +310,14 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.put("k3", "v3"); expected.put("k3", "v3");
session.update().put(customer::properties, "k3", "v3").where(customer::id, eq(id)).sync(); session.update().put(customer::properties, "k3", "v3").where(customer::id, eq(id)).sync();
actualMap = actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
session
.select(customer::properties)
.where(customer::id, eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(expected, actualMap); Assert.assertEquals(expected, actualMap);
// putAll operation // putAll operation
expected.putAll(props); expected.putAll(props);
session.update().putAll(customer::properties, props).where(customer::id, eq(id)).sync(); session.update().putAll(customer::properties, props).where(customer::id, eq(id)).sync();
actualMap = actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
session
.select(customer::properties)
.where(customer::id, eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(expected, actualMap); Assert.assertEquals(expected, actualMap);
// put existing // put existing
@ -371,14 +325,7 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.put("k3", "v33"); expected.put("k3", "v33");
session.update().put(customer::properties, "k3", "v33").where(customer::id, eq(id)).sync(); session.update().put(customer::properties, "k3", "v33").where(customer::id, eq(id)).sync();
actualMap = actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
session
.select(customer::properties)
.where(customer::id, eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(expected, actualMap); Assert.assertEquals(expected, actualMap);
// DELETE // DELETE
@ -388,28 +335,14 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
expected.remove("k3"); expected.remove("k3");
session.update().put(customer::properties, "k3", null).where(customer::id, eq(id)).sync(); session.update().put(customer::properties, "k3", null).where(customer::id, eq(id)).sync();
actualMap = actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
session
.select(customer::properties)
.where(customer::id, eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(expected, actualMap); Assert.assertEquals(expected, actualMap);
// remove full map // remove full map
session.update().set(customer::properties, null).where(customer::id, eq(id)).sync(); session.update().set(customer::properties, null).where(customer::id, eq(id)).sync();
actualMap = actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
session
.select(customer::properties)
.where(customer::id, eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertNull(actualMap); Assert.assertNull(actualMap);
// remove object // remove object

View file

@ -15,11 +15,13 @@
*/ */
package net.helenus.test.integration.core.collection; package net.helenus.test.integration.core.collection;
import com.datastax.driver.core.DataType.Name;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import com.datastax.driver.core.DataType.Name;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;
import net.helenus.mapping.annotation.Types; import net.helenus.mapping.annotation.Types;

View file

@ -17,15 +17,17 @@ package net.helenus.test.integration.core.compound;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Operator; import net.helenus.core.Operator;
import net.helenus.core.Query; import net.helenus.core.Query;
import net.helenus.support.Mutable; import net.helenus.support.Mutable;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class CompondKeyTest extends AbstractEmbeddedCassandraTest { public class CompondKeyTest extends AbstractEmbeddedCassandraTest {
@ -33,28 +35,6 @@ public class CompondKeyTest extends AbstractEmbeddedCassandraTest {
HelenusSession session; HelenusSession session;
public static class TimelineImpl implements Timeline {
UUID userId;
Date timestamp;
String text;
@Override
public UUID userId() {
return userId;
}
@Override
public Date timestamp() {
return timestamp;
}
@Override
public String text() {
return text;
}
}
@Before @Before
public void beforeTest() { public void beforeTest() {
session = Helenus.init(getSession()).showCql().add(Timeline.class).autoCreateDrop().get(); session = Helenus.init(getSession()).showCql().add(Timeline.class).autoCreateDrop().get();
@ -84,16 +64,11 @@ public class CompondKeyTest extends AbstractEmbeddedCassandraTest {
final Mutable<Date> d = new Mutable<Date>(null); final Mutable<Date> d = new Mutable<Date>(null);
final Mutable<Integer> c = new Mutable<Integer>(0); final Mutable<Integer> c = new Mutable<Integer>(0);
session session.select(timeline::userId, timeline::timestamp, timeline::text)
.select(timeline::userId, timeline::timestamp, timeline::text) .where(timeline::userId, Operator.EQ, userId).orderBy(Query.desc(timeline::timestamp)).limit(5).sync()
.where(timeline::userId, Operator.EQ, userId) .forEach(t -> {
.orderBy(Query.desc(timeline::timestamp))
.limit(5)
.sync()
.forEach(
t -> {
//System.out.println(t); // System.out.println(t);
c.set(c.get() + 1); c.set(c.get() + 1);
Date cd = d.get(); Date cd = d.get();
@ -105,4 +80,26 @@ public class CompondKeyTest extends AbstractEmbeddedCassandraTest {
Assert.assertEquals(Integer.valueOf(5), c.get()); Assert.assertEquals(Integer.valueOf(5), c.get());
} }
public static class TimelineImpl implements Timeline {
UUID userId;
Date timestamp;
String text;
@Override
public UUID userId() {
return userId;
}
@Override
public Date timestamp() {
return timestamp;
}
@Override
public String text() {
return text;
}
}
} }

View file

@ -17,11 +17,8 @@ package net.helenus.test.integration.core.compound;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
import net.helenus.mapping.annotation.ClusteringColumn;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.*;
import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table;
import net.helenus.mapping.annotation.Types;
@Table @Table
public interface Timeline { public interface Timeline {

View file

@ -18,13 +18,15 @@ package net.helenus.test.integration.core.counter;
import static net.helenus.core.Query.eq; import static net.helenus.core.Query.eq;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
public class CounterTest extends AbstractEmbeddedCassandraTest { public class CounterTest extends AbstractEmbeddedCassandraTest {
static Page page; static Page page;
@ -45,14 +47,12 @@ public class CounterTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void testCounter() throws TimeoutException { public void testCounter() throws TimeoutException {
boolean exists = boolean exists = session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().isPresent();
session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().isPresent();
Assert.assertFalse(exists); Assert.assertFalse(exists);
session.update().increment(page::hits, 10L).where(page::alias, eq("index")).sync(); session.update().increment(page::hits, 10L).where(page::alias, eq("index")).sync();
long hits = long hits = session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().get()._1;
session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().get()._1;
Assert.assertEquals(10, hits); Assert.assertEquals(10, hits);
session.update().decrement(page::hits).where(page::alias, eq("index")).sync(); session.update().decrement(page::hits).where(page::alias, eq("index")).sync();

View file

@ -15,52 +15,46 @@
*/ */
package net.helenus.test.integration.core.draft; package net.helenus.test.integration.core.draft;
import java.io.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import net.helenus.core.Helenus; import java.util.concurrent.TimeoutException;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import static net.helenus.core.Query.eq;
public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest { public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
static Supply supply; static Supply supply;
static HelenusSession session; static HelenusSession session;
static Supply.Draft draft = null;
@BeforeClass @BeforeClass
public static void beforeTest() { public static void beforeTest() throws TimeoutException {
session = Helenus.init(getSession()).showCql().add(Supply.class).autoCreateDrop().get(); session = Helenus.init(getSession()).showCql().add(Supply.class).autoCreateDrop().get();
supply = session.dsl(Supply.class); supply = session.dsl(Supply.class);
}
@Test draft = Supply.draft("APAC").code("WIDGET-002").description("Our second Widget!")
public void testFoo() throws Exception { .demand(new HashMap<String, Long>() {
Supply.Draft draft = null;
draft =
Supply.draft("APAC")
.code("WIDGET-002")
.description("Our second Widget!")
.demand(
new HashMap<String, Long>() {
{ {
put("APAC", 100L); put("APAC", 100L);
put("EMEA", 10000L); put("EMEA", 10000L);
put("NORAM", 2000000L); put("NORAM", 2000000L);
} }
}) }).shipments(new HashSet<String>() {
.shipments(
new HashSet<String>() {
{ {
add("HMS Puddle in transit to APAC, 100 units."); add("HMS Puddle in transit to APAC, 100 units.");
add("Frigate Jimmy in transit to EMEA, 10000 units."); add("Frigate Jimmy in transit to EMEA, 10000 units.");
} }
}) }).suppliers(new ArrayList<String>() {
.suppliers(
new ArrayList<String>() {
{ {
add("Puddle, Inc."); add("Puddle, Inc.");
add("Jimmy Town, LTD."); add("Jimmy Town, LTD.");
@ -68,13 +62,18 @@ public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
}); });
Supply s1 = session.<Supply>insert(draft).sync(); Supply s1 = session.<Supply>insert(draft).sync();
}
@Test
public void testFoo() throws Exception {
Supply s1 = session.<Supply>select(Supply.class).where(supply::id, eq(draft.id()))
.single()
.sync()
.orElse(null);
// List // List
Supply s2 = Supply s2 = session.<Supply>update(s1.update()).prepend(supply::suppliers, "Pignose Supply, LLC.").sync();
session
.<Supply>update(s1.update())
.prepend(supply::suppliers, "Pignose Supply, LLC.")
.sync();
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC."); Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC.");
// Set // Set
@ -86,4 +85,30 @@ public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync(); Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync();
Assert.assertEquals((long) s4.demand().get("NORAM"), 10L); Assert.assertEquals((long) s4.demand().get("NORAM"), 10L);
} }
@Test
public void testSerialization() throws Exception {
Supply s1, s2;
s1 = session.<Supply>select(Supply.class).where(supply::id, eq(draft.id()))
.single()
.sync()
.orElse(null);
byte[] data;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(s1);
out.flush();
data = bos.toByteArray();
}
try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
ObjectInput in = new ObjectInputStream(bis)) {
s2 = (Supply)in.readObject();
}
Assert.assertEquals(s2.id(), s1.id());
Assert.assertEquals(s2, s1);
}
} }

View file

@ -1,6 +1,7 @@
package net.helenus.test.integration.core.draft; package net.helenus.test.integration.core.draft;
import java.util.UUID; import java.util.UUID;
import net.helenus.core.AbstractAuditedEntityDraft; import net.helenus.core.AbstractAuditedEntityDraft;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
@ -11,6 +12,11 @@ public interface Inventory {
static Inventory inventory = Helenus.dsl(Inventory.class); static Inventory inventory = Helenus.dsl(Inventory.class);
@Transient
static Draft draft(UUID id) {
return new Draft(id);
}
@PartitionKey @PartitionKey
UUID id(); UUID id();
@ -26,11 +32,6 @@ public interface Inventory {
@Types.Counter @Types.Counter
long APAC(); long APAC();
@Transient
static Draft draft(UUID id) {
return new Draft(id);
}
@Transient @Transient
default Draft update() { default Draft update() {
return new Draft(this); return new Draft(this);

View file

@ -1,10 +1,12 @@
package net.helenus.test.integration.core.draft; package net.helenus.test.integration.core.draft;
import com.datastax.driver.core.utils.UUIDs;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import com.datastax.driver.core.utils.UUIDs;
import net.helenus.core.AbstractEntityDraft; import net.helenus.core.AbstractEntityDraft;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
@ -15,6 +17,11 @@ public interface Supply {
static Supply supply = Helenus.dsl(Supply.class); static Supply supply = Helenus.dsl(Supply.class);
@Transient
static Draft draft(String region) {
return new Draft(region);
}
@PartitionKey @PartitionKey
UUID id(); UUID id();
@ -38,11 +45,6 @@ public interface Supply {
@Index @Index
Set<String> shipments(); Set<String> shipments();
@Transient
static Draft draft(String region) {
return new Draft(region);
}
@Transient @Transient
default Draft update() { default Draft update() {
return new Draft(this); return new Draft(this);

View file

@ -5,13 +5,15 @@ import static net.helenus.core.Query.eq;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
public class HierarchyTest extends AbstractEmbeddedCassandraTest { public class HierarchyTest extends AbstractEmbeddedCassandraTest {
static Cat cat; static Cat cat;
@ -24,8 +26,7 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest {
@BeforeClass @BeforeClass
public static void beforeTest() { public static void beforeTest() {
session = session = Helenus.init(getSession()).showCql().add(Cat.class).add(Pig.class).autoCreateDrop().get();
Helenus.init(getSession()).showCql().add(Cat.class).add(Pig.class).autoCreateDrop().get();
cat = Helenus.dsl(Cat.class); cat = Helenus.dsl(Cat.class);
pig = Helenus.dsl(Pig.class); pig = Helenus.dsl(Pig.class);
} }
@ -38,21 +39,11 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void testCounter() throws TimeoutException { public void testCounter() throws TimeoutException {
session session.insert().value(cat::id, rnd.nextInt()).value(cat::nickname, "garfield").value(cat::eatable, false)
.insert()
.value(cat::id, rnd.nextInt())
.value(cat::nickname, "garfield")
.value(cat::eatable, false)
.sync();
session
.insert()
.value(pig::id, rnd.nextInt())
.value(pig::nickname, "porky")
.value(pig::eatable, true)
.sync(); .sync();
session.insert().value(pig::id, rnd.nextInt()).value(pig::nickname, "porky").value(pig::eatable, true).sync();
Optional<Cat> animal = Optional<Cat> animal = session.<Cat>select(Cat.class).where(cat::nickname, eq("garfield")).sync().findFirst();
session.<Cat>select(Cat.class).where(cat::nickname, eq("garfield")).sync().findFirst();
Assert.assertTrue(animal.isPresent()); Assert.assertTrue(animal.isPresent());
Assert.assertTrue(animal.get().warmBlodded()); Assert.assertTrue(animal.get().warmBlodded());
Assert.assertFalse(animal.get().eatable()); Assert.assertFalse(animal.get().eatable());
@ -60,14 +51,9 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void testDefaultMethod() throws TimeoutException { public void testDefaultMethod() throws TimeoutException {
session session.insert().value(cat::id, rnd.nextInt()).value(cat::nickname, "garfield").value(cat::eatable, false)
.insert()
.value(cat::id, rnd.nextInt())
.value(cat::nickname, "garfield")
.value(cat::eatable, false)
.sync(); .sync();
Optional<Cat> animal = Optional<Cat> animal = session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
Assert.assertTrue(animal.isPresent()); Assert.assertTrue(animal.isPresent());
Cat cat = animal.get(); Cat cat = animal.get();

View file

@ -16,13 +16,15 @@
package net.helenus.test.integration.core.index; package net.helenus.test.integration.core.index;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Query; import net.helenus.core.Query;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class SecondaryIndexTest extends AbstractEmbeddedCassandraTest { public class SecondaryIndexTest extends AbstractEmbeddedCassandraTest {
@ -39,15 +41,9 @@ public class SecondaryIndexTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void test() throws TimeoutException { public void test() throws TimeoutException {
session session.insert().value(book::id, 123L).value(book::isbn, "ABC").value(book::author, "Alex").sync();
.insert()
.value(book::id, 123L)
.value(book::isbn, "ABC")
.value(book::author, "Alex")
.sync();
long actualId = long actualId = session.select(book::id).where(book::isbn, Query.eq("ABC")).sync().findFirst().get()._1;
session.select(book::id).where(book::isbn, Query.eq("ABC")).sync().findFirst().get()._1;
Assert.assertEquals(123L, actualId); Assert.assertEquals(123L, actualId);
} }

View file

@ -16,6 +16,7 @@
package net.helenus.test.integration.core.prepared; package net.helenus.test.integration.core.prepared;
import java.math.BigDecimal; import java.math.BigDecimal;
import net.helenus.core.annotation.Cacheable; import net.helenus.core.annotation.Cacheable;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -15,8 +15,14 @@
*/ */
package net.helenus.test.integration.core.prepared; package net.helenus.test.integration.core.prepared;
import com.datastax.driver.core.ResultSet;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.datastax.driver.core.ResultSet;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Query; import net.helenus.core.Query;
@ -24,9 +30,6 @@ import net.helenus.core.operation.PreparedOperation;
import net.helenus.core.operation.PreparedStreamOperation; import net.helenus.core.operation.PreparedStreamOperation;
import net.helenus.support.Fun; import net.helenus.support.Fun;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class PreparedStatementTest extends AbstractEmbeddedCassandraTest { public class PreparedStatementTest extends AbstractEmbeddedCassandraTest {
@ -52,48 +55,22 @@ public class PreparedStatementTest extends AbstractEmbeddedCassandraTest {
session = Helenus.init(getSession()).showCql().add(Car.class).autoCreateDrop().get(); session = Helenus.init(getSession()).showCql().add(Car.class).autoCreateDrop().get();
car = Helenus.dsl(Car.class, session.getMetadata()); car = Helenus.dsl(Car.class, session.getMetadata());
insertOp = insertOp = session.<ResultSet>insert().value(car::make, Query.marker()).value(car::model, Query.marker())
session .value(car::year, 2004).prepare();
.<ResultSet>insert()
.value(car::make, Query.marker()) updateOp = session.update().set(car::price, Query.marker()).where(car::make, Query.eq(Query.marker()))
.value(car::model, Query.marker()) .and(car::model, Query.eq(Query.marker())).prepare();
.value(car::year, 2004)
selectOp = session.<Car>select(car).where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker())).prepare();
selectPriceOp = session.select(car::price).where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker())).prepare();
deleteOp = session.delete().where(car::make, Query.eq(Query.marker())).and(car::model, Query.eq(Query.marker()))
.prepare(); .prepare();
updateOp = countOp = session.count().where(car::make, Query.eq(Query.marker())).and(car::model, Query.eq(Query.marker()))
session
.update()
.set(car::price, Query.marker())
.where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker()))
.prepare();
selectOp =
session
.<Car>select(car)
.where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker()))
.prepare();
selectPriceOp =
session
.select(car::price)
.where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker()))
.prepare();
deleteOp =
session
.delete()
.where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker()))
.prepare();
countOp =
session
.count()
.where(car::make, Query.eq(Query.marker()))
.and(car::model, Query.eq(Query.marker()))
.prepare(); .prepare();
} }

View file

@ -18,13 +18,15 @@ package net.helenus.test.integration.core.simple;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.operation.InsertOperation; import net.helenus.core.operation.InsertOperation;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class InsertPartialTest extends AbstractEmbeddedCassandraTest { public class InsertPartialTest extends AbstractEmbeddedCassandraTest {
@ -45,8 +47,7 @@ public class InsertPartialTest extends AbstractEmbeddedCassandraTest {
map.put("id", id); map.put("id", id);
map.put("age", 5); map.put("age", 5);
InsertOperation<User> insert = session.<User>insert(Helenus.map(User.class, map)); InsertOperation<User> insert = session.<User>insert(Helenus.map(User.class, map));
String cql = String cql = "INSERT INTO simple_users (id,age) VALUES (" + id.toString() + ",5) IF NOT EXISTS;";
"INSERT INTO simple_users (id,age) VALUES (" + id.toString() + ",5) IF NOT EXISTS;";
Assert.assertEquals(cql, insert.cql()); Assert.assertEquals(cql, insert.cql());
insert.sync(); insert.sync();
} }

View file

@ -16,12 +16,8 @@
package net.helenus.test.integration.core.simple; package net.helenus.test.integration.core.simple;
import java.util.Date; import java.util.Date;
import net.helenus.mapping.annotation.ClusteringColumn;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.*;
import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.StaticColumn;
import net.helenus.mapping.annotation.Table;
import net.helenus.mapping.annotation.Types;
@Table @Table
public interface Message { public interface Message {

View file

@ -17,18 +17,21 @@ package net.helenus.test.integration.core.simple;
import static net.helenus.core.Query.eq; import static net.helenus.core.Query.eq;
import com.datastax.driver.core.ResultSet; import java.util.Optional;
import java.util.*;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.datastax.driver.core.ResultSet;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Operator; import net.helenus.core.Operator;
import net.helenus.core.operation.UpdateOperation; import net.helenus.core.operation.UpdateOperation;
import net.helenus.support.Fun; import net.helenus.support.Fun;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class SimpleUserTest extends AbstractEmbeddedCassandraTest { public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
@ -42,6 +45,120 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
user = Helenus.dsl(User.class, session.getMetadata()); user = Helenus.dsl(User.class, session.getMetadata());
} }
@Test
public void testCruid() throws Exception {
UserImpl newUser = new UserImpl();
newUser.id = 100L;
newUser.name = "alex";
newUser.age = 34;
newUser.type = UserType.USER;
// CREATE
session.upsert(newUser).sync();
// READ
// select row and map to entity
User actual = session.selectAll(User.class).mapTo(User.class).where(user::id, eq(100L)).sync().findFirst()
.get();
assertUsers(newUser, actual);
// select as object
actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
assertUsers(newUser, actual);
// select by columns
actual = session.select().column(user::id).column(user::name).column(user::age).column(user::type)
.mapTo(User.class).where(user::id, eq(100L)).sync().findFirst().get();
assertUsers(newUser, actual);
// select by columns
actual = session.select(User.class).mapTo(User.class).where(user::id, eq(100L)).sync().findFirst().get();
assertUsers(newUser, actual);
// select as object and mapTo
actual = session.select(user::id, user::name, user::age, user::type).mapTo(User.class).where(user::id, eq(100L))
.sync().findFirst().get();
assertUsers(newUser, actual);
// select single column
String name = session.select(user::name).where(user::id, eq(100L)).sync().findFirst().get()._1;
Assert.assertEquals(newUser.name(), name);
// select single column in array tuple
name = (String) session.select().column(user::name).where(user::id, eq(100L)).sync().findFirst().get()._a[0];
Assert.assertEquals(newUser.name(), name);
// UPDATE
session.update(user::name, "albert").set(user::age, 35).where(user::id, Operator.EQ, 100L).sync();
long cnt = session.count(user).where(user::id, Operator.EQ, 100L).sync();
Assert.assertEquals(1L, cnt);
name = session.select(user::name).where(user::id, Operator.EQ, 100L).map(t -> "_" + t._1).sync().findFirst()
.get();
Assert.assertEquals("_albert", name);
User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
Assert.assertEquals(Long.valueOf(100L), u2.id());
Assert.assertEquals("albert", u2.name());
Assert.assertEquals(Integer.valueOf(35), u2.age());
//
User greg = session.<User>insert(user).value(user::name, "greg").value(user::age, 44)
.value(user::type, UserType.USER).value(user::id, 1234L).sync();
Optional<User> maybeGreg = session.<User>select(user).where(user::id, eq(1234L)).single().sync();
// INSERT
session.update().set(user::name, null).set(user::age, null).set(user::type, null).where(user::id, eq(100L))
.zipkinContext(null).sync();
Fun.Tuple3<String, Integer, UserType> tuple = session.select(user::name, user::age, user::type)
.where(user::id, eq(100L)).sync().findFirst().get();
Assert.assertNull(tuple._1);
Assert.assertNull(tuple._2);
Assert.assertNull(tuple._3);
// DELETE
session.delete(user).where(user::id, eq(100L)).sync();
cnt = session.select().count().where(user::id, eq(100L)).sync();
Assert.assertEquals(0L, cnt);
}
public void testZipkin() throws TimeoutException {
session.update().set(user::name, null).set(user::age, null).set(user::type, null).where(user::id, eq(100L))
.zipkinContext(null).sync();
UpdateOperation<ResultSet> update = session.update();
update.set(user::name, null).zipkinContext(null).sync();
}
private void assertUsers(User expected, User actual) {
Assert.assertEquals(expected.id(), actual.id());
Assert.assertEquals(expected.name(), actual.name());
Assert.assertEquals(expected.age(), actual.age());
Assert.assertEquals(expected.type(), actual.type());
}
public static class UserImpl implements User { public static class UserImpl implements User {
Long id; Long id;
@ -69,190 +186,4 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
return type; return type;
} }
} }
@Test
public void testCruid() throws Exception {
UserImpl newUser = new UserImpl();
newUser.id = 100L;
newUser.name = "alex";
newUser.age = 34;
newUser.type = UserType.USER;
// CREATE
session.upsert(newUser).sync();
// READ
// select row and map to entity
User actual =
session
.selectAll(User.class)
.mapTo(User.class)
.where(user::id, eq(100L))
.sync()
.findFirst()
.get();
assertUsers(newUser, actual);
// select as object
actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
assertUsers(newUser, actual);
// select by columns
actual =
session
.select()
.column(user::id)
.column(user::name)
.column(user::age)
.column(user::type)
.mapTo(User.class)
.where(user::id, eq(100L))
.sync()
.findFirst()
.get();
assertUsers(newUser, actual);
// select by columns
actual =
session
.select(User.class)
.mapTo(User.class)
.where(user::id, eq(100L))
.sync()
.findFirst()
.get();
assertUsers(newUser, actual);
// select as object and mapTo
actual =
session
.select(user::id, user::name, user::age, user::type)
.mapTo(User.class)
.where(user::id, eq(100L))
.sync()
.findFirst()
.get();
assertUsers(newUser, actual);
// select single column
String name = session.select(user::name).where(user::id, eq(100L)).sync().findFirst().get()._1;
Assert.assertEquals(newUser.name(), name);
// select single column in array tuple
name =
(String)
session
.select()
.column(user::name)
.where(user::id, eq(100L))
.sync()
.findFirst()
.get()
._a[0];
Assert.assertEquals(newUser.name(), name);
// UPDATE
session
.update(user::name, "albert")
.set(user::age, 35)
.where(user::id, Operator.EQ, 100L)
.sync();
long cnt = session.count(user).where(user::id, Operator.EQ, 100L).sync();
Assert.assertEquals(1L, cnt);
name =
session
.select(user::name)
.where(user::id, Operator.EQ, 100L)
.map(t -> "_" + t._1)
.sync()
.findFirst()
.get();
Assert.assertEquals("_albert", name);
User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
Assert.assertEquals(Long.valueOf(100L), u2.id());
Assert.assertEquals("albert", u2.name());
Assert.assertEquals(Integer.valueOf(35), u2.age());
//
User greg =
session
.<User>insert(user)
.value(user::name, "greg")
.value(user::age, 44)
.value(user::type, UserType.USER)
.value(user::id, 1234L)
.sync();
Optional<User> maybeGreg =
session.<User>select(user).where(user::id, eq(1234L)).single().sync();
// INSERT
session
.update()
.set(user::name, null)
.set(user::age, null)
.set(user::type, null)
.where(user::id, eq(100L))
.zipkinContext(null)
.sync();
Fun.Tuple3<String, Integer, UserType> tuple =
session
.select(user::name, user::age, user::type)
.where(user::id, eq(100L))
.sync()
.findFirst()
.get();
Assert.assertNull(tuple._1);
Assert.assertNull(tuple._2);
Assert.assertNull(tuple._3);
// DELETE
session.delete(user).where(user::id, eq(100L)).sync();
cnt = session.select().count().where(user::id, eq(100L)).sync();
Assert.assertEquals(0L, cnt);
}
public void testZipkin() throws TimeoutException {
session
.update()
.set(user::name, null)
.set(user::age, null)
.set(user::type, null)
.where(user::id, eq(100L))
.zipkinContext(null)
.sync();
UpdateOperation<ResultSet> update = session.update();
update.set(user::name, null).zipkinContext(null).sync();
}
private void assertUsers(User expected, User actual) {
Assert.assertEquals(expected.id(), actual.id());
Assert.assertEquals(expected.name(), actual.name());
Assert.assertEquals(expected.age(), actual.age());
Assert.assertEquals(expected.type(), actual.type());
}
} }

View file

@ -19,13 +19,15 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Query; import net.helenus.core.Query;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class StaticColumnTest extends AbstractEmbeddedCassandraTest { public class StaticColumnTest extends AbstractEmbeddedCassandraTest {
@ -34,11 +36,7 @@ public class StaticColumnTest extends AbstractEmbeddedCassandraTest {
@BeforeClass @BeforeClass
public static void beforeTest() { public static void beforeTest() {
session = session = Helenus.init(getSession()).showCql().addPackage(Message.class.getPackage().getName()).autoCreateDrop()
Helenus.init(getSession())
.showCql()
.addPackage(Message.class.getPackage().getName())
.autoCreateDrop()
.get(); .get();
message = Helenus.dsl(Message.class, session.getMetadata()); message = Helenus.dsl(Message.class, session.getMetadata());
} }
@ -48,6 +46,71 @@ public class StaticColumnTest extends AbstractEmbeddedCassandraTest {
System.out.println(message); System.out.println(message);
} }
@Test
public void testCRUID() throws TimeoutException {
MessageImpl msg = new MessageImpl();
msg.id = 123;
msg.timestamp = new Date();
msg.from = "Alex";
msg.to = "Bob";
msg.msg = "hi";
// CREATE
session.insert(msg).sync();
msg.id = 123;
msg.to = "Craig";
session.insert(msg).sync();
// READ
List<Message> actual = session.<Message>select(message).where(message::id, Query.eq(123)).sync()
.collect(Collectors.toList());
Assert.assertEquals(2, actual.size());
Message toCraig = actual.stream().filter(m -> m.to().equals("Craig")).findFirst().get();
assertMessages(msg, toCraig);
// UPDATE
session.update().set(message::from, "Albert").where(message::id, Query.eq(123))
.onlyIf(message::from, Query.eq("Alex")).sync();
long cnt = session.select(message::from).where(message::id, Query.eq(123)).sync()
.filter(t -> t._1.equals("Albert")).count();
Assert.assertEquals(2, cnt);
// INSERT
session.update().set(message::from, null).where(message::id, Query.eq(123)).sync();
session.select(message::from).where(message::id, Query.eq(123)).sync().map(t -> t._1)
.forEach(Assert::assertNull);
session.update().set(message::from, "Alex").where(message::id, Query.eq(123))
.onlyIf(message::from, Query.eq(null)).sync();
// DELETE
session.delete().where(message::id, Query.eq(123)).sync();
cnt = session.count().where(message::id, Query.eq(123)).sync();
Assert.assertEquals(0, cnt);
}
private void assertMessages(Message expected, Message actual) {
Assert.assertEquals(expected.id(), actual.id());
Assert.assertEquals(expected.from(), actual.from());
Assert.assertEquals(expected.timestamp(), actual.timestamp());
Assert.assertEquals(expected.to(), actual.to());
Assert.assertEquals(expected.message(), actual.message());
}
private static class MessageImpl implements Message { private static class MessageImpl implements Message {
int id; int id;
@ -81,90 +144,4 @@ public class StaticColumnTest extends AbstractEmbeddedCassandraTest {
return msg; return msg;
} }
} }
@Test
public void testCRUID() throws TimeoutException {
MessageImpl msg = new MessageImpl();
msg.id = 123;
msg.timestamp = new Date();
msg.from = "Alex";
msg.to = "Bob";
msg.msg = "hi";
// CREATE
session.insert(msg).sync();
msg.id = 123;
msg.to = "Craig";
session.insert(msg).sync();
// READ
List<Message> actual =
session
.<Message>select(message)
.where(message::id, Query.eq(123))
.sync()
.collect(Collectors.toList());
Assert.assertEquals(2, actual.size());
Message toCraig = actual.stream().filter(m -> m.to().equals("Craig")).findFirst().get();
assertMessages(msg, toCraig);
// UPDATE
session
.update()
.set(message::from, "Albert")
.where(message::id, Query.eq(123))
.onlyIf(message::from, Query.eq("Alex"))
.sync();
long cnt =
session
.select(message::from)
.where(message::id, Query.eq(123))
.sync()
.filter(t -> t._1.equals("Albert"))
.count();
Assert.assertEquals(2, cnt);
// INSERT
session.update().set(message::from, null).where(message::id, Query.eq(123)).sync();
session
.select(message::from)
.where(message::id, Query.eq(123))
.sync()
.map(t -> t._1)
.forEach(Assert::assertNull);
session
.update()
.set(message::from, "Alex")
.where(message::id, Query.eq(123))
.onlyIf(message::from, Query.eq(null))
.sync();
// DELETE
session.delete().where(message::id, Query.eq(123)).sync();
cnt = session.count().where(message::id, Query.eq(123)).sync();
Assert.assertEquals(0, cnt);
}
private void assertMessages(Message expected, Message actual) {
Assert.assertEquals(expected.id(), actual.id());
Assert.assertEquals(expected.from(), actual.from());
Assert.assertEquals(expected.timestamp(), actual.timestamp());
Assert.assertEquals(expected.to(), actual.to());
Assert.assertEquals(expected.message(), actual.message());
}
} }

View file

@ -15,7 +15,6 @@
*/ */
package net.helenus.test.integration.core.simple; package net.helenus.test.integration.core.simple;
import net.helenus.core.annotation.Cacheable;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -16,6 +16,5 @@
package net.helenus.test.integration.core.simple; package net.helenus.test.integration.core.simple;
public enum UserType { public enum UserType {
USER, USER, ADMIN;
ADMIN;
} }

View file

@ -15,15 +15,13 @@
*/ */
package net.helenus.test.integration.core.simple; package net.helenus.test.integration.core.simple;
import java.lang.annotation.Documented; import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.helenus.mapping.annotation.Constraints; import net.helenus.mapping.annotation.Constraints;
@Documented @Documented
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraints.LowerCase @Constraints.LowerCase
public @interface Username {} public @interface Username {
}

View file

@ -17,6 +17,7 @@ package net.helenus.test.integration.core.tuple;
import com.datastax.driver.core.DataType; import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TupleValue; import com.datastax.driver.core.TupleValue;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -15,11 +15,12 @@
*/ */
package net.helenus.test.integration.core.tuple; package net.helenus.test.integration.core.tuple;
import net.helenus.core.Helenus;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
public class DslTest extends AbstractEmbeddedCassandraTest { public class DslTest extends AbstractEmbeddedCassandraTest {
@Test @Test

View file

@ -16,13 +16,15 @@
package net.helenus.test.integration.core.tuple; package net.helenus.test.integration.core.tuple;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Query; import net.helenus.core.Query;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class InnerTupleTest extends AbstractEmbeddedCassandraTest { public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
@ -44,8 +46,7 @@ public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void testCruid() throws TimeoutException { public void testCruid() throws TimeoutException {
Photo photo = Photo photo = new Photo() {
new Photo() {
@Override @Override
public byte[] blob() { public byte[] blob() {
@ -53,8 +54,7 @@ public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
} }
}; };
PhotoFolder folder = PhotoFolder folder = new PhotoFolder() {
new PhotoFolder() {
@Override @Override
public String name() { public String name() {
@ -73,27 +73,21 @@ public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
// READ (R) // READ (R)
PhotoFolder actual = PhotoFolder actual = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().findFirst()
session .get()._1;
.select(photoAlbum::folder)
.where(photoAlbum::id, Query.eq(123))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(folder.name(), actual.name()); Assert.assertEquals(folder.name(), actual.name());
// UPDATE (U) // UPDATE (U)
// unfortunately this is not working right now in Cassandra, can not update a single column in tuple :( // unfortunately this is not working right now in Cassandra, can not update a
//session.update() // single column in tuple :(
// session.update()
// .set(photoAlbum.folder().photo()::blob, "Helenus".getBytes()) // .set(photoAlbum.folder().photo()::blob, "Helenus".getBytes())
// .where(photoAlbum::id, eq(123)) // .where(photoAlbum::id, eq(123))
// .sync(); // .sync();
PhotoFolder expected = PhotoFolder expected = new PhotoFolder() {
new PhotoFolder() {
@Override @Override
public String name() { public String name() {
@ -108,14 +102,7 @@ public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
session.update().set(photoAlbum::folder, expected).where(photoAlbum::id, Query.eq(123)).sync(); session.update().set(photoAlbum::folder, expected).where(photoAlbum::id, Query.eq(123)).sync();
actual = actual = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().findFirst().get()._1;
session
.select(photoAlbum::folder)
.where(photoAlbum::id, Query.eq(123))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(expected.name(), actual.name()); Assert.assertEquals(expected.name(), actual.name());
@ -124,21 +111,13 @@ public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
session.update().set(photoAlbum::folder, null).where(photoAlbum::id, Query.eq(123)).sync(); session.update().set(photoAlbum::folder, null).where(photoAlbum::id, Query.eq(123)).sync();
actual = actual = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().findFirst().get()._1;
session
.select(photoAlbum::folder)
.where(photoAlbum::id, Query.eq(123))
.sync()
.findFirst()
.get()
._1;
Assert.assertNull(actual); Assert.assertNull(actual);
// DELETE (D) // DELETE (D)
session.delete().where(photoAlbum::id, Query.eq(123)).sync(); session.delete().where(photoAlbum::id, Query.eq(123)).sync();
long cnt = long cnt = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().count();
session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().count();
Assert.assertEquals(0, cnt); Assert.assertEquals(0, cnt);
} }
} }

View file

@ -17,17 +17,20 @@ package net.helenus.test.integration.core.tuple;
import static net.helenus.core.Query.eq; import static net.helenus.core.Query.eq;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TupleType;
import com.datastax.driver.core.TupleValue;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TupleType;
import com.datastax.driver.core.TupleValue;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
public class TupleTest extends AbstractEmbeddedCassandraTest { public class TupleTest extends AbstractEmbeddedCassandraTest {
static Album album; static Album album;
@ -49,8 +52,7 @@ public class TupleTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void testCruid() throws TimeoutException { public void testCruid() throws TimeoutException {
AlbumInformation info = AlbumInformation info = new AlbumInformation() {
new AlbumInformation() {
@Override @Override
public String about() { public String about() {
@ -69,22 +71,21 @@ public class TupleTest extends AbstractEmbeddedCassandraTest {
// READ (R) // READ (R)
AlbumInformation actual = AlbumInformation actual = session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
Assert.assertEquals(info.about(), actual.about()); Assert.assertEquals(info.about(), actual.about());
Assert.assertEquals(info.place(), actual.place()); Assert.assertEquals(info.place(), actual.place());
// UPDATE (U) // UPDATE (U)
// unfortunately this is not working right now in Cassandra, can not update a single column in tuple :( // unfortunately this is not working right now in Cassandra, can not update a
//session.update() // single column in tuple :(
// session.update()
// .set(album.info()::about, "Helenus") // .set(album.info()::about, "Helenus")
// .where(album::id, eq(123)) // .where(album::id, eq(123))
// .sync(); // .sync();
AlbumInformation expected = AlbumInformation expected = new AlbumInformation() {
new AlbumInformation() {
@Override @Override
public String about() { public String about() {
@ -134,8 +135,7 @@ public class TupleTest extends AbstractEmbeddedCassandraTest {
// READ (R) // READ (R)
TupleValue actual = TupleValue actual = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
Assert.assertEquals(info.getString(0), actual.getString(0)); Assert.assertEquals(info.getString(0), actual.getString(0));
Assert.assertEquals(info.getString(1), actual.getString(1)); Assert.assertEquals(info.getString(1), actual.getString(1));
@ -149,8 +149,7 @@ public class TupleTest extends AbstractEmbeddedCassandraTest {
session.update().set(album::infoNoMapping, expected).where(album::id, eq(555)).sync(); session.update().set(album::infoNoMapping, expected).where(album::id, eq(555)).sync();
actual = actual = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
Assert.assertEquals(expected.getString(0), actual.getString(0)); Assert.assertEquals(expected.getString(0), actual.getString(0));
Assert.assertEquals(expected.getString(1), actual.getString(1)); Assert.assertEquals(expected.getString(1), actual.getString(1));
@ -160,8 +159,7 @@ public class TupleTest extends AbstractEmbeddedCassandraTest {
session.update().set(album::infoNoMapping, null).where(album::id, eq(555)).sync(); session.update().set(album::infoNoMapping, null).where(album::id, eq(555)).sync();
actual = actual = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
Assert.assertNull(actual); Assert.assertNull(actual);
// DELETE (D) // DELETE (D)

View file

@ -18,6 +18,7 @@ package net.helenus.test.integration.core.tuplecollection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -15,11 +15,12 @@
*/ */
package net.helenus.test.integration.core.tuplecollection; package net.helenus.test.integration.core.tuplecollection;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.BeforeClass;
import org.junit.Test;
public abstract class TupleCollectionTest extends AbstractEmbeddedCassandraTest { public abstract class TupleCollectionTest extends AbstractEmbeddedCassandraTest {
@ -69,16 +70,23 @@ public abstract class TupleCollectionTest extends AbstractEmbeddedCassandraTest
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj)
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AuthorImpl other = (AuthorImpl) obj; AuthorImpl other = (AuthorImpl) obj;
if (city == null) { if (city == null) {
if (other.city != null) return false; if (other.city != null)
} else if (!city.equals(other.city)) return false; return false;
} else if (!city.equals(other.city))
return false;
if (name == null) { if (name == null) {
if (other.name != null) return false; if (other.name != null)
} else if (!name.equals(other.name)) return false; return false;
} else if (!name.equals(other.name))
return false;
return true; return true;
} }
@ -119,14 +127,20 @@ public abstract class TupleCollectionTest extends AbstractEmbeddedCassandraTest
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj)
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SectionImpl other = (SectionImpl) obj; SectionImpl other = (SectionImpl) obj;
if (page != other.page) return false; if (page != other.page)
return false;
if (title == null) { if (title == null) {
if (other.title != null) return false; if (other.title != null)
} else if (!title.equals(other.title)) return false; return false;
} else if (!title.equals(other.title))
return false;
return true; return true;
} }

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.tuplecollection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class TupleKeyMapTest extends TupleCollectionTest { public class TupleKeyMapTest extends TupleCollectionTest {
@Test @Test
@ -50,16 +52,13 @@ public class TupleKeyMapTest extends TupleCollectionTest {
// read full map // read full map
Map<Section, String> actualMap = Map<Section, String> actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualMaps(notes, actualMap); assertEqualMaps(notes, actualMap);
// read single key-value in map // read single key-value in map
String cql = String cql = session.select(Query.get(book::notes, new SectionImpl("first", 1))).where(book::id, Query.eq(id))
session
.select(Query.get(book::notes, new SectionImpl("first", 1)))
.where(book::id, Query.eq(id))
.cql(); .cql();
System.out.println("Still not supporting cql = " + cql); System.out.println("Still not supporting cql = " + cql);
@ -85,16 +84,14 @@ public class TupleKeyMapTest extends TupleCollectionTest {
expected.put(third, "v3"); expected.put(third, "v3");
session.update().put(book::notes, third, "v3").where(book::id, Query.eq(id)).sync(); session.update().put(book::notes, third, "v3").where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// putAll operation // putAll operation
expected.putAll(notes); expected.putAll(notes);
session.update().putAll(book::notes, notes).where(book::id, Query.eq(id)).sync(); session.update().putAll(book::notes, notes).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// put existing // put existing
@ -102,8 +99,7 @@ public class TupleKeyMapTest extends TupleCollectionTest {
expected.put(third, "v33"); expected.put(third, "v33");
session.update().put(book::notes, third, "v33").where(book::id, Query.eq(id)).sync(); session.update().put(book::notes, third, "v33").where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// DELETE // DELETE
@ -113,16 +109,14 @@ public class TupleKeyMapTest extends TupleCollectionTest {
expected.remove(third); expected.remove(third);
session.update().put(book::notes, third, null).where(book::id, Query.eq(id)).sync(); session.update().put(book::notes, third, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// remove full map // remove full map
session.update().set(book::notes, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::notes, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualMap); Assert.assertNull(actualMap);
// remove object // remove object
@ -137,8 +131,7 @@ public class TupleKeyMapTest extends TupleCollectionTest {
Assert.assertEquals(expected.size(), actual.size()); Assert.assertEquals(expected.size(), actual.size());
for (Section e : expected.keySet()) { for (Section e : expected.keySet()) {
Section a = Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
Assert.assertEquals(e.title(), a.title()); Assert.assertEquals(e.title(), a.title());
Assert.assertEquals(e.page(), a.page()); Assert.assertEquals(e.page(), a.page());
Assert.assertEquals(expected.get(e), actual.get(a)); Assert.assertEquals(expected.get(e), actual.get(a));

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.tuplecollection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class TupleListTest extends TupleCollectionTest { public class TupleListTest extends TupleCollectionTest {
@Test @Test
@ -49,8 +51,8 @@ public class TupleListTest extends TupleCollectionTest {
// read full list // read full list
List<Author> actualList = List<Author> actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualLists(authors, actualList); assertEqualLists(authors, actualList);
// read single value by index // read single value by index
@ -75,43 +77,33 @@ public class TupleListTest extends TupleCollectionTest {
// prepend operation // prepend operation
expected.add(0, new AuthorImpl("Prepend", "PrependCity")); expected.add(0, new AuthorImpl("Prepend", "PrependCity"));
session session.update().prepend(book::authors, new AuthorImpl("Prepend", "PrependCity")).where(book::id, Query.eq(id))
.update()
.prepend(book::authors, new AuthorImpl("Prepend", "PrependCity"))
.where(book::id, Query.eq(id))
.sync(); .sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// append operation // append operation
expected.add(new AuthorImpl("Append", "AppendCity")); expected.add(new AuthorImpl("Append", "AppendCity"));
session session.update().append(book::authors, new AuthorImpl("Append", "AppendCity")).where(book::id, Query.eq(id))
.update()
.append(book::authors, new AuthorImpl("Append", "AppendCity"))
.where(book::id, Query.eq(id))
.sync(); .sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// prependAll operation // prependAll operation
expected.addAll(0, authors); expected.addAll(0, authors);
session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync(); session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// appendAll operation // appendAll operation
expected.addAll(authors); expected.addAll(authors);
session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync(); session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// set by Index // set by Index
@ -120,8 +112,7 @@ public class TupleListTest extends TupleCollectionTest {
expected.set(5, inserted); expected.set(5, inserted);
session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync(); session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// DELETE // DELETE
@ -131,8 +122,7 @@ public class TupleListTest extends TupleCollectionTest {
expected.remove(inserted); expected.remove(inserted);
session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync(); session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// remove values // remove values
@ -140,16 +130,14 @@ public class TupleListTest extends TupleCollectionTest {
expected.removeAll(authors); expected.removeAll(authors);
session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync(); session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// remove full list // remove full list
session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualList); Assert.assertNull(actualList);
// remove object // remove object

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.tuplecollection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class TupleMapTest extends TupleCollectionTest { public class TupleMapTest extends TupleCollectionTest {
@Test @Test
@ -30,10 +32,8 @@ public class TupleMapTest extends TupleCollectionTest {
int id = 333; int id = 333;
Map<Section, Author> writers = new HashMap<Section, Author>(); Map<Section, Author> writers = new HashMap<Section, Author>();
writers.put( writers.put(new SectionImpl("first", 1), new TupleCollectionTest.AuthorImpl("Alex", "San Jose"));
new SectionImpl("first", 1), new TupleCollectionTest.AuthorImpl("Alex", "San Jose")); writers.put(new SectionImpl("second", 2), new TupleCollectionTest.AuthorImpl("Bob", "San Francisco"));
writers.put(
new SectionImpl("second", 2), new TupleCollectionTest.AuthorImpl("Bob", "San Francisco"));
// CREATE // CREATE
@ -43,8 +43,7 @@ public class TupleMapTest extends TupleCollectionTest {
// read full object // read full object
Book actual = Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
assertEqualMaps(writers, actual.writers()); assertEqualMaps(writers, actual.writers());
Assert.assertNull(actual.reviewers()); Assert.assertNull(actual.reviewers());
@ -53,16 +52,13 @@ public class TupleMapTest extends TupleCollectionTest {
// read full map // read full map
Map<Section, Author> actualMap = Map<Section, Author> actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualMaps(writers, actualMap); assertEqualMaps(writers, actualMap);
// read single key-value in map // read single key-value in map
String cql = String cql = session.select(Query.get(book::writers, new SectionImpl("first", 1))).where(book::id, Query.eq(id))
session
.select(Query.get(book::writers, new SectionImpl("first", 1)))
.where(book::id, Query.eq(id))
.cql(); .cql();
System.out.println("Still not supporting cql = " + cql); System.out.println("Still not supporting cql = " + cql);
@ -90,16 +86,14 @@ public class TupleMapTest extends TupleCollectionTest {
expected.put(third, unk); expected.put(third, unk);
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// putAll operation // putAll operation
expected.putAll(writers); expected.putAll(writers);
session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync(); session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// put existing // put existing
@ -107,8 +101,7 @@ public class TupleMapTest extends TupleCollectionTest {
expected.put(third, unk); expected.put(third, unk);
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// DELETE // DELETE
@ -118,16 +111,14 @@ public class TupleMapTest extends TupleCollectionTest {
expected.remove(third); expected.remove(third);
session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// remove full map // remove full map
session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualMap); Assert.assertNull(actualMap);
// remove object // remove object
@ -142,8 +133,7 @@ public class TupleMapTest extends TupleCollectionTest {
Assert.assertEquals(expected.size(), actual.size()); Assert.assertEquals(expected.size(), actual.size());
for (Section e : expected.keySet()) { for (Section e : expected.keySet()) {
Section a = Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
Assert.assertEquals(e.title(), a.title()); Assert.assertEquals(e.title(), a.title());
Assert.assertEquals(e.page(), a.page()); Assert.assertEquals(e.page(), a.page());

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.tuplecollection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class TupleSetTest extends TupleCollectionTest { public class TupleSetTest extends TupleCollectionTest {
@Test @Test
@ -50,29 +52,23 @@ public class TupleSetTest extends TupleCollectionTest {
session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync(); session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync();
Set<Author> actualSet = Set<Author> actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// add operation // add operation
expected.add(new AuthorImpl("Add", "AddCity")); expected.add(new AuthorImpl("Add", "AddCity"));
session session.update().add(book::reviewers, new AuthorImpl("Add", "AddCity")).where(book::id, Query.eq(id)).sync();
.update()
.add(book::reviewers, new AuthorImpl("Add", "AddCity"))
.where(book::id, Query.eq(id))
.sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// addAll operation // addAll operation
expected.addAll(reviewers); expected.addAll(reviewers);
session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync(); session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// DELETE // DELETE
@ -84,8 +80,7 @@ public class TupleSetTest extends TupleCollectionTest {
session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync(); session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// remove values // remove values
@ -94,16 +89,14 @@ public class TupleSetTest extends TupleCollectionTest {
expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get()); expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get());
session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync(); session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// remove full list // remove full list
session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualSet); Assert.assertNull(actualSet);
// remove object // remove object

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.tuplecollection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class TupleValueMapTest extends TupleCollectionTest { public class TupleValueMapTest extends TupleCollectionTest {
@Test @Test
@ -50,8 +52,8 @@ public class TupleValueMapTest extends TupleCollectionTest {
// read full map // read full map
Map<Integer, Section> actualMap = Map<Integer, Section> actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync()
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .findFirst().get()._1;
assertEqualMaps(contents, actualMap); assertEqualMaps(contents, actualMap);
// read single key-value in map // read single key-value in map
@ -81,16 +83,14 @@ public class TupleValueMapTest extends TupleCollectionTest {
expected.put(3, third); expected.put(3, third);
session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync(); session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// putAll operation // putAll operation
expected.putAll(contents); expected.putAll(contents);
session.update().putAll(book::contents, contents).where(book::id, Query.eq(id)).sync(); session.update().putAll(book::contents, contents).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// put existing // put existing
@ -99,8 +99,7 @@ public class TupleValueMapTest extends TupleCollectionTest {
expected.put(3, third); expected.put(3, third);
session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync(); session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// DELETE // DELETE
@ -110,16 +109,14 @@ public class TupleValueMapTest extends TupleCollectionTest {
expected.remove(3); expected.remove(3);
session.update().put(book::contents, 3, null).where(book::id, Query.eq(id)).sync(); session.update().put(book::contents, 3, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// remove full map // remove full map
session.update().set(book::contents, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::contents, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualMap); Assert.assertNull(actualMap);
// remove object // remove object

View file

@ -18,6 +18,7 @@ package net.helenus.test.integration.core.udtcollection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -15,11 +15,12 @@
*/ */
package net.helenus.test.integration.core.udtcollection; package net.helenus.test.integration.core.udtcollection;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.BeforeClass;
import org.junit.Test;
public abstract class UDTCollectionTest extends AbstractEmbeddedCassandraTest { public abstract class UDTCollectionTest extends AbstractEmbeddedCassandraTest {
@ -70,16 +71,23 @@ public abstract class UDTCollectionTest extends AbstractEmbeddedCassandraTest {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj)
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AuthorImpl other = (AuthorImpl) obj; AuthorImpl other = (AuthorImpl) obj;
if (city == null) { if (city == null) {
if (other.city != null) return false; if (other.city != null)
} else if (!city.equals(other.city)) return false; return false;
} else if (!city.equals(other.city))
return false;
if (name == null) { if (name == null) {
if (other.name != null) return false; if (other.name != null)
} else if (!name.equals(other.name)) return false; return false;
} else if (!name.equals(other.name))
return false;
return true; return true;
} }
@ -120,14 +128,20 @@ public abstract class UDTCollectionTest extends AbstractEmbeddedCassandraTest {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj)
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SectionImpl other = (SectionImpl) obj; SectionImpl other = (SectionImpl) obj;
if (page != other.page) return false; if (page != other.page)
return false;
if (title == null) { if (title == null) {
if (other.title != null) return false; if (other.title != null)
} else if (!title.equals(other.title)) return false; return false;
} else if (!title.equals(other.title))
return false;
return true; return true;
} }

View file

@ -21,6 +21,7 @@ import static net.helenus.core.Query.get;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -52,14 +53,13 @@ public class UDTKeyMapTest extends UDTCollectionTest {
// read full map // read full map
Map<Section, String> actualMap = Map<Section, String> actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst()
session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualMaps(notes, actualMap); assertEqualMaps(notes, actualMap);
// read single key-value in map // read single key-value in map
String cql = String cql = session.select(get(book::notes, new SectionImpl("first", 1))).where(book::id, eq(id)).cql();
session.select(get(book::notes, new SectionImpl("first", 1))).where(book::id, eq(id)).cql();
System.out.println("Still not supporting cql = " + cql); System.out.println("Still not supporting cql = " + cql);
@ -131,8 +131,7 @@ public class UDTKeyMapTest extends UDTCollectionTest {
Assert.assertEquals(expected.size(), actual.size()); Assert.assertEquals(expected.size(), actual.size());
for (Section e : expected.keySet()) { for (Section e : expected.keySet()) {
Section a = Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
Assert.assertEquals(e.title(), a.title()); Assert.assertEquals(e.title(), a.title());
Assert.assertEquals(e.page(), a.page()); Assert.assertEquals(e.page(), a.page());
Assert.assertEquals(expected.get(e), actual.get(a)); Assert.assertEquals(expected.get(e), actual.get(a));

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.udtcollection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class UDTListTest extends UDTCollectionTest { public class UDTListTest extends UDTCollectionTest {
@Test @Test
@ -49,8 +51,8 @@ public class UDTListTest extends UDTCollectionTest {
// read full list // read full list
List<Author> actualList = List<Author> actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualLists(authors, actualList); assertEqualLists(authors, actualList);
// read single value by index // read single value by index
@ -75,43 +77,33 @@ public class UDTListTest extends UDTCollectionTest {
// prepend operation // prepend operation
expected.add(0, new AuthorImpl("Prepend", "PrependCity")); expected.add(0, new AuthorImpl("Prepend", "PrependCity"));
session session.update().prepend(book::authors, new AuthorImpl("Prepend", "PrependCity")).where(book::id, Query.eq(id))
.update()
.prepend(book::authors, new AuthorImpl("Prepend", "PrependCity"))
.where(book::id, Query.eq(id))
.sync(); .sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// append operation // append operation
expected.add(new AuthorImpl("Append", "AppendCity")); expected.add(new AuthorImpl("Append", "AppendCity"));
session session.update().append(book::authors, new AuthorImpl("Append", "AppendCity")).where(book::id, Query.eq(id))
.update()
.append(book::authors, new AuthorImpl("Append", "AppendCity"))
.where(book::id, Query.eq(id))
.sync(); .sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// prependAll operation // prependAll operation
expected.addAll(0, authors); expected.addAll(0, authors);
session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync(); session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// appendAll operation // appendAll operation
expected.addAll(authors); expected.addAll(authors);
session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync(); session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// set by Index // set by Index
@ -120,8 +112,7 @@ public class UDTListTest extends UDTCollectionTest {
expected.set(5, inserted); expected.set(5, inserted);
session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync(); session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// DELETE // DELETE
@ -131,8 +122,7 @@ public class UDTListTest extends UDTCollectionTest {
expected.remove(inserted); expected.remove(inserted);
session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync(); session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// remove values // remove values
@ -140,16 +130,14 @@ public class UDTListTest extends UDTCollectionTest {
expected.removeAll(authors); expected.removeAll(authors);
session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync(); session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualLists(expected, actualList); assertEqualLists(expected, actualList);
// remove full list // remove full list
session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync();
actualList = actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualList); Assert.assertNull(actualList);
// remove object // remove object

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.udtcollection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class UDTMapTest extends UDTCollectionTest { public class UDTMapTest extends UDTCollectionTest {
@Test @Test
@ -50,16 +52,13 @@ public class UDTMapTest extends UDTCollectionTest {
// read full map // read full map
Map<Section, Author> actualMap = Map<Section, Author> actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualMaps(writers, actualMap); assertEqualMaps(writers, actualMap);
// read single key-value in map // read single key-value in map
String cql = String cql = session.select(Query.get(book::writers, new SectionImpl("first", 1))).where(book::id, Query.eq(id))
session
.select(Query.get(book::writers, new SectionImpl("first", 1)))
.where(book::id, Query.eq(id))
.cql(); .cql();
System.out.println("Still not supporting cql = " + cql); System.out.println("Still not supporting cql = " + cql);
@ -86,16 +85,14 @@ public class UDTMapTest extends UDTCollectionTest {
expected.put(third, unk); expected.put(third, unk);
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// putAll operation // putAll operation
expected.putAll(writers); expected.putAll(writers);
session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync(); session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// put existing // put existing
@ -103,8 +100,7 @@ public class UDTMapTest extends UDTCollectionTest {
expected.put(third, unk); expected.put(third, unk);
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// DELETE // DELETE
@ -114,16 +110,14 @@ public class UDTMapTest extends UDTCollectionTest {
expected.remove(third); expected.remove(third);
session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// remove full map // remove full map
session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync();
actualMap = actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualMap); Assert.assertNull(actualMap);
// remove object // remove object
@ -138,8 +132,7 @@ public class UDTMapTest extends UDTCollectionTest {
Assert.assertEquals(expected.size(), actual.size()); Assert.assertEquals(expected.size(), actual.size());
for (Section e : expected.keySet()) { for (Section e : expected.keySet()) {
Section a = Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
Assert.assertEquals(e.title(), a.title()); Assert.assertEquals(e.title(), a.title());
Assert.assertEquals(e.page(), a.page()); Assert.assertEquals(e.page(), a.page());

View file

@ -18,10 +18,12 @@ package net.helenus.test.integration.core.udtcollection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Query;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Query;
public class UDTSetTest extends UDTCollectionTest { public class UDTSetTest extends UDTCollectionTest {
@Test @Test
@ -50,29 +52,23 @@ public class UDTSetTest extends UDTCollectionTest {
session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync(); session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync();
Set<Author> actualSet = Set<Author> actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst()
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// add operation // add operation
expected.add(new AuthorImpl("Add", "AddCity")); expected.add(new AuthorImpl("Add", "AddCity"));
session session.update().add(book::reviewers, new AuthorImpl("Add", "AddCity")).where(book::id, Query.eq(id)).sync();
.update()
.add(book::reviewers, new AuthorImpl("Add", "AddCity"))
.where(book::id, Query.eq(id))
.sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// addAll operation // addAll operation
expected.addAll(reviewers); expected.addAll(reviewers);
session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync(); session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// DELETE // DELETE
@ -84,8 +80,7 @@ public class UDTSetTest extends UDTCollectionTest {
session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync(); session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// remove values // remove values
@ -94,16 +89,14 @@ public class UDTSetTest extends UDTCollectionTest {
expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get()); expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get());
session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync(); session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualSets(expected, actualSet); assertEqualSets(expected, actualSet);
// remove full list // remove full list
session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync(); session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync();
actualSet = actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
Assert.assertNull(actualSet); Assert.assertNull(actualSet);
// remove object // remove object

View file

@ -21,6 +21,7 @@ import static net.helenus.core.Query.get;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -52,8 +53,8 @@ public class UDTValueMapTest extends UDTCollectionTest {
// read full map // read full map
Map<Integer, Section> actualMap = Map<Integer, Section> actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst()
session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1; .get()._1;
assertEqualMaps(contents, actualMap); assertEqualMaps(contents, actualMap);
// read single key-value in map // read single key-value in map

View file

@ -18,13 +18,15 @@ package net.helenus.test.integration.core.unitofwork;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest { public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
@ -43,37 +45,26 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
uow5 = session.begin(); uow5 = session.begin();
uow3 = session.begin(uow5); uow3 = session.begin(uow5);
uow1 = session.begin(uow3); uow1 = session.begin(uow3);
uow1.commit() uow1.commit().andThen(() -> {
.andThen(
() -> {
q.add("1"); q.add("1");
}); });
uow2 = session.begin(uow3); uow2 = session.begin(uow3);
uow2.commit() uow2.commit().andThen(() -> {
.andThen(
() -> {
q.add("2"); q.add("2");
}); });
uow3.commit() uow3.commit().andThen(() -> {
.andThen(
() -> {
q.add("3"); q.add("3");
}); });
uow4 = session.begin(uow5); uow4 = session.begin(uow5);
uow4.commit() uow4.commit().andThen(() -> {
.andThen(
() -> {
q.add("4"); q.add("4");
}); });
uow5.commit() uow5.commit().andThen(() -> {
.andThen(
() -> {
q.add("5"); q.add("5");
}); });
System.out.println(q); System.out.println(q);
Assert.assertTrue( Assert.assertTrue(Arrays.equals(q.toArray(new String[5]), new String[]{"1", "2", "3", "4", "5"}));
Arrays.equals(q.toArray(new String[5]), new String[] {"1", "2", "3", "4", "5"}));
} }
@Test @Test
@ -86,34 +77,24 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
try { try {
uow3 = session.begin(uow4); uow3 = session.begin(uow4);
uow1 = session.begin(uow3); uow1 = session.begin(uow3);
uow1.commit() uow1.commit().andThen(() -> {
.andThen(
() -> {
q.add("1"); q.add("1");
}); });
uow2 = session.begin(uow3); uow2 = session.begin(uow3);
uow2.commit() uow2.commit().andThen(() -> {
.andThen(
() -> {
q.add("2"); q.add("2");
}); });
uow3.commit() uow3.commit().andThen(() -> {
.andThen(
() -> {
q.add("3"); q.add("3");
}); });
uow4.commit() uow4.commit().andThen(() -> {
.andThen(
() -> {
q.add("4"); q.add("4");
}); });
throw new Exception(); throw new Exception();
} catch (Exception e) { } catch (Exception e) {
uow4.abort(); uow4.abort();
} }
uow5.commit() uow5.commit().andThen(() -> {
.andThen(
() -> {
q.add("5"); q.add("5");
}); });
@ -137,9 +118,7 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
try (UnitOfWork uow = session.begin()) { try (UnitOfWork uow = session.begin()) {
unitOfWork = uow; unitOfWork = uow;
Assert.assertFalse(uow.hasAborted()); Assert.assertFalse(uow.hasAborted());
uow.commit() uow.commit().andThen(() -> {
.andThen(
() -> {
Assert.assertFalse(uow.hasAborted()); Assert.assertFalse(uow.hasAborted());
Assert.assertTrue(uow.hasCommitted()); Assert.assertTrue(uow.hasCommitted());
}); });

View file

@ -15,9 +15,12 @@
*/ */
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import com.datastax.driver.core.DataType.Name;
import java.util.Set; import java.util.Set;
import net.helenus.mapping.annotation.*;
import com.datastax.driver.core.DataType.Name;
import net.helenus.mapping.annotation.Types;
import net.helenus.mapping.annotation.UDT;
@UDT @UDT
public interface Directory extends FilesystemNode { public interface Directory extends FilesystemNode {

View file

@ -15,7 +15,8 @@
*/ */
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.UDT;
@UDT @UDT
public interface File extends FilesystemNode { public interface File extends FilesystemNode {

View file

@ -16,7 +16,11 @@
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import java.util.UUID; import java.util.UUID;
import net.helenus.mapping.annotation.*;
import net.helenus.mapping.annotation.ClusteringColumn;
import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table;
@Table("fs") @Table("fs")
public interface FilesystemNode { public interface FilesystemNode {

View file

@ -17,21 +17,24 @@ package net.helenus.test.integration.core.unitofwork;
import static net.helenus.core.Query.eq; import static net.helenus.core.Query.eq;
import com.datastax.driver.core.utils.UUIDs;
import java.util.UUID; import java.util.UUID;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.datastax.driver.core.utils.UUIDs;
import net.bytebuddy.utility.RandomString; import net.bytebuddy.utility.RandomString;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
import net.helenus.core.annotation.Cacheable; import net.helenus.core.annotation.Cacheable;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Constraints;
import net.helenus.mapping.annotation.Index; import net.helenus.mapping.annotation.Index;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
@Table @Table
@Cacheable @Cacheable
@ -39,8 +42,8 @@ interface Widget {
@PartitionKey @PartitionKey
UUID id(); UUID id();
@Column
@Index @Index
@Constraints.Distinct()
String name(); String name();
} }
@ -57,37 +60,29 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
@Test @Test
public void testSelectAfterSelect() throws Exception { public void testSelectAfterSelect() throws Exception {
Widget w1, w2, w3; Widget w1, w2, w3, w4;
UUID key = UUIDs.timeBased(); UUID key = UUIDs.timeBased();
// This should inserted Widget, but not cache it. // This should inserted Widget, but not cache it.
session w1 = session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync();
.<Widget>insert(widget)
.value(widget::id, key)
.value(widget::name, RandomString.make(20))
.sync();
try (UnitOfWork uow = session.begin()) { try (UnitOfWork uow = session.begin()) {
uow.setPurpose("testSelectAfterSelect"); uow.setPurpose("testSelectAfterSelect");
// This should read from the database and return a Widget. // This should read from the database and return a Widget.
w1 = w2 = session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
// This should read from the cache and get the same instance of a Widget. // This should read from the cache and get the same instance of a Widget.
w2 = w3 = session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
uow.commit() uow.commit().andThen(() -> {
.andThen( Assert.assertEquals(w2, w3);
() -> {
Assert.assertEquals(w1, w2);
}); });
} }
w3 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single().sync().orElse(null); w4 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single().sync().orElse(null);
Assert.assertEquals(w1, w3); Assert.assertEquals(w4, w1);
} }
@Test @Test
@ -98,52 +93,28 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
// This should inserted Widget, and not cache it in uow1. // This should inserted Widget, and not cache it in uow1.
try (UnitOfWork uow1 = session.begin()) { try (UnitOfWork uow1 = session.begin()) {
w1 = w1 = session.<Widget>insert(widget).value(widget::id, key1).value(widget::name, RandomString.make(20))
session
.<Widget>insert(widget)
.value(widget::id, key1)
.value(widget::name, RandomString.make(20))
.sync(uow1); .sync(uow1);
try (UnitOfWork uow2 = session.begin(uow1)) { try (UnitOfWork uow2 = session.begin(uow1)) {
// This should read from uow1's cache and return the same Widget. // This should read from uow1's cache and return the same Widget.
w2 = w2 = session.<Widget>select(widget).where(widget::id, eq(key1)).single().sync(uow2).orElse(null);
session
.<Widget>select(widget)
.where(widget::id, eq(key1))
.single()
.sync(uow2)
.orElse(null);
Assert.assertEquals(w1, w2); Assert.assertEquals(w1, w2);
w3 = w3 = session.<Widget>insert(widget).value(widget::id, key2).value(widget::name, RandomString.make(20))
session
.<Widget>insert(widget)
.value(widget::id, key2)
.value(widget::name, RandomString.make(20))
.sync(uow2); .sync(uow2);
uow2.commit() uow2.commit().andThen(() -> {
.andThen(
() -> {
Assert.assertEquals(w1, w2); Assert.assertEquals(w1, w2);
}); });
} }
// This should read from the cache and get the same instance of a Widget. // This should read from the cache and get the same instance of a Widget.
w4 = w4 = session.<Widget>select(widget).where(widget::id, eq(key2)).single().sync(uow1).orElse(null);
session
.<Widget>select(widget)
.where(widget::id, eq(key2))
.single()
.sync(uow1)
.orElse(null);
uow1.commit() uow1.commit().andThen(() -> {
.andThen(
() -> {
Assert.assertEquals(w3, w4); Assert.assertEquals(w3, w4);
}); });
} }
@ -156,84 +127,132 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
try (UnitOfWork uow = session.begin()) { try (UnitOfWork uow = session.begin()) {
// This should insert and cache Widget in the uow. // This should insert and cache Widget in the uow.
session session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync(uow);
.<Widget>insert(widget)
.value(widget::id, key)
.value(widget::name, RandomString.make(20))
.sync(uow);
// This should read from the database and return a Widget. // This should read from the database and return a Widget.
w1 = w1 = session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
session
.<Widget>select(widget)
.where(widget::id, eq(key))
.single()
.sync(uow)
.orElse(null);
// This should read from the cache and get the same instance of a Widget. // This should read from the cache and get the same instance of a Widget.
w2 = w2 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single().sync(uow).orElse(null);
session
.<Widget>select(widget)
.where(widget::name, eq(w1.name()))
.single()
.sync(uow)
.orElse(null);
uow.commit() uow.commit().andThen(() -> {
.andThen(
() -> {
Assert.assertEquals(w1, w2); Assert.assertEquals(w1, w2);
}); });
} }
} }
/*
@Test @Test
public void testSelectAfterInsertProperlyCachesEntity() throws Exception { public void testSelectAfterUpdated() throws Exception {
Widget w1, w2, w3, w4; Widget w1, w2, w3, w4, w5, w6;
UUID key = UUIDs.timeBased(); UUID key = UUIDs.timeBased();
// This should inserted Widget, but not cache it.
w1 = session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync();
try (UnitOfWork uow = session.begin()) { try (UnitOfWork uow = session.begin()) {
// This should cache the inserted Widget. // This should read from the database and return a Widget.
w1 = session.<Widget>insert(widget) w2 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
.value(widget::id, key) .sync(uow).orElse(null);
.value(widget::name, RandomString.make(20)) Assert.assertEquals(w1, w2);
// This should remove the object from the cache.
//TODO(gburd): w3 = session.
session.<Widget>update(w2)
.set(widget::name, "Bill")
.where(widget::id, eq(key))
.sync(uow); .sync(uow);
// This should read from the cache and get the same instance of a Widget. // Fetch from session cache, should have old name.
w2 = session.<Widget>select(widget) w4 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
.where(widget::id, eq(key)) .sync().orElse(null);
.single() Assert.assertEquals(w4, w2);
.sync(uow) Assert.assertEquals(w4.name(), w1.name());
.orElse(null);
uow.commit() // This should skip the cache.
.andThen(() -> { w5 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
.uncached()
.sync().orElse(null);
Assert.assertNotEquals(w5, w2); // Not the same instance
Assert.assertTrue(w2.equals(w5)); // But they have the same values
Assert.assertFalse(w5.equals(w2)); // TODO(gburd): should also work
Assert.assertEquals(w5.name(), "Bill");
uow.commit().andThen(() -> {
Assert.assertEquals(w1, w2); Assert.assertEquals(w1, w2);
}); });
} }
// This should read the widget from the session cache and maintain object identity. // The name changed, this should miss cache and not find anything in the database.
w3 = session.<Widget>select(widget) w6 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single()
.where(widget::id, eq(key)) .sync().orElse(null);
.single() Assert.assertTrue(w2.equals(w5));
.sync()
.orElse(null);
Assert.assertEquals(w1, w3);
// This should read the widget from the database, no object identity but values should match.
w4 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.ignoreCache()
.single()
.sync()
.orElse(null);
Assert.assertNotEquals(w1, w4);
Assert.assertTrue(w1.equals(w4));
} }
@Test
public void testSelectAfterDeleted() throws Exception {
Widget w1, w2, w3, w4;
UUID key = UUIDs.timeBased();
// This should inserted Widget, but not cache it.
w1 = session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync();
try (UnitOfWork uow = session.begin()) {
// This should read from the database and return a Widget.
w2 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
.sync(uow).orElse(null);
// This should remove the object from the cache.
session.delete(widget).where(widget::id, eq(key))
.sync(uow);
// This should fail to read from the cache.
w3 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
.sync(uow).orElse(null);
Assert.assertEquals(w3, null);
uow.commit().andThen(() -> {
Assert.assertEquals(w1, w2);
Assert.assertEquals(w3, null);
});
}
w4 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single()
.sync().orElse(null);
Assert.assertEquals(w4, null);
}
/*
* @Test public void testSelectAfterInsertProperlyCachesEntity() throws
* Exception { Widget w1, w2, w3, w4; UUID key = UUIDs.timeBased();
*
* try (UnitOfWork uow = session.begin()) {
*
* // This should cache the inserted Widget. w1 = session.<Widget>insert(widget)
* .value(widget::id, key) .value(widget::name, RandomString.make(20))
* .sync(uow);
*
* // This should read from the cache and get the same instance of a Widget. w2
* = session.<Widget>select(widget) .where(widget::id, eq(key)) .single()
* .sync(uow) .orElse(null);
*
* uow.commit() .andThen(() -> { Assert.assertEquals(w1, w2); }); }
*
* // This should read the widget from the session cache and maintain object
* identity. w3 = session.<Widget>select(widget) .where(widget::id, eq(key))
* .single() .sync() .orElse(null);
*
* Assert.assertEquals(w1, w3);
*
* // This should read the widget from the database, no object identity but
* values should match. w4 = session.<Widget>select(widget) .where(widget::id,
* eq(key)) .uncached() .single() .sync() .orElse(null);
*
* Assert.assertNotEquals(w1, w4); Assert.assertTrue(w1.equals(w4)); }
*/ */
} }

View file

@ -16,6 +16,7 @@
package net.helenus.test.integration.core.usertype; package net.helenus.test.integration.core.usertype;
import com.datastax.driver.core.UDTValue; import com.datastax.driver.core.UDTValue;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -15,8 +15,10 @@
*/ */
package net.helenus.test.integration.core.usertype; package net.helenus.test.integration.core.usertype;
import com.datastax.driver.core.DataType;
import java.util.Set; import java.util.Set;
import com.datastax.driver.core.DataType;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.Types; import net.helenus.mapping.annotation.Types;
import net.helenus.mapping.annotation.UDT; import net.helenus.mapping.annotation.UDT;

View file

@ -1,6 +1,7 @@
package net.helenus.test.integration.core.usertype; package net.helenus.test.integration.core.usertype;
import java.util.UUID; import java.util.UUID;
import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Column;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;

View file

@ -15,19 +15,22 @@
*/ */
package net.helenus.test.integration.core.usertype; package net.helenus.test.integration.core.usertype;
import com.google.common.collect.Sets;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.core.Query;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import com.google.common.collect.Sets;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.core.Query;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest { public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
static Customer customer; static Customer customer;
@ -47,7 +50,8 @@ public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
public static void afterTest() { public static void afterTest() {
session.getSession().execute("DROP TABLE IF EXISTS customer;"); session.getSession().execute("DROP TABLE IF EXISTS customer;");
session.getSession().execute("DROP TYPE IF EXISTS address_information;"); session.getSession().execute("DROP TYPE IF EXISTS address_information;");
// SchemaUtil.dropUserType(session.getSessionRepository().findUserType("address_information")), true); // SchemaUtil.dropUserType(session.getSessionRepository().findUserType("address_information")),
// true);
} }
@Test @Test
@ -61,8 +65,7 @@ public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
UUID id = UUID.randomUUID(); UUID id = UUID.randomUUID();
Address a = Address a = new Address() {
new Address() {
@Override @Override
public String street() { public String street() {
@ -90,8 +93,7 @@ public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
} }
}; };
AddressInformation ai = AddressInformation ai = new AddressInformation() {
new AddressInformation() {
@Override @Override
public Address address() { public Address address() {
@ -101,25 +103,16 @@ public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
session.insert().value(customer::id, id).value(customer::addressInformation, ai).sync(); session.insert().value(customer::id, id).value(customer::addressInformation, ai).sync();
String cql = String cql = session.update().set(customer.addressInformation().address()::street, "3 st")
session .where(customer::id, Query.eq(id)).cql();
.update()
.set(customer.addressInformation().address()::street, "3 st")
.where(customer::id, Query.eq(id))
.cql();
//TODO: System.out.println("At the time when this test was written Cassandra did not support queries like this: " + cql); // TODO: System.out.println("At the time when this test was written Cassandra
// did not support queries like this: " + cql);
session.update().set(customer::addressInformation, ai).where(customer::id, Query.eq(id)).sync(); session.update().set(customer::addressInformation, ai).where(customer::id, Query.eq(id)).sync();
String street = String street = session.select(customer.addressInformation().address()::street)
session .where(customer::id, Query.eq(id)).sync().findFirst().get()._1;
.select(customer.addressInformation().address()::street)
.where(customer::id, Query.eq(id))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals("1 st", street); Assert.assertEquals("1 st", street);

View file

@ -15,17 +15,20 @@
*/ */
package net.helenus.test.integration.core.usertype; package net.helenus.test.integration.core.usertype;
import com.datastax.driver.core.UDTValue;
import com.datastax.driver.core.UserType;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.datastax.driver.core.UDTValue;
import com.datastax.driver.core.UserType;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Query; import net.helenus.core.Query;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest { public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
@ -34,6 +37,129 @@ public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
static HelenusSession session; static HelenusSession session;
@BeforeClass
public static void beforeTest() {
session = Helenus.init(getSession()).showCql().add(Account.class).autoCreateDrop().get();
address = Helenus.dsl(Address.class);
account = Helenus.dsl(Account.class);
}
@Test
public void testPrint() {
System.out.println(address);
System.out.println(account);
}
@Test
public void testMappingCRUID() throws TimeoutException {
AddressImpl addr = new AddressImpl();
addr.street = "1 st";
addr.city = "San Jose";
AccountImpl acc = new AccountImpl();
acc.id = 123L;
acc.address = addr;
// CREATE
session.upsert(acc).sync();
// READ
String streetName = session.select(account.address()::street).where(account::id, Query.eq(123L)).sync()
.findFirst().get()._1;
Assert.assertEquals("1 st", streetName);
// UPDATE
AddressImpl expected = new AddressImpl();
expected.street = "2 st";
expected.city = "San Francisco";
session.update().set(account::address, expected).where(account::id, Query.eq(123L)).sync();
Address actual = session.select(account::address).where(account::id, Query.eq(123L)).sync().findFirst()
.get()._1;
Assert.assertEquals(expected.street(), actual.street());
Assert.assertEquals(expected.city(), actual.city());
Assert.assertNull(actual.country());
Assert.assertEquals(0, actual.zip());
// INSERT using UPDATE
session.update().set(account::address, null).where(account::id, Query.eq(123L)).sync();
Address adrNull = session.select(account::address).where(account::id, Query.eq(123L)).sync().findFirst()
.get()._1;
Assert.assertNull(adrNull);
// DELETE
session.delete().where(account::id, Query.eq(123L)).sync();
Long cnt = session.count().where(account::id, Query.eq(123L)).sync();
Assert.assertEquals(Long.valueOf(0), cnt);
}
@Test
public void testNoMapping() throws TimeoutException {
String ks = getSession().getLoggedKeyspace();
UserType addressType = getSession().getCluster().getMetadata().getKeyspace(ks).getUserType("address");
UDTValue addressNoMapping = addressType.newValue();
addressNoMapping.setString("line_1", "1st street");
addressNoMapping.setString("city", "San Jose");
AccountImpl acc = new AccountImpl();
acc.id = 777L;
acc.addressNoMapping = addressNoMapping;
// CREATE
session.upsert(acc).sync();
// READ
UDTValue found = session.select(account::addressNoMapping).where(account::id, Query.eq(777L)).sync().findFirst()
.get()._1;
Assert.assertEquals(addressNoMapping.getType(), found.getType());
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
// UPDATE
addressNoMapping = addressType.newValue();
addressNoMapping.setString("line_1", "Market street");
addressNoMapping.setString("city", "San Francisco");
session.update().set(account::addressNoMapping, addressNoMapping).where(account::id, Query.eq(777L)).sync();
found = session.select(account::addressNoMapping).where(account::id, Query.eq(777L)).sync().findFirst()
.get()._1;
Assert.assertEquals(addressNoMapping.getType(), found.getType());
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
// INSERT using UPDATE
session.update().set(account::addressNoMapping, null).where(account::id, Query.eq(777L)).sync();
found = session.select(account::addressNoMapping).where(account::id, Query.eq(777L)).sync().findFirst()
.get()._1;
Assert.assertNull(found);
// DELETE
session.delete().where(account::id, Query.eq(777L)).sync();
Long cnt = session.count().where(account::id, Query.eq(777L)).sync();
Assert.assertEquals(Long.valueOf(0), cnt);
}
public static class AccountImpl implements Account { public static class AccountImpl implements Account {
long id; long id;
@ -89,168 +215,4 @@ public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
return phones; return phones;
} }
} }
@BeforeClass
public static void beforeTest() {
session = Helenus.init(getSession()).showCql().add(Account.class).autoCreateDrop().get();
address = Helenus.dsl(Address.class);
account = Helenus.dsl(Account.class);
}
@Test
public void testPrint() {
System.out.println(address);
System.out.println(account);
}
@Test
public void testMappingCRUID() throws TimeoutException {
AddressImpl addr = new AddressImpl();
addr.street = "1 st";
addr.city = "San Jose";
AccountImpl acc = new AccountImpl();
acc.id = 123L;
acc.address = addr;
// CREATE
session.upsert(acc).sync();
// READ
String streetName =
session
.select(account.address()::street)
.where(account::id, Query.eq(123L))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals("1 st", streetName);
// UPDATE
AddressImpl expected = new AddressImpl();
expected.street = "2 st";
expected.city = "San Francisco";
session.update().set(account::address, expected).where(account::id, Query.eq(123L)).sync();
Address actual =
session
.select(account::address)
.where(account::id, Query.eq(123L))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(expected.street(), actual.street());
Assert.assertEquals(expected.city(), actual.city());
Assert.assertNull(actual.country());
Assert.assertEquals(0, actual.zip());
// INSERT using UPDATE
session.update().set(account::address, null).where(account::id, Query.eq(123L)).sync();
Address adrNull =
session
.select(account::address)
.where(account::id, Query.eq(123L))
.sync()
.findFirst()
.get()
._1;
Assert.assertNull(adrNull);
// DELETE
session.delete().where(account::id, Query.eq(123L)).sync();
Long cnt = session.count().where(account::id, Query.eq(123L)).sync();
Assert.assertEquals(Long.valueOf(0), cnt);
}
@Test
public void testNoMapping() throws TimeoutException {
String ks = getSession().getLoggedKeyspace();
UserType addressType =
getSession().getCluster().getMetadata().getKeyspace(ks).getUserType("address");
UDTValue addressNoMapping = addressType.newValue();
addressNoMapping.setString("line_1", "1st street");
addressNoMapping.setString("city", "San Jose");
AccountImpl acc = new AccountImpl();
acc.id = 777L;
acc.addressNoMapping = addressNoMapping;
// CREATE
session.upsert(acc).sync();
// READ
UDTValue found =
session
.select(account::addressNoMapping)
.where(account::id, Query.eq(777L))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(addressNoMapping.getType(), found.getType());
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
// UPDATE
addressNoMapping = addressType.newValue();
addressNoMapping.setString("line_1", "Market street");
addressNoMapping.setString("city", "San Francisco");
session
.update()
.set(account::addressNoMapping, addressNoMapping)
.where(account::id, Query.eq(777L))
.sync();
found =
session
.select(account::addressNoMapping)
.where(account::id, Query.eq(777L))
.sync()
.findFirst()
.get()
._1;
Assert.assertEquals(addressNoMapping.getType(), found.getType());
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
// INSERT using UPDATE
session.update().set(account::addressNoMapping, null).where(account::id, Query.eq(777L)).sync();
found =
session
.select(account::addressNoMapping)
.where(account::id, Query.eq(777L))
.sync()
.findFirst()
.get()
._1;
Assert.assertNull(found);
// DELETE
session.delete().where(account::id, Query.eq(777L)).sync();
Long cnt = session.count().where(account::id, Query.eq(777L)).sync();
Assert.assertEquals(Long.valueOf(0), cnt);
}
} }

View file

@ -2,18 +2,15 @@ package net.helenus.test.integration.core.views;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
import net.helenus.mapping.annotation.ClusteringColumn; import net.helenus.mapping.annotation.ClusteringColumn;
import net.helenus.mapping.annotation.CoveringIndex; import net.helenus.mapping.annotation.CoveringIndex;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;
@Table @Table
@CoveringIndex( @CoveringIndex(name = "cyclist_mv", covering = {"age", "birthday", "country"}, partitionKeys = {"age",
name = "cyclist_mv", "cid"}, clusteringColumns = {})
covering = {"age", "birthday", "country"},
partitionKeys = {"age", "cid"},
clusteringColumns = {}
)
public interface Cyclist { public interface Cyclist {
@ClusteringColumn @ClusteringColumn
UUID cid(); UUID cid();

View file

@ -2,8 +2,12 @@ package net.helenus.test.integration.core.views;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
import net.helenus.mapping.OrderingDirection; import net.helenus.mapping.OrderingDirection;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.ClusteringColumn;
import net.helenus.mapping.annotation.Index;
import net.helenus.mapping.annotation.MaterializedView;
import net.helenus.mapping.annotation.PartitionKey;
@MaterializedView @MaterializedView
public interface CyclistsByAge extends Cyclist { public interface CyclistsByAge extends Cyclist {

View file

@ -19,13 +19,16 @@ import static net.helenus.core.Query.eq;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.BeforeClass;
import org.junit.Test;
// See: https://docs.datastax.com/en/cql/3.3/cql/cql_using/useCreateMV.html // See: https://docs.datastax.com/en/cql/3.3/cql/cql_using/useCreateMV.html
// https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateMaterializedView.html // https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateMaterializedView.html
@ -48,26 +51,16 @@ public class MaterializedViewTest extends AbstractEmbeddedCassandraTest {
@BeforeClass @BeforeClass
public static void beforeTest() { public static void beforeTest() {
session = session = Helenus.init(getSession()).showCql().add(Cyclist.class).add(CyclistsByAge.class).autoCreateDrop()
Helenus.init(getSession())
.showCql()
.add(Cyclist.class)
.add(CyclistsByAge.class)
.autoCreateDrop()
.get(); .get();
cyclist = session.dsl(Cyclist.class); cyclist = session.dsl(Cyclist.class);
//try { try {
session session.insert(cyclist).value(cyclist::cid, UUID.randomUUID()).value(cyclist::age, 18)
.insert(cyclist) .value(cyclist::birthday, dateFromString("1997-02-08")).value(cyclist::country, "Netherlands")
.value(cyclist::cid, UUID.randomUUID()) .value(cyclist::name, "Pascal EENKHOORN").sync();
.value(cyclist::age, 18) } catch (TimeoutException e) {
.value(cyclist::birthday, dateFromString("1997-02-08")) }
.value(cyclist::country, "Netherlands")
.value(cyclist::name, "Pascal EENKHOORN")
.sync();
//} catch (TimeoutException e) {
//}
} }
@Test @Test

View file

@ -16,6 +16,7 @@
package net.helenus.test.performance.core.dsl; package net.helenus.test.performance.core.dsl;
import java.util.Map; import java.util.Map;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
public final class CachedElevatorImpl implements Elevator, MapExportable { public final class CachedElevatorImpl implements Elevator, MapExportable {

View file

@ -16,6 +16,7 @@
package net.helenus.test.performance.core.dsl; package net.helenus.test.performance.core.dsl;
import java.util.Map; import java.util.Map;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
public final class ElevatorImpl implements Elevator, MapExportable { public final class ElevatorImpl implements Elevator, MapExportable {

View file

@ -17,9 +17,11 @@ package net.helenus.test.performance.core.dsl;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.helenus.core.Helenus;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
public class MappingTest { public class MappingTest {
static Map<String, Object> fixture; static Map<String, Object> fixture;

View file

@ -18,6 +18,7 @@ package net.helenus.test.unit.core.dsl;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.helenus.core.reflect.Drafted; import net.helenus.core.reflect.Drafted;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.*;
@ -39,7 +40,7 @@ public interface Account {
return new Draft(); return new Draft();
} }
class Draft implements Drafted { //TODO class Draft implements Drafted { // TODO
@Override @Override
public Set<String> mutated() { public Set<String> mutated() {

View file

@ -15,10 +15,12 @@
*/ */
package net.helenus.test.unit.core.dsl; package net.helenus.test.unit.core.dsl;
import com.datastax.driver.core.DataType.Name;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.datastax.driver.core.DataType.Name;
import net.helenus.mapping.annotation.PartitionKey; import net.helenus.mapping.annotation.PartitionKey;
import net.helenus.mapping.annotation.Table; import net.helenus.mapping.annotation.Table;
import net.helenus.mapping.annotation.Types; import net.helenus.mapping.annotation.Types;

View file

@ -15,14 +15,15 @@
*/ */
package net.helenus.test.unit.core.dsl; package net.helenus.test.unit.core.dsl;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import net.helenus.core.Getter; import net.helenus.core.Getter;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.Query; import net.helenus.core.Query;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.support.DslPropertyException; import net.helenus.support.DslPropertyException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class CollectionsDlsTest { public class CollectionsDlsTest {

View file

@ -15,11 +15,12 @@
*/ */
package net.helenus.test.unit.core.dsl; package net.helenus.test.unit.core.dsl;
import net.helenus.core.Helenus;
import net.helenus.support.DslPropertyException;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.support.DslPropertyException;
public class DslTest { public class DslTest {
static Account account; static Account account;

View file

@ -17,10 +17,12 @@ package net.helenus.test.unit.core.dsl;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.helenus.core.Helenus;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
public class UDTCollectionsDlsTest { public class UDTCollectionsDlsTest {
@Test @Test

View file

@ -17,11 +17,13 @@ package net.helenus.test.unit.core.dsl;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.helenus.core.Helenus;
import net.helenus.support.HelenusException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.support.HelenusException;
public class WrapperTest { public class WrapperTest {
@Test @Test
@ -42,10 +44,14 @@ public class WrapperTest {
@Test @Test
public void testPrimitive() throws Exception { public void testPrimitive() throws Exception {
// NOTE: noramlly a ValueProviderMap for the entity would include all keys for an entity // NOTE: noramlly a ValueProviderMap for the entity would include all keys for
// at creation time. This test need to validate that MapperInvocationHander will return // an entity
// the correct default value for an entity, the twist is that if the key doesn't exist // at creation time. This test need to validate that MapperInvocationHander will
// in the map then it returns null (so as to support the partial update feature). Here we // return
// the correct default value for an entity, the twist is that if the key doesn't
// exist
// in the map then it returns null (so as to support the partial update
// feature). Here we
// need to setup the test with a null value for the key we'd like to test. // need to setup the test with a null value for the key we'd like to test.
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();

View file

@ -18,10 +18,12 @@ package net.helenus.test.unit.support;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.helenus.support.Immutables;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.support.Immutables;
public class ImmutablesTest { public class ImmutablesTest {
@Test @Test

View file

@ -19,10 +19,12 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import net.helenus.support.Transformers;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import net.helenus.support.Transformers;
public class TransformersTest { public class TransformersTest {
@Test @Test

View file

@ -13,18 +13,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# for production, you should probably set the root to INFO # for production, you should probably set the root to INFO
# and the pattern to %c instead of %l. (%l is slower.) # and the pattern to %c instead of %l. (%l is slower.)
# output messages into a rolling log file as well as stdout # output messages into a rolling log file as well as stdout
log4j.rootLogger=ERROR,stdout log4j.rootLogger=ERROR,stdout
# stdout # stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c{3} - %m%n log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c{3} - %m%n
log4j.appender.stdout.follow=true log4j.appender.stdout.follow=true
log4j.logger.org.apache=WARN log4j.logger.org.apache=WARN
log4j.logger.org.cassandraunit=ERROR log4j.logger.org.cassandraunit=ERROR

View file

@ -1 +1 @@
handlers = org.slf4j.bridge.SLF4JBridgeHandler handlers=org.slf4j.bridge.SLF4JBridgeHandler