-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CASSANDRA-20155: To improve accord interoperability test coverage, nehttps://github.com/dcapwell/cassandra/pull/new/CASSANDRA-20155 #3753
base: cep-15-accord
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -387,7 +387,15 @@ public ResultMessage execute(QueryState state, QueryOptions options, Dispatcher. | |
|
||
// check again since now we have query options; note that statements are quaranted to be single partition reads at this point | ||
for (NamedSelect assignment : assignments) | ||
{ | ||
checkFalse(isSelectingMultipleClusterings(assignment.select, options), INCOMPLETE_PRIMARY_KEY_SELECT_MESSAGE, "LET assignment", assignment.select.source); | ||
if (assignment.select.getRestrictions().keyIsInRelation()) | ||
checkTrue(assignment.select.getLimit(options) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", assignment.select.source); | ||
} | ||
if (returningSelect != null && returningSelect.select.getRestrictions().keyIsInRelation()) | ||
{ | ||
checkTrue(returningSelect.select.getLimit(options) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", returningSelect.select.source); | ||
} | ||
|
||
Txn txn = createTxn(state.getClientState(), options); | ||
|
||
|
@@ -492,8 +500,9 @@ private static void validate(SelectStatement prepared) | |
if (prepared.hasAggregation()) | ||
throw invalidRequest(NO_AGGREGATION_IN_TXNS_MESSAGE, "SELECT", prepared.source); | ||
|
||
// when "LIMIT ?" this check can't be performed, so need to do again once the options are known | ||
if (prepared.getRestrictions().keyIsInRelation()) | ||
checkTrue(prepared.getLimit(null) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", prepared.source); | ||
checkTrue(prepared.isLimitMarker() || prepared.getLimit(null) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", prepared.source); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when |
||
} | ||
|
||
public static class Parsed extends QualifiedStatement.Composite | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,7 @@ private static Query read(String ks, String table, List<ByteBuffer> keys) | |
assert !keys.isEmpty(); | ||
Txn.Builder builder = new Txn.Builder(); | ||
for (int i = 0; i < keys.size(); i++) | ||
builder.addLet("row" + i, new Select.Builder().withWildcard().withTable(ks, table).withColumnEquals("pk", keys.get(i))); | ||
builder.addLet("row" + i, new Select.Builder().wildcard().table(ks, table).value("pk", keys.get(i))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in this case |
||
builder.addReturnReferences("row0.pk"); | ||
Txn txn = builder.build(); | ||
ByteBuffer[] binds = txn.bindsEncoded(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,8 +46,15 @@ | |
import accord.utils.RandomSource; | ||
import org.apache.cassandra.config.CassandraRelevantProperties; | ||
import org.apache.cassandra.config.Config; | ||
import org.apache.cassandra.cql3.ast.CQLFormatter; | ||
import org.apache.cassandra.cql3.ast.Mutation; | ||
import org.apache.cassandra.cql3.ast.Select; | ||
import org.apache.cassandra.cql3.ast.StandardVisitors; | ||
import org.apache.cassandra.cql3.ast.Statement; | ||
import org.apache.cassandra.cql3.ast.Txn; | ||
import org.apache.cassandra.db.marshal.AsciiType; | ||
import org.apache.cassandra.db.marshal.BytesType; | ||
import org.apache.cassandra.db.marshal.UTF8Type; | ||
import org.apache.cassandra.distributed.Cluster; | ||
import org.apache.cassandra.distributed.api.ConsistencyLevel; | ||
import org.apache.cassandra.distributed.api.IInstanceConfig; | ||
|
@@ -59,23 +66,38 @@ | |
import org.apache.cassandra.service.accord.api.AccordAgent; | ||
import org.apache.cassandra.service.consensus.TransactionalMode; | ||
import org.apache.cassandra.utils.ASTGenerators; | ||
import org.apache.cassandra.utils.AbstractTypeGenerators; | ||
import org.apache.cassandra.utils.CassandraGenerators; | ||
import org.apache.cassandra.utils.FastByteOperations; | ||
import org.apache.cassandra.utils.Generators; | ||
import org.apache.cassandra.utils.Isolated; | ||
import org.apache.cassandra.utils.Shared; | ||
import org.quicktheories.generators.SourceDSL; | ||
|
||
import static org.apache.cassandra.utils.AbstractTypeGenerators.overridePrimitiveTypeSupport; | ||
import static org.apache.cassandra.utils.AbstractTypeGenerators.stringComparator; | ||
import static org.apache.cassandra.utils.AccordGenerators.fromQT; | ||
|
||
public class AccordTopologyMixupTest extends TopologyMixupTestBase<AccordTopologyMixupTest.Spec> | ||
{ | ||
private static final Logger logger = LoggerFactory.getLogger(AccordTopologyMixupTest.class); | ||
|
||
/** | ||
* Should the history show the CQL? By default, this is off as its very verbose, but when debugging this can be helpful. | ||
*/ | ||
private static final boolean HISTORY_SHOWS_CQL = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the changes to this class are not needed for this patch, nor for the model... but they are here for the following reasons
|
||
|
||
static | ||
{ | ||
CassandraRelevantProperties.ACCORD_AGENT_CLASS.setString(InterceptAgent.class.getName()); | ||
// enable most expensive debugging checks | ||
CassandraRelevantProperties.ACCORD_KEY_PARANOIA_CPU.setString(Invariants.Paranoia.QUADRATIC.name()); | ||
CassandraRelevantProperties.ACCORD_KEY_PARANOIA_MEMORY.setString(Invariants.Paranoia.QUADRATIC.name()); | ||
CassandraRelevantProperties.ACCORD_KEY_PARANOIA_COSTFACTOR.setString(Invariants.ParanoiaCostFactor.HIGH.name()); | ||
|
||
overridePrimitiveTypeSupport(AsciiType.instance, AbstractTypeGenerators.TypeSupport.of(AsciiType.instance, SourceDSL.strings().ascii().ofLengthBetween(1, 10), stringComparator(AsciiType.instance))); | ||
overridePrimitiveTypeSupport(UTF8Type.instance, AbstractTypeGenerators.TypeSupport.of(UTF8Type.instance, Generators.utf8(1, 10), stringComparator(UTF8Type.instance))); | ||
overridePrimitiveTypeSupport(BytesType.instance, AbstractTypeGenerators.TypeSupport.of(BytesType.instance, Generators.bytes(1, 10), FastByteOperations::compareUnsigned)); | ||
} | ||
|
||
private static final List<TransactionalMode> TRANSACTIONAL_MODES = Stream.of(TransactionalMode.values()).filter(t -> t.accordIsEnabled).collect(Collectors.toList()); | ||
|
@@ -97,13 +119,18 @@ private static Spec createSchemaSpec(RandomSource rs, Cluster cluster) | |
{ | ||
TransactionalMode mode = rs.pick(TRANSACTIONAL_MODES); | ||
boolean enableMigration = allowsMigration(mode) && rs.nextBoolean(); | ||
// This test puts a focus on topology / cluster operations, so schema "shouldn't matter"... limit the domain of the test to improve the ability to debug | ||
AbstractTypeGenerators.TypeGenBuilder supportedTypes = AbstractTypeGenerators.withoutUnsafeEquality(AbstractTypeGenerators.builder() | ||
.withTypeKinds(AbstractTypeGenerators.TypeKind.PRIMITIVE)); | ||
TableMetadata metadata = fromQT(new CassandraGenerators.TableMetadataBuilder() | ||
.withKeyspaceName(KEYSPACE) | ||
.withTableName("tbl") | ||
.withTableKinds(TableMetadata.Kind.REGULAR) | ||
.withKnownMemtables() | ||
.withSimpleColumnNames() | ||
//TODO (coverage): include "fast_path = 'keyspace'" override | ||
.withTransactionalMode(enableMigration ? TransactionalMode.off : mode) | ||
.withoutEmpty() | ||
.withDefaultTypeGen(supportedTypes) | ||
.build()) | ||
.next(rs); | ||
maybeCreateUDTs(cluster, metadata); | ||
|
@@ -133,14 +160,16 @@ private static CommandGen<Spec> cqlOperations(Spec spec) | |
|
||
private static Command<State<Spec>, Void, ?> cqlOperation(RandomSource rs, State<Spec> state, Gen<Statement> statementGen) | ||
{ | ||
Statement stmt = statementGen.next(rs); | ||
String cql; | ||
//TODO (usability): are there any transaction_modes that actually need simple mutations/select to be wrapped in a BEGIN TRANSACTION? If not then this logica can be simplified | ||
if (stmt.kind() == Statement.Kind.TXN || stmt.kind() == Statement.Kind.MUTATION && ((Mutation) stmt).isCas()) | ||
cql = stmt.toCQL(); | ||
else cql = wrapInTxn(stmt.toCQL()); | ||
Statement stmt = statementGen.map(s -> { | ||
if (s.kind() == Statement.Kind.TXN || s.kind() == Statement.Kind.MUTATION && ((Mutation) s).isCas()) | ||
return s; | ||
return s instanceof Select ? Txn.wrap((Select) s) : Txn.wrap((Mutation) s); | ||
}).next(rs); | ||
IInvokableInstance node = state.cluster.get(rs.pickInt(state.topologyHistory.up())); | ||
return new Property.SimpleCommand<>(node + ": " + stmt.kind() + "; epoch=" + state.currentEpoch.get(), s2 -> executeTxn(s2.cluster, node, cql, stmt.bindsEncoded())); | ||
String msg = HISTORY_SHOWS_CQL ? | ||
"\n" + stmt.visit(StandardVisitors.DEBUG).toCQL(new CQLFormatter.PrettyPrint()) + "\n" | ||
: stmt.kind() == Statement.Kind.MUTATION ? ((Mutation) stmt).mutationKind().name() : stmt.kind().name(); | ||
return new Property.SimpleCommand<>(node + ":" + msg + "; epoch=" + state.currentEpoch.get(), s2 -> executeTxn(s2.cluster, node, stmt.toCQL(), stmt.bindsEncoded())); | ||
} | ||
|
||
private static boolean allowsMigration(TransactionalMode mode) | ||
|
@@ -199,6 +228,12 @@ public String keyspace() | |
{ | ||
return metadata.keyspace; | ||
} | ||
|
||
@Override | ||
public String createSchema() | ||
{ | ||
return metadata.toCqlString(false, false, false); | ||
} | ||
} | ||
|
||
private static class AccordState extends State<Spec> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when
LIMIT ?
we are not able to validate, so need to rerun the validation here