From e54e232633d74a8098828cf480db27d31468c473 Mon Sep 17 00:00:00 2001 From: 4paradigm <4paradigm@denglong.local> Date: Thu, 30 Nov 2023 09:59:00 +0800 Subject: [PATCH 1/4] fix: set object null --- .../common/codec/ClassicRowBuilder.java | 11 ++++++- .../common/codec/FlexibleRowBuilder.java | 9 ++++++ .../openmldb/common/RowCodecTest.java | 32 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java b/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java index 15bb50d0471..ecdf0bb0ff9 100644 --- a/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java +++ b/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java @@ -205,6 +205,9 @@ public boolean appendTimestamp(Timestamp val) { if (!check(DataType.kTimestamp)) { return false; } + if (val == null) { + return appendNULL(); + } setField(cnt); buf.position(offsetVec.get(cnt)); buf.putLong(val.getTime()); @@ -250,6 +253,9 @@ public boolean appendDouble(double val) { @Override public boolean appendDate(Date date) { + if (date == null) { + return appendNULL(); + } int dateInt = CodecUtil.dateToDateInt(date); buf.position(offsetVec.get(cnt)); buf.putInt(dateInt); @@ -260,9 +266,12 @@ public boolean appendDate(Date date) { @Override public boolean appendString(String val) { + if (val == null) { + return appendNULL(); + } byte[] bytes = val.getBytes(CodecUtil.CHARSET); int length = bytes.length; - if (val == null || (!check(DataType.kVarchar) && !check(DataType.kString))) { + if (!check(DataType.kVarchar) && !check(DataType.kString)) { return false; } if (strOffset + length > size) { diff --git a/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/FlexibleRowBuilder.java b/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/FlexibleRowBuilder.java index e9029fb7663..f11f2a31a64 100644 --- a/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/FlexibleRowBuilder.java +++ b/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/FlexibleRowBuilder.java @@ -273,6 +273,9 @@ public boolean setTimestamp(int idx, Timestamp val) { if (!checkType(idx, Type.DataType.kTimestamp)) { return false; } + if (val == null) { + return setNULL(idx); + } settedValue.atPut(idx, true); baseFieldBuf.putLong(getOffset(idx), val.getTime()); return true; @@ -313,6 +316,9 @@ public boolean setDate(int idx, Date val) { if (!checkType(idx, Type.DataType.kDate)) { return false; } + if (val == null) { + return setNULL(idx); + } settedValue.atPut(idx, true); int dateVal = CodecUtil.dateToDateInt(val); baseFieldBuf.putInt(getOffset(idx), dateVal); @@ -324,6 +330,9 @@ public boolean setString(int idx, String val) { if (!checkType(idx, Type.DataType.kString) && !checkType(idx, Type.DataType.kVarchar)) { return false; } + if (val == null) { + return setNULL(idx); + } if (settedValue.at(idx)) { return false; } diff --git a/java/openmldb-common/src/test/java/com/_4paradigm/openmldb/common/RowCodecTest.java b/java/openmldb-common/src/test/java/com/_4paradigm/openmldb/common/RowCodecTest.java index ff1c51f06ea..c562cbd70ee 100644 --- a/java/openmldb-common/src/test/java/com/_4paradigm/openmldb/common/RowCodecTest.java +++ b/java/openmldb-common/src/test/java/com/_4paradigm/openmldb/common/RowCodecTest.java @@ -89,6 +89,38 @@ public void testNull(String builderName) { } } + @Test(dataProvider = "builder") + public void testValueNull(String builderName) { + try { + List schema = new ArrayList(); + schema.add(ColumnDesc.newBuilder().setName("col1").setDataType(DataType.kTimestamp).build()); + schema.add(ColumnDesc.newBuilder().setName("col2").setDataType(DataType.kDate).build()); + schema.add(ColumnDesc.newBuilder().setName("col3").setDataType(DataType.kVarchar).build()); + RowBuilder builder; + if (builderName.equals("classic")) { + ClassicRowBuilder cBuilder = new ClassicRowBuilder(schema); + int size = cBuilder.calTotalLength(0); + ByteBuffer buffer = ByteBuffer.allocate(size).order(ByteOrder.LITTLE_ENDIAN); + cBuilder.setBuffer(buffer, size); + builder = cBuilder; + } else { + builder = new FlexibleRowBuilder(schema); + } + Assert.assertTrue(builder.appendTimestamp(null)); + Assert.assertTrue(builder.appendDate(null)); + Assert.assertTrue(builder.appendString(null)); + Assert.assertTrue(builder.build()); + ByteBuffer buffer = builder.getValue(); + RowView rowView = new RowView(schema, buffer, buffer.capacity()); + Assert.assertTrue(rowView.isNull(0)); + Assert.assertTrue(rowView.isNull(1)); + Assert.assertTrue(rowView.isNull(2)); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + } + @Test(dataProvider = "builder") public void testNormal(String builderName) { try { From 961c36b28e199b29ea2b80871a64f715b48df8b3 Mon Sep 17 00:00:00 2001 From: 4paradigm <4paradigm@denglong.local> Date: Thu, 30 Nov 2023 10:04:04 +0800 Subject: [PATCH 2/4] refact: check type at first --- .../_4paradigm/openmldb/common/codec/ClassicRowBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java b/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java index ecdf0bb0ff9..0b5048eff74 100644 --- a/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java +++ b/java/openmldb-common/src/main/java/com/_4paradigm/openmldb/common/codec/ClassicRowBuilder.java @@ -266,14 +266,14 @@ public boolean appendDate(Date date) { @Override public boolean appendString(String val) { + if (!check(DataType.kVarchar) && !check(DataType.kString)) { + return false; + } if (val == null) { return appendNULL(); } byte[] bytes = val.getBytes(CodecUtil.CHARSET); int length = bytes.length; - if (!check(DataType.kVarchar) && !check(DataType.kString)) { - return false; - } if (strOffset + length > size) { return false; } From 1cb5a564e750920c36904672d87cdf19b6fbd480 Mon Sep 17 00:00:00 2001 From: 4paradigm <4paradigm@denglong.local> Date: Thu, 30 Nov 2023 14:45:14 +0800 Subject: [PATCH 3/4] docs: add doc --- docs/en/quickstart/sdk/java_sdk.md | 3 ++- docs/zh/quickstart/sdk/java_sdk.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/en/quickstart/sdk/java_sdk.md b/docs/en/quickstart/sdk/java_sdk.md index ea06bc671db..936666524fe 100644 --- a/docs/en/quickstart/sdk/java_sdk.md +++ b/docs/en/quickstart/sdk/java_sdk.md @@ -241,7 +241,8 @@ try { 1. Get `InsertPrepareStatement` by calling `SqlClusterExecutor::getInsertPreparedStmt(db, insertSqlWithPlaceHolder)` interface. 2. Use `PreparedStatement::setType(index, value)` interface to fill in data to the `InsertPrepareStatement`. Note that the index starts from 1. -3. Use `PreparedStatement::execute()` interface to execute the insert statement. +3. For String, Date and Timestamp types, null objects can be set using either `setType(index, null)` or `setNull(index)` +4. Use `PreparedStatement::execute()` interface to execute the insert statement. ```{note} When the conditions of the `PreparedStatement` are the same, you can repeatedly call the set method of the same object to fill in data before executing `execute`. There is no need to create a new `PreparedStatement` object. diff --git a/docs/zh/quickstart/sdk/java_sdk.md b/docs/zh/quickstart/sdk/java_sdk.md index 37a874e4521..59b92e59040 100644 --- a/docs/zh/quickstart/sdk/java_sdk.md +++ b/docs/zh/quickstart/sdk/java_sdk.md @@ -245,7 +245,8 @@ try { 1. 使用 `SqlClusterExecutor::getInsertPreparedStmt(db, insertSqlWithPlaceHolder)` 接口获取 InsertPrepareStatement。 2. 调用 `PreparedStatement::setType(index, value)` 接口,填充数据到 InsertPrepareStatement中。注意 index 从 1 开始。 -3. 使用 `PreparedStatement::execute()` 接口执行 insert 语句。 +3. 对于String, Date和Timestamp类型, 可以通过`setType(index, null)`和`setNull(index)`两种方式来设置null对象 +4. 使用 `PreparedStatement::execute()` 接口执行 insert 语句。 ```{note} PreparedStatment条件相同时,可以对同一个对象反复set填充数据后,再执行execute,不需要重新创建PreparedStatement。 ``` From 314f2f203e8b884e6da50c35ff1541aeeef7a7a0 Mon Sep 17 00:00:00 2001 From: 4paradigm <4paradigm@denglong.local> Date: Thu, 30 Nov 2023 14:47:05 +0800 Subject: [PATCH 4/4] docs: update doc --- docs/en/quickstart/sdk/java_sdk.md | 2 +- docs/zh/quickstart/sdk/java_sdk.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/quickstart/sdk/java_sdk.md b/docs/en/quickstart/sdk/java_sdk.md index 936666524fe..8934c55abf0 100644 --- a/docs/en/quickstart/sdk/java_sdk.md +++ b/docs/en/quickstart/sdk/java_sdk.md @@ -241,7 +241,7 @@ try { 1. Get `InsertPrepareStatement` by calling `SqlClusterExecutor::getInsertPreparedStmt(db, insertSqlWithPlaceHolder)` interface. 2. Use `PreparedStatement::setType(index, value)` interface to fill in data to the `InsertPrepareStatement`. Note that the index starts from 1. -3. For String, Date and Timestamp types, null objects can be set using either `setType(index, null)` or `setNull(index)` +3. For String, Date and Timestamp types, null objects can be set using either `setType(index, null)` or `setNull(index)`. 4. Use `PreparedStatement::execute()` interface to execute the insert statement. ```{note} diff --git a/docs/zh/quickstart/sdk/java_sdk.md b/docs/zh/quickstart/sdk/java_sdk.md index 59b92e59040..5503cc97fd1 100644 --- a/docs/zh/quickstart/sdk/java_sdk.md +++ b/docs/zh/quickstart/sdk/java_sdk.md @@ -245,7 +245,7 @@ try { 1. 使用 `SqlClusterExecutor::getInsertPreparedStmt(db, insertSqlWithPlaceHolder)` 接口获取 InsertPrepareStatement。 2. 调用 `PreparedStatement::setType(index, value)` 接口,填充数据到 InsertPrepareStatement中。注意 index 从 1 开始。 -3. 对于String, Date和Timestamp类型, 可以通过`setType(index, null)`和`setNull(index)`两种方式来设置null对象 +3. 对于String, Date和Timestamp类型, 可以通过`setType(index, null)`和`setNull(index)`两种方式来设置null对象。 4. 使用 `PreparedStatement::execute()` 接口执行 insert 语句。 ```{note} PreparedStatment条件相同时,可以对同一个对象反复set填充数据后,再执行execute,不需要重新创建PreparedStatement。