github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/tests/integration/database_sql_regression_test.go (about)

     1  //go:build integration
     2  // +build integration
     3  
     4  package integration
     5  
     6  import (
     7  	"context"
     8  	"database/sql"
     9  	"errors"
    10  	"fmt"
    11  	"math/rand"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/stretchr/testify/require"
    16  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
    17  
    18  	"github.com/ydb-platform/ydb-go-sdk/v3"
    19  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
    20  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/badconn"
    21  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest"
    22  	"github.com/ydb-platform/ydb-go-sdk/v3/retry"
    23  	"github.com/ydb-platform/ydb-go-sdk/v3/table"
    24  	"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
    25  )
    26  
    27  func TestRegressionCloud109307(t *testing.T) {
    28  	var (
    29  		ctx   = xtest.Context(t)
    30  		scope = newScope(t)
    31  		db    = scope.SQLDriverWithFolder(
    32  			ydb.WithTablePathPrefix(scope.Folder()),
    33  			ydb.WithAutoDeclare(),
    34  		)
    35  	)
    36  
    37  	ctx, cancel := context.WithTimeout(ctx, 42*time.Second)
    38  	defer cancel()
    39  
    40  	for i := int64(1); ; i++ {
    41  		if ctx.Err() != nil {
    42  			break
    43  		}
    44  
    45  		err := retry.DoTx(ctx, db, func(ctx context.Context, tx *sql.Tx) error {
    46  			//nolint:gosec
    47  			if rand.Int31n(3) == 0 {
    48  				return badconn.Map(xerrors.Operation(xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION)))
    49  			}
    50  			var rows *sql.Rows
    51  			rows, err := tx.QueryContext(ctx, `SELECT $i`, sql.Named("i", i))
    52  			if err != nil {
    53  				return err
    54  			}
    55  			defer rows.Close()
    56  			if !rows.Next() {
    57  				return errors.New("no rows")
    58  			}
    59  			var result interface{}
    60  			if err = rows.Scan(&result); err != nil {
    61  				return err
    62  			}
    63  			if result.(int64)%100 == 0 {
    64  				t.Logf("result: %+v\n", result)
    65  			}
    66  			return rows.Err()
    67  		}, retry.WithTxOptions(&sql.TxOptions{
    68  			Isolation: sql.LevelSnapshot,
    69  			ReadOnly:  true,
    70  		}), retry.WithIdempotent(true))
    71  		if ctx.Err() == nil {
    72  			require.NoError(t, err)
    73  		}
    74  	}
    75  }
    76  
    77  func TestRegressionKikimr17104(t *testing.T) {
    78  	var (
    79  		ctx   = xtest.Context(t)
    80  		scope = newScope(t)
    81  		db    = scope.SQLDriverWithFolder(
    82  			ydb.WithTablePathPrefix(scope.Folder()),
    83  			ydb.WithAutoDeclare(),
    84  		)
    85  		tableName       = t.Name()
    86  		upsertRowsCount = 100000
    87  		upsertChecksum  uint64
    88  	)
    89  
    90  	t.Run("data", func(t *testing.T) {
    91  		t.Run("prepare", func(t *testing.T) {
    92  			t.Run("scheme", func(t *testing.T) {
    93  				err := retry.Do(ydb.WithQueryMode(ctx, ydb.SchemeQueryMode), db,
    94  					func(ctx context.Context, cc *sql.Conn) (err error) {
    95  						_, err = cc.ExecContext(ctx,
    96  							fmt.Sprintf("CREATE TABLE %s (val Int32, PRIMARY KEY (val))", tableName),
    97  						)
    98  						if err != nil {
    99  							return err
   100  						}
   101  						return nil
   102  					}, retry.WithIdempotent(true),
   103  				)
   104  				require.NoError(t, err)
   105  			})
   106  			t.Run("data", func(t *testing.T) {
   107  				// - upsert data
   108  				t.Logf("> preparing values to upsert...\n")
   109  				values := make([]types.Value, 0, upsertRowsCount)
   110  				for i := 0; i < upsertRowsCount; i++ {
   111  					upsertChecksum += uint64(i)
   112  					values = append(values,
   113  						types.StructValue(
   114  							types.StructFieldValue("val", types.Int32Value(int32(i))),
   115  						),
   116  					)
   117  				}
   118  				t.Logf("> upsert data\n")
   119  				err := retry.Do(ydb.WithQueryMode(ctx, ydb.DataQueryMode), db,
   120  					func(ctx context.Context, cc *sql.Conn) (err error) {
   121  						_, err = cc.ExecContext(ctx,
   122  							fmt.Sprintf("UPSERT INTO %s SELECT val FROM AS_TABLE($values);", tableName),
   123  							table.NewQueryParameters(table.ValueParam("$values", types.ListValue(values...))),
   124  						)
   125  						if err != nil {
   126  							return err
   127  						}
   128  						return nil
   129  					}, retry.WithIdempotent(true),
   130  				)
   131  				require.NoError(t, err)
   132  			})
   133  		})
   134  		t.Run("scan", func(t *testing.T) {
   135  			t.Run("query", func(t *testing.T) {
   136  				var (
   137  					rowsCount int
   138  					checkSum  uint64
   139  				)
   140  				err := retry.Do(ydb.WithQueryMode(ctx, ydb.ScanQueryMode), db,
   141  					func(ctx context.Context, cc *sql.Conn) (err error) {
   142  						var rows *sql.Rows
   143  						rowsCount = 0
   144  						checkSum = 0
   145  						rows, err = cc.QueryContext(ctx, fmt.Sprintf("SELECT val FROM %s", tableName))
   146  						if err != nil {
   147  							return err
   148  						}
   149  						for rows.NextResultSet() {
   150  							for rows.Next() {
   151  								rowsCount++
   152  								var val uint64
   153  								err = rows.Scan(&val)
   154  								if err != nil {
   155  									return err
   156  								}
   157  								checkSum += val
   158  							}
   159  						}
   160  						return rows.Err()
   161  					}, retry.WithIdempotent(true),
   162  				)
   163  				require.NoError(t, err)
   164  				require.Equal(t, upsertRowsCount, rowsCount)
   165  				require.Equal(t, upsertChecksum, checkSum)
   166  			})
   167  		})
   168  	})
   169  }