diff --git a/CHANGES.txt b/CHANGES.txt index 4693c8815e..bdecf8f324 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,7 +4,9 @@ * Deprecate and ignore use_deterministic_table_id (CASSANDRA-19809) * Prioritize built indexes in IndexStatusManager (CASSANDRA-19400) * Add java.base/java.lang.reflect among opens for jvm11-client.options (CASSANDRA-19780) +Merged from 4.1: Merged from 4.0: + * Fix rendering UNSET collection types in query tracing (CASSANDRA-19880) * Fix latency reported by ideal consistency level monitoring (CASSANDRA-19651) * Do not spam log with SSLExceptions (CASSANDRA-18839) diff --git a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java index 6199d543d7..89b7e2a4a2 100644 --- a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java +++ b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java @@ -17,6 +17,7 @@ */ package org.apache.cassandra.transport.messages; +import java.nio.ByteBuffer; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -39,6 +40,7 @@ import org.apache.cassandra.transport.Dispatcher; import org.apache.cassandra.transport.Message; import org.apache.cassandra.transport.ProtocolException; import org.apache.cassandra.transport.ProtocolVersion; +import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.JVMStabilityInspector; import org.apache.cassandra.utils.MD5Digest; import org.apache.cassandra.utils.NoSpamLogger; @@ -224,7 +226,8 @@ public class ExecuteMessage extends Message.Request { ColumnSpecification cs = prepared.statement.getBindVariables().get(i); String boundName = cs.name.toString(); - String boundValue = cs.type.asCQL3Type().toCQLLiteral(options.getValues().get(i)); + ByteBuffer bytes = options.getValues().get(i); + String boundValue = (bytes == ByteBufferUtil.UNSET_BYTE_BUFFER) ? "" : cs.type.asCQL3Type().toCQLLiteral(bytes); if (boundValue.length() > 1000) boundValue = boundValue.substring(0, 1000) + "...'"; diff --git a/test/unit/org/apache/cassandra/cql3/TraceCqlTest.java b/test/unit/org/apache/cassandra/cql3/TraceCqlTest.java index f1af9227e6..74b407ef56 100644 --- a/test/unit/org/apache/cassandra/cql3/TraceCqlTest.java +++ b/test/unit/org/apache/cassandra/cql3/TraceCqlTest.java @@ -18,10 +18,16 @@ package org.apache.cassandra.cql3; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.CodecRegistry; import com.datastax.driver.core.DataType; import com.datastax.driver.core.PreparedStatement; @@ -140,6 +146,29 @@ public class TraceCqlTest extends CQLTester //when tracing is done, this boundValue will be surrounded by single quote, and first 1000 characters //will be filtered. Here we take into account single quotes by adding them to the expected output assertEquals("'" + boundValue.substring(0, 999) + "...'", trace.getParameters().get("bound_var_0_value(v3)")); + + pstmt = session.prepare("INSERT INTO " + KEYSPACE + '.' + currentTable() + " (id, v1, v2, v3) values (?, ?, ?, ?)").enableTracing(); + BoundStatement boundStatement = pstmt.bind(13, "lukasz", value, map(2024, "birthday", 40, "anniversary")); + + boundStatement.unset(3); // test query tracing after UNSET collection type + trace = session.execute(boundStatement).getExecutionInfo().getQueryTrace(); + Map boundParameters = getBoundParameters(trace); + assertEquals(Arrays.asList("13", "'lukasz'", "(3, 'bar', 2.1)", ""), new ArrayList<>(boundParameters.values())); + + boundStatement.unset(2); // test query tracing after UNSET tuple type + trace = session.execute(boundStatement).getExecutionInfo().getQueryTrace(); + boundParameters = getBoundParameters(trace); + assertEquals(Arrays.asList("13", "'lukasz'", "", ""), new ArrayList<>(boundParameters.values())); } } + + private Map getBoundParameters(QueryTrace trace) { + Map boundParameters = new LinkedHashMap<>(); + trace.getParameters().forEach((paramName, paramValue) -> { + if (paramName.startsWith("bound_")) { + boundParameters.put(paramName, paramValue); + } + }); + return boundParameters; + } }