use of org.apache.cassandra.exceptions.PreparedQueryNotFoundException in project cassandra by apache.
the class BatchMessage method execute.
public Message.Response execute(QueryState state, long queryStartNanoTime) {
try {
UUID tracingId = null;
if (isTracingRequested()) {
tracingId = UUIDGen.getTimeUUID();
state.prepareTracingSession(tracingId);
}
if (state.traceNextQuery()) {
state.createTracingSession();
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
if (options.getConsistency() != null)
builder.put("consistency_level", options.getConsistency().name());
if (options.getSerialConsistency() != null)
builder.put("serial_consistency_level", options.getSerialConsistency().name());
// TODO we don't have [typed] access to CQL bind variables here. CASSANDRA-4560 is open to add support.
Tracing.instance.begin("Execute batch of CQL3 queries", state.getClientAddress(), builder.build());
}
QueryHandler handler = ClientState.getCQLQueryHandler();
List<ParsedStatement.Prepared> prepared = new ArrayList<>(queryOrIdList.size());
for (int i = 0; i < queryOrIdList.size(); i++) {
Object query = queryOrIdList.get(i);
ParsedStatement.Prepared p;
if (query instanceof String) {
p = QueryProcessor.parseStatement((String) query, state);
} else {
p = handler.getPrepared((MD5Digest) query);
if (p == null)
throw new PreparedQueryNotFoundException((MD5Digest) query);
}
List<ByteBuffer> queryValues = values.get(i);
if (queryValues.size() != p.statement.getBoundTerms())
throw new InvalidRequestException(String.format("There were %d markers(?) in CQL but %d bound variables", p.statement.getBoundTerms(), queryValues.size()));
prepared.add(p);
}
BatchQueryOptions batchOptions = BatchQueryOptions.withPerStatementVariables(options, values, queryOrIdList);
List<ModificationStatement> statements = new ArrayList<>(prepared.size());
for (int i = 0; i < prepared.size(); i++) {
ParsedStatement.Prepared p = prepared.get(i);
batchOptions.prepareStatement(i, p.boundNames);
if (!(p.statement instanceof ModificationStatement))
throw new InvalidRequestException("Invalid statement in batch: only UPDATE, INSERT and DELETE statements are allowed.");
statements.add((ModificationStatement) p.statement);
}
// Note: It's ok at this point to pass a bogus value for the number of bound terms in the BatchState ctor
// (and no value would be really correct, so we prefer passing a clearly wrong one).
BatchStatement batch = new BatchStatement(-1, batchType, statements, Attributes.none());
Message.Response response = handler.processBatch(batch, state, batchOptions, getCustomPayload(), queryStartNanoTime);
if (tracingId != null)
response.setTracingId(tracingId);
return response;
} catch (Exception e) {
JVMStabilityInspector.inspectThrowable(e);
return ErrorMessage.fromException(e);
} finally {
Tracing.instance.stopSession();
}
}
use of org.apache.cassandra.exceptions.PreparedQueryNotFoundException in project cassandra by apache.
the class ExecuteMessage method execute.
public Message.Response execute(QueryState state, long queryStartNanoTime) {
try {
QueryHandler handler = ClientState.getCQLQueryHandler();
ParsedStatement.Prepared prepared = handler.getPrepared(statementId);
if (prepared == null)
throw new PreparedQueryNotFoundException(statementId);
options.prepare(prepared.boundNames);
CQLStatement statement = prepared.statement;
if (options.getPageSize() == 0)
throw new ProtocolException("The page size cannot be 0");
UUID tracingId = null;
if (isTracingRequested()) {
tracingId = UUIDGen.getTimeUUID();
state.prepareTracingSession(tracingId);
}
if (state.traceNextQuery()) {
state.createTracingSession(getCustomPayload());
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
if (options.getPageSize() > 0)
builder.put("page_size", Integer.toString(options.getPageSize()));
if (options.getConsistency() != null)
builder.put("consistency_level", options.getConsistency().name());
if (options.getSerialConsistency() != null)
builder.put("serial_consistency_level", options.getSerialConsistency().name());
builder.put("query", prepared.rawCQLStatement);
for (int i = 0; i < prepared.boundNames.size(); i++) {
ColumnSpecification cs = prepared.boundNames.get(i);
String boundName = cs.name.toString();
String boundValue = cs.type.asCQL3Type().toCQLLiteral(options.getValues().get(i), options.getProtocolVersion());
if (boundValue.length() > 1000) {
boundValue = boundValue.substring(0, 1000) + "...'";
}
//Here we prefix boundName with the index to avoid possible collission in builder keys due to
//having multiple boundValues for the same variable
builder.put("bound_var_" + Integer.toString(i) + "_" + boundName, boundValue);
}
Tracing.instance.begin("Execute CQL3 prepared query", state.getClientAddress(), builder.build());
}
// Some custom QueryHandlers are interested by the bound names. We provide them this information
// by wrapping the QueryOptions.
QueryOptions queryOptions = QueryOptions.addColumnSpecifications(options, prepared.boundNames);
Message.Response response = handler.processPrepared(statement, state, queryOptions, getCustomPayload(), queryStartNanoTime);
if (options.skipMetadata() && response instanceof ResultMessage.Rows)
((ResultMessage.Rows) response).result.metadata.setSkipMetadata();
if (tracingId != null)
response.setTracingId(tracingId);
return response;
} catch (Exception e) {
JVMStabilityInspector.inspectThrowable(e);
return ErrorMessage.fromException(e);
} finally {
Tracing.instance.stopSession();
}
}
use of org.apache.cassandra.exceptions.PreparedQueryNotFoundException in project cassandra by apache.
the class PreparedStatementsTest method testMetadataFlagsWithLWTs.
@Test
public void testMetadataFlagsWithLWTs() throws Throwable {
// Verify the behavior of CASSANDRA-10786 (result metadata IDs) on the protocol level.
// Tests are against an LWT statement and a "regular" SELECT statement.
// The fundamental difference between a SELECT and an LWT statement is that the result metadata
// of an LWT can change between invocations - therefore we always return the resultset metadata
// for LWTs. For "normal" SELECTs, the resultset metadata can only change when DDLs happen
// (aka the famous prepared 'SELECT * FROM ks.tab' stops working after the schema of that table
// changes). In those cases, the Result.Rows message contains a METADATA_CHANGED flag to tell
// clients that the cached metadata for this statement has changed and is included in the result,
// whereas the resultset metadata is omitted, if the metadata ID sent with the EXECUTE message
// matches the one for the (current) schema.
// Note: this test does not cover all aspects of 10786 (yet) - it was intended to test the
// changes for CASSANDRA-13992.
createTable("CREATE TABLE %s (pk int, v1 int, v2 int, PRIMARY KEY (pk))");
execute("INSERT INTO %s (pk, v1, v2) VALUES (1,1,1)");
try (SimpleClient simpleClient = newSimpleClient(ProtocolVersion.BETA.orElse(ProtocolVersion.CURRENT))) {
ResultMessage.Prepared prepUpdate = simpleClient.prepare(String.format("UPDATE %s.%s SET v1 = ?, v2 = ? WHERE pk = 1 IF v1 = ?", keyspace(), currentTable()));
ResultMessage.Prepared prepSelect = simpleClient.prepare(String.format("SELECT * FROM %s.%s WHERE pk = ?", keyspace(), currentTable()));
// This is a _successful_ LWT update
verifyMetadataFlagsWithLWTsUpdate(simpleClient, prepUpdate, Arrays.asList(Int32Serializer.instance.serialize(10), Int32Serializer.instance.serialize(20), Int32Serializer.instance.serialize(1)), Arrays.asList("[applied]"), Arrays.asList(BooleanSerializer.instance.serialize(true)));
prepSelect = verifyMetadataFlagsWithLWTsSelect(simpleClient, prepSelect, Arrays.asList("pk", "v1", "v2"), Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(10), Int32Serializer.instance.serialize(20)), EnumSet.of(org.apache.cassandra.cql3.ResultSet.Flag.GLOBAL_TABLES_SPEC));
// This is an _unsuccessful_ LWT update (as the condition fails)
verifyMetadataFlagsWithLWTsUpdate(simpleClient, prepUpdate, Arrays.asList(Int32Serializer.instance.serialize(10), Int32Serializer.instance.serialize(20), Int32Serializer.instance.serialize(1)), Arrays.asList("[applied]", "v1"), Arrays.asList(BooleanSerializer.instance.serialize(false), Int32Serializer.instance.serialize(10)));
prepSelect = verifyMetadataFlagsWithLWTsSelect(simpleClient, prepSelect, Arrays.asList("pk", "v1", "v2"), Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(10), Int32Serializer.instance.serialize(20)), EnumSet.of(org.apache.cassandra.cql3.ResultSet.Flag.GLOBAL_TABLES_SPEC));
// force a schema change on that table
simpleClient.execute(String.format("ALTER TABLE %s.%s ADD v3 int", keyspace(), currentTable()), ConsistencyLevel.LOCAL_ONE);
try {
simpleClient.executePrepared(prepUpdate, Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(30), Int32Serializer.instance.serialize(10)), ConsistencyLevel.LOCAL_ONE);
fail();
} catch (RuntimeException re) {
assertTrue(re.getCause() instanceof PreparedQueryNotFoundException);
// the prepared statement has been removed from the pstmt cache, need to re-prepare it
// only prepare the statement on the server side but don't set the variable
simpleClient.prepare(String.format("UPDATE %s.%s SET v1 = ?, v2 = ? WHERE pk = 1 IF v1 = ?", keyspace(), currentTable()));
}
try {
simpleClient.executePrepared(prepSelect, Arrays.asList(Int32Serializer.instance.serialize(1)), ConsistencyLevel.LOCAL_ONE);
fail();
} catch (RuntimeException re) {
assertTrue(re.getCause() instanceof PreparedQueryNotFoundException);
// the prepared statement has been removed from the pstmt cache, need to re-prepare it
// only prepare the statement on the server side but don't set the variable
simpleClient.prepare(String.format("SELECT * FROM %s.%s WHERE pk = ?", keyspace(), currentTable()));
}
// This is a _successful_ LWT update
verifyMetadataFlagsWithLWTsUpdate(simpleClient, prepUpdate, Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(30), Int32Serializer.instance.serialize(10)), Arrays.asList("[applied]"), Arrays.asList(BooleanSerializer.instance.serialize(true)));
// Re-assign prepSelect here, as the resultset metadata changed to submit the updated
// resultset-metadata-ID in the next SELECT. This behavior does not apply to LWT statements.
prepSelect = verifyMetadataFlagsWithLWTsSelect(simpleClient, prepSelect, Arrays.asList("pk", "v1", "v2", "v3"), Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(30), null), EnumSet.of(org.apache.cassandra.cql3.ResultSet.Flag.GLOBAL_TABLES_SPEC, org.apache.cassandra.cql3.ResultSet.Flag.METADATA_CHANGED));
// This is an _unsuccessful_ LWT update (as the condition fails)
verifyMetadataFlagsWithLWTsUpdate(simpleClient, prepUpdate, Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(30), Int32Serializer.instance.serialize(10)), Arrays.asList("[applied]", "v1"), Arrays.asList(BooleanSerializer.instance.serialize(false), Int32Serializer.instance.serialize(1)));
verifyMetadataFlagsWithLWTsSelect(simpleClient, prepSelect, Arrays.asList("pk", "v1", "v2", "v3"), Arrays.asList(Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(1), Int32Serializer.instance.serialize(30), null), EnumSet.of(org.apache.cassandra.cql3.ResultSet.Flag.GLOBAL_TABLES_SPEC));
}
}
use of org.apache.cassandra.exceptions.PreparedQueryNotFoundException in project cassandra by apache.
the class BatchMessage method execute.
@Override
protected Message.Response execute(QueryState state, long queryStartNanoTime, boolean traceRequest) {
List<QueryHandler.Prepared> prepared = null;
try {
if (traceRequest)
traceQuery(state);
QueryHandler handler = ClientState.getCQLQueryHandler();
prepared = new ArrayList<>(queryOrIdList.size());
for (int i = 0; i < queryOrIdList.size(); i++) {
Object query = queryOrIdList.get(i);
QueryHandler.Prepared p;
if (query instanceof String) {
p = QueryProcessor.parseAndPrepare((String) query, state.getClientState().cloneWithKeyspaceIfSet(options.getKeyspace()), false);
} else {
p = handler.getPrepared((MD5Digest) query);
if (null == p)
throw new PreparedQueryNotFoundException((MD5Digest) query);
}
List<ByteBuffer> queryValues = values.get(i);
if (queryValues.size() != p.statement.getBindVariables().size())
throw new InvalidRequestException(String.format("There were %d markers(?) in CQL but %d bound variables", p.statement.getBindVariables().size(), queryValues.size()));
prepared.add(p);
}
BatchQueryOptions batchOptions = BatchQueryOptions.withPerStatementVariables(options, values, queryOrIdList);
List<ModificationStatement> statements = new ArrayList<>(prepared.size());
List<String> queries = QueryEvents.instance.hasListeners() ? new ArrayList<>(prepared.size()) : null;
for (int i = 0; i < prepared.size(); i++) {
CQLStatement statement = prepared.get(i).statement;
if (queries != null)
queries.add(prepared.get(i).rawCQLStatement);
batchOptions.prepareStatement(i, statement.getBindVariables());
if (!(statement instanceof ModificationStatement))
throw new InvalidRequestException("Invalid statement in batch: only UPDATE, INSERT and DELETE statements are allowed.");
statements.add((ModificationStatement) statement);
}
// Note: It's ok at this point to pass a bogus value for the number of bound terms in the BatchState ctor
// (and no value would be really correct, so we prefer passing a clearly wrong one).
BatchStatement batch = new BatchStatement(batchType, VariableSpecifications.empty(), statements, Attributes.none());
long queryTime = currentTimeMillis();
Message.Response response = handler.processBatch(batch, state, batchOptions, getCustomPayload(), queryStartNanoTime);
if (queries != null)
QueryEvents.instance.notifyBatchSuccess(batchType, statements, queries, values, options, state, queryTime, response);
return response;
} catch (Exception e) {
QueryEvents.instance.notifyBatchFailure(prepared, batchType, queryOrIdList, values, options, state, e);
JVMStabilityInspector.inspectThrowable(e);
return ErrorMessage.fromException(e);
}
}
use of org.apache.cassandra.exceptions.PreparedQueryNotFoundException in project cassandra by apache.
the class ExecuteMessage method execute.
@Override
protected Message.Response execute(QueryState state, long queryStartNanoTime, boolean traceRequest) {
QueryHandler.Prepared prepared = null;
try {
QueryHandler handler = ClientState.getCQLQueryHandler();
prepared = handler.getPrepared(statementId);
if (prepared == null)
throw new PreparedQueryNotFoundException(statementId);
if (!prepared.fullyQualified && !Objects.equals(state.getClientState().getRawKeyspace(), prepared.keyspace) && // We can not reliably detect inconsistencies for batches yet
!(prepared.statement instanceof BatchStatement)) {
state.getClientState().warnAboutUseWithPreparedStatements(statementId, prepared.keyspace);
String msg = String.format("Tried to execute a prepared unqalified statement on a keyspace it was not prepared on. " + " Executing the resulting prepared statement will return unexpected results: %s (on keyspace %s, previously prepared on %s)", statementId, state.getClientState().getRawKeyspace(), prepared.keyspace);
nospam.error(msg);
}
CQLStatement statement = prepared.statement;
options.prepare(statement.getBindVariables());
if (options.getPageSize() == 0)
throw new ProtocolException("The page size cannot be 0");
if (traceRequest)
traceQuery(state, prepared);
// Some custom QueryHandlers are interested by the bound names. We provide them this information
// by wrapping the QueryOptions.
QueryOptions queryOptions = QueryOptions.addColumnSpecifications(options, prepared.statement.getBindVariables());
long requestStartTime = currentTimeMillis();
Message.Response response = handler.processPrepared(statement, state, queryOptions, getCustomPayload(), queryStartNanoTime);
QueryEvents.instance.notifyExecuteSuccess(prepared.statement, prepared.rawCQLStatement, options, state, requestStartTime, response);
if (response instanceof ResultMessage.Rows) {
ResultMessage.Rows rows = (ResultMessage.Rows) response;
ResultSet.ResultMetadata resultMetadata = rows.result.metadata;
if (options.getProtocolVersion().isGreaterOrEqualTo(ProtocolVersion.V5)) {
// for details.
if (!statement.hasConditions()) {
// check if there was a change, comparing it with metadata that's about to be returned to client.
if (!resultMetadata.getResultMetadataId().equals(resultMetadataId))
resultMetadata.setMetadataChanged();
else if (options.skipMetadata())
resultMetadata.setSkipMetadata();
}
} else {
// and compare it with the metadata to be returned to client.
if (options.skipMetadata() && prepared.resultMetadataId.equals(resultMetadata.getResultMetadataId()))
resultMetadata.setSkipMetadata();
}
}
return response;
} catch (Exception e) {
QueryEvents.instance.notifyExecuteFailure(prepared, options, state, e);
JVMStabilityInspector.inspectThrowable(e);
return ErrorMessage.fromException(e);
}
}
Aggregations