This is an automated email from the ASF dual-hosted git repository.

shuwenwei pushed a commit to branch fix-moreData-not-updated
in repository https://gitbox.apache.org/repos/asf/iotdb-client-go.git

commit 829f5975f9dbc2fd9bed10b4fd56608a05381a32
Author: shuwenwei <[email protected]>
AuthorDate: Fri Aug 7 09:57:05 2026 +0800

    Fix IoTDBRpcDataSet.moreData not updated in fetchResults (#171)
---
 client/rpcdataset.go      |   2 +
 client/rpcdataset_test.go | 164 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 166 insertions(+)

diff --git a/client/rpcdataset.go b/client/rpcdataset.go
index da97ef6..d41a765 100644
--- a/client/rpcdataset.go
+++ b/client/rpcdataset.go
@@ -234,6 +234,8 @@ func (s *IoTDBRpcDataSet) fetchResults() (bool, error) {
                return false, err
        }
 
+       s.moreData = resp.GetMoreData()
+
        if !resp.HasResultSet {
                err = s.Close()
        } else {
diff --git a/client/rpcdataset_test.go b/client/rpcdataset_test.go
new file mode 100644
index 0000000..45d385d
--- /dev/null
+++ b/client/rpcdataset_test.go
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package client
+
+import (
+       "context"
+       "testing"
+
+       "github.com/apache/iotdb-client-go/v2/common"
+       "github.com/apache/iotdb-client-go/v2/rpc"
+       "github.com/apache/thrift/lib/go/thrift"
+)
+
+// fakeThriftClient implements thrift.TClient to intercept RPC calls made by
+// rpc.IClientRPCServiceClient without requiring a real IoTDB server.
+type fakeThriftClient struct {
+       thrift.TClient
+       fetchResultsResp *rpc.TSFetchResultsResp
+       closeStatus      *common.TSStatus
+}
+
+func (f *fakeThriftClient) Call(ctx context.Context, method string, args, 
result thrift.TStruct) (thrift.ResponseMeta, error) {
+       switch method {
+       case "fetchResultsV2":
+               fetchResultsResult, ok := 
result.(*rpc.IClientRPCServiceFetchResultsV2Result)
+               if !ok {
+                       return thrift.ResponseMeta{}, 
thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "unexpected result type")
+               }
+               fetchResultsResult.Success = f.fetchResultsResp
+       case "closeOperation":
+               closeResult, ok := 
result.(*rpc.IClientRPCServiceCloseOperationResult)
+               if !ok {
+                       return thrift.ResponseMeta{}, 
thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "unexpected result type")
+               }
+               closeResult.Success = f.closeStatus
+       default:
+               return thrift.ResponseMeta{}, 
thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "unexpected method 
"+method)
+       }
+       return thrift.ResponseMeta{}, nil
+}
+
+func boolPtr(b bool) *bool {
+       return &b
+}
+
+func newTestRPCDataSet(t *testing.T, fake *fakeThriftClient, moreData bool) 
*IoTDBRpcDataSet {
+       t.Helper()
+       client := rpc.NewIClientRPCServiceClient(fake)
+       ds, err := NewIoTDBRpcDataSet(
+               "select s1 from root.test",
+               []string{"s1"},
+               []string{"INT64"},
+               map[string]int32{"s1": 1},
+               false,
+               moreData,
+               1,
+               2,
+               client,
+               3,
+               nil,
+               1024,
+               nil,
+               "UTC",
+               DEFAULT_TIME_FORMAT,
+               1_000,
+               []int32{0},
+       )
+       if err != nil {
+               t.Fatalf("NewIoTDBRpcDataSet error: %v", err)
+       }
+       return ds
+}
+
+func TestIoTDBRpcDataSet_fetchResults_updatesMoreData(t *testing.T) {
+       tests := []struct {
+               name            string
+               initialMoreData bool
+               respMoreData    bool
+               wantMoreData    bool
+       }{
+               {name: "more data available", initialMoreData: false, 
respMoreData: true, wantMoreData: true},
+               {name: "no more data", initialMoreData: true, respMoreData: 
false, wantMoreData: false},
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       fake := &fakeThriftClient{
+                               fetchResultsResp: &rpc.TSFetchResultsResp{
+                                       Status:       &common.TSStatus{Code: 
SuccessStatus},
+                                       HasResultSet: true,
+                                       MoreData:     boolPtr(tt.respMoreData),
+                               },
+                       }
+                       ds := newTestRPCDataSet(t, fake, tt.initialMoreData)
+                       ok, err := ds.fetchResults()
+                       if err != nil {
+                               t.Fatalf("fetchResults() error = %v", err)
+                       }
+                       if !ok {
+                               t.Fatalf("fetchResults() = false, want true")
+                       }
+                       if ds.moreData != tt.wantMoreData {
+                               t.Errorf("moreData = %v, want %v", ds.moreData, 
tt.wantMoreData)
+                       }
+               })
+       }
+}
+
+func TestIoTDBRpcDataSet_fetchResults_noMoreDataFieldDefaultsToFalse(t 
*testing.T) {
+       fake := &fakeThriftClient{
+               fetchResultsResp: &rpc.TSFetchResultsResp{
+                       Status:       &common.TSStatus{Code: SuccessStatus},
+                       HasResultSet: true,
+               },
+       }
+       ds := newTestRPCDataSet(t, fake, true)
+       if _, err := ds.fetchResults(); err != nil {
+               t.Fatalf("fetchResults() error = %v", err)
+       }
+       if ds.moreData {
+               t.Errorf("moreData = true, want false when MoreData field is 
unset")
+       }
+}
+
+func TestIoTDBRpcDataSet_fetchResults_closesWhenNoResultSet(t *testing.T) {
+       fake := &fakeThriftClient{
+               fetchResultsResp: &rpc.TSFetchResultsResp{
+                       Status:       &common.TSStatus{Code: SuccessStatus},
+                       HasResultSet: false,
+                       MoreData:     boolPtr(false),
+               },
+               closeStatus: &common.TSStatus{Code: SuccessStatus},
+       }
+       ds := newTestRPCDataSet(t, fake, true)
+       ok, err := ds.fetchResults()
+       if err != nil {
+               t.Fatalf("fetchResults() error = %v", err)
+       }
+       if ok {
+               t.Fatalf("fetchResults() = true, want false")
+       }
+       if !ds.IsClosed() {
+               t.Errorf("data set is not closed after fetching empty result")
+       }
+       if ds.moreData {
+               t.Errorf("moreData = true, want false")
+       }
+}

Reply via email to