From 4a1f35b1e4175a8181b3af8e56df54f125e8305a Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 18 Aug 2024 22:00:49 +0600 Subject: [PATCH] Fix empty LUA table reply (#3924) * Fix empty LUA table reply * processMapKeyValueReply returns List * make PROTOCOL_EMPTY_MAP unmodifiable --- .../redis/clients/jedis/BuilderFactory.java | 7 ++++-- .../java/redis/clients/jedis/Protocol.java | 22 ++++++++++++------- .../commands/jedis/ScriptingCommandsTest.java | 6 +++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/main/java/redis/clients/jedis/BuilderFactory.java b/src/main/java/redis/clients/jedis/BuilderFactory.java index 18eeb64afd..a48168357d 100644 --- a/src/main/java/redis/clients/jedis/BuilderFactory.java +++ b/src/main/java/redis/clients/jedis/BuilderFactory.java @@ -385,7 +385,9 @@ public Object build(Object data) { if (data instanceof List) { final List list = (List) data; - if (list.isEmpty()) return Collections.emptyMap(); + if (list.isEmpty()) { + return list == Protocol.PROTOCOL_EMPTY_MAP ? Collections.emptyMap() : Collections.emptyList(); + } if (list.get(0) instanceof KeyValue) { return ((List) data).stream() @@ -397,8 +399,9 @@ public Object build(Object data) { } } else if (data instanceof byte[]) { return STRING.build(data); + } else { + return data; } - return data; } }; diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 448bd7ff12..d9c9872e1c 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -4,6 +4,7 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; @@ -49,6 +50,8 @@ public final class Protocol { public static final byte[] POSITIVE_INFINITY_BYTES = "+inf".getBytes(); public static final byte[] NEGATIVE_INFINITY_BYTES = "-inf".getBytes(); + static final List PROTOCOL_EMPTY_MAP = Collections.unmodifiableList(new ArrayList<>(0)); + private static final String ASK_PREFIX = "ASK "; private static final String MOVED_PREFIX = "MOVED "; private static final String CLUSTERDOWN_PREFIX = "CLUSTERDOWN "; @@ -192,7 +195,6 @@ private static byte[] processBulkReply(final RedisInputStream is) { } private static List processMultiBulkReply(final RedisInputStream is) { - // private static List processMultiBulkReply(final int num, final RedisInputStream is) { final int num = is.readIntCrLf(); if (num == -1) return null; final List ret = new ArrayList<>(num); @@ -206,16 +208,20 @@ private static List processMultiBulkReply(final RedisInputStream is) { return ret; } - // private static List processMultiBulkReply(final RedisInputStream is) { - // private static List processMultiBulkReply(final int num, final RedisInputStream is) { private static List processMapKeyValueReply(final RedisInputStream is) { final int num = is.readIntCrLf(); - if (num == -1) return null; - final List ret = new ArrayList<>(num); - for (int i = 0; i < num; i++) { - ret.add(new KeyValue(process(is), process(is))); + switch (num) { + case -1: + return null; + case 0: + return PROTOCOL_EMPTY_MAP; + default: + final List ret = new ArrayList<>(num); + for (int i = 0; i < num; i++) { + ret.add(new KeyValue(process(is), process(is))); + } + return ret; } - return ret; } public static Object read(final RedisInputStream is) { diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java index 5f26baec58..9f4c60de0b 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java @@ -328,6 +328,12 @@ public void scriptExistsWithBrokenConnection() { deadClient.close(); } + @Test + public void emptyLuaTableReply() { + Object reply = jedis.eval("return {}"); + assertEquals(Collections.emptyList(), reply); + } + @Test public void functionLoadAndDelete() { String engine = "Lua";