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

     1  //go:build integration
     2  // +build integration
     3  
     4  package integration
     5  
     6  import (
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/google/uuid"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/ydb-platform/ydb-go-sdk/v3"
    15  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/query/tx"
    16  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/version"
    17  	"github.com/ydb-platform/ydb-go-sdk/v3/query"
    18  	"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
    19  )
    20  
    21  func TestUUIDSerializationQueryServiceIssue1501(t *testing.T) {
    22  	// https://github.com/ydb-platform/ydb-go-sdk/issues/1501
    23  	// test with special uuid - all bytes are different for check any byte swaps
    24  
    25  	t.Run("old-send-with-force-wrapper", func(t *testing.T) {
    26  		// test old behavior - for test way of safe work with data, written with bagged API version
    27  		var (
    28  			scope = newScope(t)
    29  			ctx   = scope.Ctx
    30  			db    = scope.Driver()
    31  		)
    32  
    33  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
    34  		expectedResultWithBug := "2d9e498b-b746-9cfb-084d-de4e1cb4736e"
    35  		id := uuid.MustParse(idString)
    36  		row, err := db.Query().QueryRow(ctx, `
    37  DECLARE $val AS UUID;
    38  
    39  SELECT CAST($val AS Utf8)`,
    40  			query.WithIdempotent(),
    41  			query.WithParameters(ydb.ParamsBuilder().Param("$val").UUIDWithIssue1501Value(id).Build()),
    42  			query.WithTxControl(tx.SerializableReadWriteTxControl()),
    43  		)
    44  
    45  		require.NoError(t, err)
    46  
    47  		var res string
    48  
    49  		err = row.Scan(&res)
    50  		require.NoError(t, err)
    51  		require.Equal(t, expectedResultWithBug, res)
    52  	})
    53  	t.Run("old-receive-to-bytes", func(t *testing.T) {
    54  		// test old behavior - for test way of safe work with data, written with bagged API version
    55  		var (
    56  			scope = newScope(t)
    57  			ctx   = scope.Ctx
    58  			db    = scope.Driver()
    59  		)
    60  
    61  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
    62  		row, err := db.Query().QueryRow(ctx, `
    63  DECLARE $val AS Text;
    64  
    65  SELECT CAST($val AS UUID)`,
    66  			query.WithIdempotent(),
    67  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Text(idString).Build()),
    68  			query.WithTxControl(tx.SerializableReadWriteTxControl()),
    69  		)
    70  
    71  		require.NoError(t, err)
    72  
    73  		var res [16]byte
    74  
    75  		err = row.Scan(&res)
    76  		require.ErrorIs(t, err, types.ErrIssue1501BadUUID)
    77  	})
    78  	t.Run("old-receive-to-bytes-with-force-wrapper", func(t *testing.T) {
    79  		// test old behavior - for test way of safe work with data, written with bagged API version
    80  		var (
    81  			scope = newScope(t)
    82  			ctx   = scope.Ctx
    83  			db    = scope.Driver()
    84  		)
    85  
    86  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
    87  		expectedResultWithBug := "8b499e2d-46b7-fb9c-4d08-4ede6e73b41c"
    88  		row, err := db.Query().QueryRow(ctx, `
    89  DECLARE $val AS Text;
    90  
    91  SELECT CAST($val AS UUID)`,
    92  			query.WithIdempotent(),
    93  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Text(idString).Build()),
    94  			query.WithTxControl(tx.SerializableReadWriteTxControl()),
    95  		)
    96  
    97  		require.NoError(t, err)
    98  
    99  		var res types.UUIDBytesWithIssue1501Type
   100  
   101  		err = row.Scan(&res)
   102  		require.NoError(t, err)
   103  
   104  		resUUID := uuid.UUID(res.AsBytesArray())
   105  		require.Equal(t, expectedResultWithBug, resUUID.String())
   106  	})
   107  	t.Run("old-receive-to-string", func(t *testing.T) {
   108  		// test old behavior - for test way of safe work with data, written with bagged API version
   109  		var (
   110  			scope = newScope(t)
   111  			ctx   = scope.Ctx
   112  			db    = scope.Driver()
   113  		)
   114  
   115  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
   116  		row, err := db.Query().QueryRow(ctx, `
   117  DECLARE $val AS Text;
   118  
   119  SELECT CAST($val AS UUID)`,
   120  			query.WithIdempotent(),
   121  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Text(idString).Build()),
   122  			query.WithTxControl(tx.SerializableReadWriteTxControl()),
   123  		)
   124  
   125  		require.NoError(t, err)
   126  
   127  		var res string
   128  
   129  		err = row.Scan(&res)
   130  		require.ErrorIs(t, err, types.ErrIssue1501BadUUID)
   131  	})
   132  	t.Run("old-receive-to-string-with-force-wrapper", func(t *testing.T) {
   133  		// test old behavior - for test way of safe work with data, written with bagged API version
   134  		var (
   135  			scope = newScope(t)
   136  			ctx   = scope.Ctx
   137  			db    = scope.Driver()
   138  		)
   139  
   140  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
   141  		expectedResultWithBug := []byte{0x8b, 0x49, 0x9e, 0x2d, 0x46, 0xb7, 0xfb, 0x9c, 0x4d, 0x8, 0x4e, 0xde, 0x6e, 0x73, 0xb4, 0x1c}
   142  		row, err := db.Query().QueryRow(ctx, `
   143  DECLARE $val AS Text;
   144  
   145  SELECT CAST($val AS UUID)`,
   146  			query.WithIdempotent(),
   147  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Text(idString).Build()),
   148  			query.WithTxControl(tx.SerializableReadWriteTxControl()),
   149  		)
   150  
   151  		require.NoError(t, err)
   152  
   153  		var resFromDB types.UUIDBytesWithIssue1501Type
   154  
   155  		err = row.Scan(&resFromDB)
   156  		require.NoError(t, err)
   157  
   158  		res := resFromDB.AsBrokenString()
   159  		require.Equal(t, expectedResultWithBug, []byte(res))
   160  	})
   161  	t.Run("old-send-receive-with-force-wrapper", func(t *testing.T) {
   162  		// test old behavior - for test way of safe work with data, written with bagged API version
   163  		var (
   164  			scope = newScope(t)
   165  			ctx   = scope.Ctx
   166  			db    = scope.Driver()
   167  		)
   168  
   169  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
   170  		id := uuid.MustParse(idString)
   171  		row, err := db.Query().QueryRow(ctx, `
   172  DECLARE $val AS UUID;
   173  
   174  SELECT $val`,
   175  			query.WithIdempotent(),
   176  			query.WithParameters(ydb.ParamsBuilder().Param("$val").UUIDWithIssue1501Value(id).Build()),
   177  			query.WithTxControl(tx.SerializableReadWriteTxControl()),
   178  		)
   179  
   180  		require.NoError(t, err)
   181  
   182  		var resWrapper types.UUIDBytesWithIssue1501Type
   183  		err = row.Scan(&resWrapper)
   184  		require.NoError(t, err)
   185  
   186  		resUUID := uuid.UUID(resWrapper.AsBytesArray())
   187  
   188  		require.Equal(t, id, resUUID)
   189  	})
   190  	t.Run("good-send", func(t *testing.T) {
   191  		var (
   192  			scope = newScope(t)
   193  			ctx   = scope.Ctx
   194  			db    = scope.Driver()
   195  		)
   196  
   197  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
   198  		id := uuid.MustParse(idString)
   199  		row, err := db.Query().QueryRow(ctx, `
   200  DECLARE $val AS UUID;
   201  
   202  SELECT CAST($val AS Utf8)`,
   203  			query.WithIdempotent(),
   204  			query.WithTxControl(query.SerializableReadWriteTxControl()),
   205  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Uuid(id).Build()),
   206  		)
   207  
   208  		require.NoError(t, err)
   209  
   210  		var res string
   211  		err = row.Scan(&res)
   212  		require.NoError(t, err)
   213  		require.Equal(t, id.String(), res)
   214  	})
   215  	t.Run("good-receive", func(t *testing.T) {
   216  		// test old behavior - for test way of safe work with data, written with bagged API version
   217  		var (
   218  			scope = newScope(t)
   219  			ctx   = scope.Ctx
   220  			db    = scope.Driver()
   221  		)
   222  
   223  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
   224  		row, err := db.Query().QueryRow(ctx, `
   225  DECLARE $val AS Utf8;
   226  
   227  SELECT CAST($val AS UUID)`,
   228  			query.WithIdempotent(),
   229  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Text(idString).Build()),
   230  			query.WithTxControl(query.SerializableReadWriteTxControl()),
   231  		)
   232  
   233  		require.NoError(t, err)
   234  
   235  		var res uuid.UUID
   236  
   237  		err = row.Scan(&res)
   238  		require.NoError(t, err)
   239  
   240  		resString := strings.ToUpper(res.String())
   241  		require.Equal(t, idString, resString)
   242  	})
   243  	t.Run("good-send-receive", func(t *testing.T) {
   244  		var (
   245  			scope = newScope(t)
   246  			ctx   = scope.Ctx
   247  			db    = scope.Driver()
   248  		)
   249  
   250  		idString := "6E73B41C-4EDE-4D08-9CFB-B7462D9E498B"
   251  		id := uuid.MustParse(idString)
   252  		row, err := db.Query().QueryRow(ctx, `
   253  DECLARE $val AS UUID;
   254  
   255  SELECT $val`,
   256  			query.WithIdempotent(),
   257  			query.WithParameters(ydb.ParamsBuilder().Param("$val").Uuid(id).Build()),
   258  			query.WithTxControl(query.SerializableReadWriteTxControl()),
   259  		)
   260  
   261  		require.NoError(t, err)
   262  
   263  		var res uuid.UUID
   264  		err = row.Scan(&res)
   265  		require.NoError(t, err)
   266  		require.Equal(t, id.String(), res.String())
   267  	})
   268  }
   269  
   270  // https://github.com/ydb-platform/ydb-go-sdk/issues/1506
   271  func TestIssue1506TypedNullPushdown(t *testing.T) {
   272  	if version.Lt(os.Getenv("YDB_VERSION"), "24.1") {
   273  		t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'")
   274  	}
   275  
   276  	scope := newScope(t)
   277  	ctx := scope.Ctx
   278  	db := scope.Driver()
   279  
   280  	val := int64(123)
   281  	row, err := db.Query().QueryRow(ctx, `
   282  DECLARE $arg1 AS Int64?;
   283  DECLARE $arg2 AS Int64?;
   284  
   285  SELECT CAST($arg1 AS Utf8) AS v1, CAST($arg2 AS Utf8) AS v2
   286  `, query.WithParameters(
   287  		ydb.ParamsBuilder().
   288  			Param("$arg1").BeginOptional().Int64(nil).EndOptional().
   289  			Param("$arg2").BeginOptional().Int64(&val).EndOptional().
   290  			Build(),
   291  	),
   292  	)
   293  	require.NoError(t, err)
   294  
   295  	var res struct {
   296  		V1 *string `sql:"v1"`
   297  		V2 *string `sql:"v2"`
   298  	}
   299  	err = row.ScanStruct(&res)
   300  	require.NoError(t, err)
   301  
   302  	require.Nil(t, res.V1)
   303  	require.Equal(t, "123", *res.V2)
   304  }