From 7105345dfbc9df739ba27b0567bad6619290d225 Mon Sep 17 00:00:00 2001 From: Dmitry Konstantinov Date: Sat, 3 Aug 2024 12:27:17 +0100 Subject: [PATCH 1/2] Make UdtCodec logic tolerant to extra unknown fields at the tail of UDT to support live schema upgrades Patch by Dmitry Konstantinov; reviewed by TBD for CASSANDRA-19814 --- .../internal/core/type/codec/UdtCodec.java | 6 ++-- .../core/type/codec/UdtCodecTest.java | 29 +++++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodec.java b/core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodec.java index f5177e63b5e..75fe4b48a65 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodec.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodec.java @@ -107,10 +107,8 @@ public UdtValue decode(@Nullable ByteBuffer bytes, @NonNull ProtocolVersion prot int i = 0; while (input.hasRemaining()) { if (i == cqlType.getFieldTypes().size()) { - throw new IllegalArgumentException( - String.format( - "Too many fields in encoded UDT value, expected %d", - cqlType.getFieldTypes().size())); + // ignores all unknown fields at the tail during a decoding + break; } int elementSize = input.getInt(); ByteBuffer element; diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java index bf7c1e98b26..1a40f7ac45b 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java @@ -136,18 +136,23 @@ public void should_decode_udt() { } @Test - public void should_fail_to_decode_udt_when_too_many_fields() { - assertThatThrownBy( - () -> - decode( - "0x" - + ("00000004" + "00000001") - + "ffffffff" - + ("00000001" + "61") - // extra contents - + "ffffffff")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Too many fields in encoded UDT value, expected 3"); + public void should_decode_udt_when_too_many_fields() { + UdtValue udt = decode("0x" + + ("00000004" + "00000001") // size and contents of int field 0 + + "ffffffff" // null field 1 + + ("00000001" + "61") // size and contents of String field 2 + + ("00000004" + "00000002") // size and contents of int field 3, unknown for UDT version used to create the codec + ); + + assertThat(udt.getInt(0)).isEqualTo(1); + assertThat(udt.isNull(1)).isTrue(); + assertThat(udt.getString(2)).isEqualTo("a"); + assertThat(udt.size()).isEqualTo(3); // unknown field is not decoded + + + verify(intCodec).decodePrimitive(Bytes.fromHexString("0x00000001"), ProtocolVersion.DEFAULT); + verifyZeroInteractions(doubleCodec); + verify(textCodec).decode(Bytes.fromHexString("0x61"), ProtocolVersion.DEFAULT); } /** Test for JAVA-2557. Ensures that the codec can decode null fields with any negative length. */ From ef9bed9b5d07f3c7018f489417235be84d6b30c4 Mon Sep 17 00:00:00 2001 From: Dmitry Konstantinov Date: Wed, 13 Nov 2024 18:50:47 +0000 Subject: [PATCH 2/2] Fix formatting issue Patch by Dmitry Konstantinov; reviewed by TBD for CASSANDRA-19814 --- .../internal/core/type/codec/UdtCodecTest.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java index 1a40f7ac45b..c9a3b12e6d5 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/type/codec/UdtCodecTest.java @@ -137,19 +137,22 @@ public void should_decode_udt() { @Test public void should_decode_udt_when_too_many_fields() { - UdtValue udt = decode("0x" - + ("00000004" + "00000001") // size and contents of int field 0 - + "ffffffff" // null field 1 - + ("00000001" + "61") // size and contents of String field 2 - + ("00000004" + "00000002") // size and contents of int field 3, unknown for UDT version used to create the codec - ); + UdtValue udt = + decode( + "0x" + + ("00000004" + "00000001") // size and contents of int field 0 + + "ffffffff" // null field 1 + + ("00000001" + "61") // size and contents of String field 2 + + ("00000004" + + "00000002") // size and contents of int field 3, unknown for UDT version used + // to create the codec + ); assertThat(udt.getInt(0)).isEqualTo(1); assertThat(udt.isNull(1)).isTrue(); assertThat(udt.getString(2)).isEqualTo("a"); assertThat(udt.size()).isEqualTo(3); // unknown field is not decoded - verify(intCodec).decodePrimitive(Bytes.fromHexString("0x00000001"), ProtocolVersion.DEFAULT); verifyZeroInteractions(doubleCodec); verify(textCodec).decode(Bytes.fromHexString("0x61"), ProtocolVersion.DEFAULT);