[client-v2] Compiled POJO setter emits invalid bytecode (VerifyError) when the column type does not match the primitive field type
还没有人认领这个 Issue。
评估
调研方向
使用所示的 client-v2 POJO 查询重现该失败,然后检查 SerializerUtils.compilePOJOSetter 和 binaryReaderMethodForType,包括 longToOpcode、floatToOpcode 和 doubleToOpcode 分支。完成的标准是:不匹配的 primitive binding 会生成带有 Java 窄化或拓宽转换的可验证 setter,并且 Number 值列可以读入 primitive 字段而不会出现 VerifyError。
由索引模型根据 Issue 内容生成。
描述
Describe the bug
client-v2 compiles a POJO field setter into bytecode (SerializerUtils.compilePOJOSetter). When the column type
and the POJO field's primitive type do not match exactly, the generated class is invalid and reading fails with
java.lang.VerifyError (thrown when the compiled setter class is first linked, i.e. on the first row read).
Two distinct groups of combinations are affected.
1. The value left on the stack is not converted to the setter's primitive type.
binaryReaderMethodForType only computed a conversion opcode for a few reader/field combinations
(longToOpcode, floatToOpcode and doubleToOpcode return -1 for byte/short/char/boolean, and the
Int8/UInt8/Int16/Enum8/Enum16/Bool branches computed no conversion at all). So, for example:
- an
Int64,UInt32,Float32,Float64orBFloat16column bound to abyte,short,charorbooleanfield - an
Int8,UInt8,Int16,Enum8,Enum16orBoolcolumn bound to along,floatordoublefield
leave a value of the wrong type on the operand stack for the setter descriptor, and the generated class does not verify.
2. A primitive field bound to a column that is not read into a primitive.
The generic branch emits LDC of a class constant for the target type and CHECKCAST with its internal name.
For a primitive target that produces a class constant named "I"/"J" and a CHECKCAST int, and the value read
by readValue (an Object) is passed to a primitive setter descriptor. So Int128, UInt128, Int256, UInt256
and Decimal* columns cannot be read into a primitive field at all, even though the value is a Number.
Steps to reproduce
public class Pojo {
private short v;
public short getV() { return v; }
public void setV(short v) { this.v = v; }
}
String sql = "SELECT toInt64(300) AS v"; // also: toFloat64(-2.7), toInt8(-5) into a long field, ...
TableSchema schema = client.getTableSchemaFromQuery(sql);
client.register(Pojo.class, schema);
client.queryAll(sql, Pojo.class, schema); // -> java.lang.VerifyError
The same happens with SELECT toInt128(-2) AS v or SELECT toDecimal64(123.45, 2) AS v bound to a long/double
field (group 2).
Expected behaviour
The value is converted to the field's primitive type following Java's narrowing/widening rules (as already happens
for an Int32 column bound to a byte field), and a Number-valued column can be read into a primitive field.
Error log
java.lang.VerifyError
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
...
at com.clickhouse.client.api.data_formats.internal.SerializerUtils.compilePOJOSetter(SerializerUtils.java:...)
Configuration
- Client version:
main(0.11.0-rc1) - Language: Java
- Client:
client-v2(POJO binding /queryAll(sql, Pojo.class, schema))
- 主要语言
- Java
- 星标
- 1.6k
- 派生
- 637
- 平均合并
- 2 天 17 小时
- 30 天内合并 PR
- 29
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
ClickHouse/clickhouse-java 的其他 Issue
-
难度 1/5 1 小时以内 新手友好度 85/100
ClickHouse/clickhouse-java#3111 ·
-
area:data-type bug
难度 2/5 1-3 小时 新手友好度 78/100
ClickHouse/clickhouse-java#3098 · 1 条评论 ·
-
bug client-api-v2 test
难度 2/5 1-3 小时 新手友好度 92/100
ClickHouse/clickhouse-java#3076 ·
-
area:sql-parser bug client-v1
难度 1/5 1-3 小时 新手友好度 92/100
ClickHouse/clickhouse-java#3066 ·
-
area:general bug client-api-v2 jdbc jdbc-v2
难度 2/5 1-3 小时 新手友好度 88/100
ClickHouse/clickhouse-java#3063 ·
查看 ClickHouse/clickhouse-java 的全部 Issue
相似的 Issue
-
area-deployment area-integrations triage:bot-seen
难度 2/5 半天 新手友好度 86/100
-
难度 2/5 1-3 小时 新手友好度 75/100
apache/flink-agents#1156 ·
-
area/connectors autoteam community connectors/source/shopify needs-triage team/use type/bug
难度 2/5 1-3 小时 新手友好度 84/100
-
难度 2/5 1-3 小时 新手友好度 70/100
-
难度 1/5 1 小时以内 新手友好度 85/100