github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/tests/integration/table_truncated_err_test.go (about) 1 //go:build integration 2 // +build integration 3 4 package integration 5 6 import ( 7 "context" 8 "database/sql" 9 "fmt" 10 "strconv" 11 "testing" 12 13 "github.com/ydb-platform/ydb-go-sdk/v3" 14 "github.com/ydb-platform/ydb-go-sdk/v3/retry" 15 "github.com/ydb-platform/ydb-go-sdk/v3/table" 16 "github.com/ydb-platform/ydb-go-sdk/v3/table/options" 17 "github.com/ydb-platform/ydb-go-sdk/v3/table/result" 18 "github.com/ydb-platform/ydb-go-sdk/v3/table/types" 19 ) 20 21 // https://github.com/ydb-platform/ydb-go-sdk/issues/798 22 func TestIssue798TruncatedError(t *testing.T) { 23 const rowsLimit = 1000 24 var ( 25 scope = newScope(t) 26 driver = scope.Driver() 27 db = scope.SQLDriver() 28 tablePath = scope.TablePath() 29 ) 30 31 ctx, cancel := context.WithCancel(context.Background()) 32 defer cancel() 33 34 // upsert rows 35 { 36 rows := make([]types.Value, rowsLimit) 37 for i := range rows { 38 rows[i] = types.StructValue( 39 types.StructFieldValue("id", types.Int64Value(int64(i))), 40 types.StructFieldValue("val", types.TextValue(strconv.Itoa(i))), 41 ) 42 } 43 err := driver.Table().Do(ctx, func(ctx context.Context, s table.Session) error { 44 return s.BulkUpsert(ctx, tablePath, types.ListValue(rows...)) 45 }, table.WithIdempotent()) 46 scope.Require.NoError(err) 47 } 48 49 // select rows without truncated error 50 { 51 err := driver.Table().Do(ctx, func(ctx context.Context, s table.Session) error { 52 _, results, err := s.Execute(ctx, 53 table.DefaultTxControl(), 54 fmt.Sprintf("SELECT * FROM `%s`;", tablePath), 55 nil, 56 ) 57 if err != nil { 58 return err 59 } 60 if err = results.NextResultSetErr(ctx); err != nil { 61 return fmt.Errorf("no result sets: %w", err) 62 } 63 if results.CurrentResultSet().RowCount() != rowsLimit { 64 return fmt.Errorf("unexpected rows count: %d", results.CurrentResultSet().RowCount()) 65 } 66 return results.Err() 67 }, table.WithIdempotent()) 68 scope.Require.NoError(err) 69 70 err = retry.Do(ctx, db, func(ctx context.Context, cc *sql.Conn) error { 71 rows, err := cc.QueryContext(ctx, fmt.Sprintf("SELECT * FROM `%s`;", tablePath)) 72 if err != nil { 73 return err 74 } 75 defer func() { 76 _ = rows.Close() 77 }() 78 count := 0 79 for rows.Next() { 80 count++ 81 } 82 if count != rowsLimit { 83 return fmt.Errorf("unexpected rows count: %d", count) 84 } 85 return rows.Err() 86 }, retry.WithIdempotent(true)) 87 scope.Require.NoError(err) 88 } 89 90 // upsert 1 row for get 1001 rows and truncated error 91 { 92 err := driver.Table().Do(ctx, func(ctx context.Context, s table.Session) error { 93 return s.BulkUpsert(ctx, tablePath, types.ListValue(types.StructValue( 94 types.StructFieldValue("id", types.Int64Value(rowsLimit)), 95 types.StructFieldValue("val", types.TextValue(strconv.Itoa(rowsLimit))), 96 ))) 97 }, table.WithIdempotent()) 98 scope.Require.NoError(err) 99 } 100 101 // select all rows with truncated result error 102 { 103 err := driver.Table().Do(ctx, func(ctx context.Context, s table.Session) error { 104 _, results, err := s.Execute(ctx, 105 table.DefaultTxControl(), 106 fmt.Sprintf("SELECT * FROM `%s`;", tablePath), 107 nil, 108 ) 109 if err != nil { 110 return err 111 } 112 if err = results.NextResultSetErr(ctx); err != nil { 113 return fmt.Errorf("no result sets: %w", err) 114 } 115 if results.CurrentResultSet().RowCount() != rowsLimit { 116 return fmt.Errorf("unexpected rows count: %d", results.CurrentResultSet().RowCount()) 117 } 118 return results.Err() // expected truncated error 119 }, table.WithIdempotent()) 120 scope.Require.ErrorIs(err, result.ErrTruncated) 121 122 err = retry.Do(ctx, db, func(ctx context.Context, cc *sql.Conn) error { 123 rows, err := cc.QueryContext(ctx, fmt.Sprintf("SELECT * FROM `%s`;", tablePath)) 124 if err != nil { 125 return err 126 } 127 defer func() { 128 _ = rows.Close() 129 }() 130 count := 0 131 for rows.Next() { 132 count++ 133 } 134 return rows.Err() 135 }, retry.WithIdempotent(true)) 136 scope.Require.ErrorIs(err, result.ErrTruncated) 137 } 138 139 // select all rows without truncated result error 140 { 141 err := driver.Table().Do(ctx, func(ctx context.Context, s table.Session) error { 142 _, results, err := s.Execute(ctx, 143 table.DefaultTxControl(), 144 fmt.Sprintf("SELECT * FROM `%s`;", tablePath), 145 nil, 146 options.WithIgnoreTruncated(), 147 ) 148 if err != nil { 149 return err 150 } 151 if err = results.NextResultSetErr(ctx); err != nil { 152 return fmt.Errorf("no result sets: %w", err) 153 } 154 if results.CurrentResultSet().RowCount() != rowsLimit { 155 return fmt.Errorf("unexpected rows count: %d", results.CurrentResultSet().RowCount()) 156 } 157 return results.Err() // expected nil 158 }, table.WithIdempotent()) 159 scope.Require.NoError(err) 160 } 161 162 // connect with default option ignore truncated without truncated result error 163 { 164 driver, err := driver.With(ctx, ydb.WithIgnoreTruncated()) 165 scope.Require.NoError(err) 166 167 err = driver.Table().Do(ctx, func(ctx context.Context, s table.Session) error { 168 _, results, err := s.Execute(ctx, 169 table.DefaultTxControl(), 170 fmt.Sprintf("SELECT * FROM `%s`;", tablePath), 171 nil, 172 ) 173 if err != nil { 174 return err 175 } 176 if err = results.NextResultSetErr(ctx); err != nil { 177 return fmt.Errorf("no result sets: %w", err) 178 } 179 if results.CurrentResultSet().RowCount() != rowsLimit { 180 return fmt.Errorf("unexpected rows count: %d", results.CurrentResultSet().RowCount()) 181 } 182 return results.Err() // expected nil 183 }, table.WithIdempotent()) 184 scope.Require.NoError(err) 185 186 db = sql.OpenDB(ydb.MustConnector(driver)) 187 err = retry.Do(ctx, db, func(ctx context.Context, cc *sql.Conn) error { 188 rows, err := cc.QueryContext(ctx, fmt.Sprintf("SELECT * FROM `%s`;", tablePath)) 189 if err != nil { 190 return err 191 } 192 defer func() { 193 _ = rows.Close() 194 }() 195 count := 0 196 for rows.Next() { 197 count++ 198 } 199 return rows.Err() 200 }, retry.WithIdempotent(true)) 201 scope.Require.NoError(err) 202 } 203 }