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  }