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

     1  //go:build integration
     2  // +build integration
     3  
     4  package integration
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/ydb-platform/ydb-go-sdk/v3"
    16  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/version"
    17  	"github.com/ydb-platform/ydb-go-sdk/v3/query"
    18  )
    19  
    20  func TestQueryExecute(t *testing.T) {
    21  	if version.Lt(os.Getenv("YDB_VERSION"), "24.1") {
    22  		t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'")
    23  	}
    24  
    25  	ctx, cancel := context.WithCancel(context.Background())
    26  	defer cancel()
    27  
    28  	db, err := ydb.Open(ctx,
    29  		os.Getenv("YDB_CONNECTION_STRING"),
    30  		ydb.WithAccessTokenCredentials(os.Getenv("YDB_ACCESS_TOKEN_CREDENTIALS")),
    31  	)
    32  	require.NoError(t, err)
    33  	t.Run("Scan", func(t *testing.T) {
    34  		var (
    35  			p1 string
    36  			p2 uint64
    37  			p3 time.Duration
    38  		)
    39  		err = db.Query().Do(ctx, func(ctx context.Context, s query.Session) (err error) {
    40  			_, res, err := s.Execute(ctx, `
    41  				DECLARE $p1 AS Text;
    42  				DECLARE $p2 AS Uint64;
    43  				DECLARE $p3 AS Interval;
    44  				SELECT $p1, $p2, $p3;
    45  				`,
    46  				query.WithParameters(
    47  					ydb.ParamsBuilder().
    48  						Param("$p1").Text("test").
    49  						Param("$p2").Uint64(100500000000).
    50  						Param("$p3").Interval(time.Duration(100500000000)).
    51  						Build(),
    52  				),
    53  				query.WithSyntax(query.SyntaxYQL),
    54  			)
    55  			if err != nil {
    56  				return err
    57  			}
    58  			rs, err := res.NextResultSet(ctx)
    59  			if err != nil {
    60  				return err
    61  			}
    62  			row, err := rs.NextRow(ctx)
    63  			if err != nil {
    64  				return err
    65  			}
    66  			err = row.Scan(&p1, &p2, &p3)
    67  			if err != nil {
    68  				return err
    69  			}
    70  			return res.Err()
    71  		}, query.WithIdempotent())
    72  		require.NoError(t, err)
    73  		require.EqualValues(t, "test", p1)
    74  		require.EqualValues(t, 100500000000, p2)
    75  		require.EqualValues(t, time.Duration(100500000000), p3)
    76  	})
    77  	t.Run("ScanNamed", func(t *testing.T) {
    78  		var (
    79  			p1 string
    80  			p2 uint64
    81  			p3 time.Duration
    82  		)
    83  		err = db.Query().Do(ctx, func(ctx context.Context, s query.Session) (err error) {
    84  			_, res, err := s.Execute(ctx, `
    85  				DECLARE $p1 AS Text;
    86  				DECLARE $p2 AS Uint64;
    87  				DECLARE $p3 AS Interval;
    88  				SELECT $p1 AS p1, $p2 AS p2, $p3 AS p3;
    89  				`,
    90  				query.WithParameters(
    91  					ydb.ParamsBuilder().
    92  						Param("$p1").Text("test").
    93  						Param("$p2").Uint64(100500000000).
    94  						Param("$p3").Interval(time.Duration(100500000000)).
    95  						Build(),
    96  				),
    97  				query.WithSyntax(query.SyntaxYQL),
    98  			)
    99  			if err != nil {
   100  				return err
   101  			}
   102  			rs, err := res.NextResultSet(ctx)
   103  			if err != nil {
   104  				return err
   105  			}
   106  			row, err := rs.NextRow(ctx)
   107  			if err != nil {
   108  				return err
   109  			}
   110  			err = row.ScanNamed(
   111  				query.Named("p1", &p1),
   112  				query.Named("p2", &p2),
   113  				query.Named("p3", &p3),
   114  			)
   115  			if err != nil {
   116  				return err
   117  			}
   118  			return res.Err()
   119  		}, query.WithIdempotent())
   120  		require.NoError(t, err)
   121  		require.EqualValues(t, "test", p1)
   122  		require.EqualValues(t, 100500000000, p2)
   123  		require.EqualValues(t, time.Duration(100500000000), p3)
   124  	})
   125  	t.Run("ScanStruct", func(t *testing.T) {
   126  		var data struct {
   127  			P1 *string       `sql:"p1"`
   128  			P2 uint64        `sql:"p2"`
   129  			P3 time.Duration `sql:"p3"`
   130  			P4 *string       `sql:"p4"`
   131  		}
   132  		err = db.Query().Do(ctx, func(ctx context.Context, s query.Session) (err error) {
   133  			_, res, err := s.Execute(ctx, `
   134  				DECLARE $p1 AS Text;
   135  				DECLARE $p2 AS Uint64;
   136  				DECLARE $p3 AS Interval;
   137  				SELECT CAST($p1 AS Optional<Text>) AS p1, $p2 AS p2, $p3 AS p3, CAST(NULL AS Optional<Text>) AS p4;
   138  				`,
   139  				query.WithParameters(
   140  					ydb.ParamsBuilder().
   141  						Param("$p1").Text("test").
   142  						Param("$p2").Uint64(100500000000).
   143  						Param("$p3").Interval(time.Duration(100500000000)).
   144  						Build(),
   145  				),
   146  				query.WithSyntax(query.SyntaxYQL),
   147  			)
   148  			if err != nil {
   149  				return err
   150  			}
   151  			rs, err := res.NextResultSet(ctx)
   152  			if err != nil {
   153  				return err
   154  			}
   155  			row, err := rs.NextRow(ctx)
   156  			if err != nil {
   157  				return err
   158  			}
   159  			err = row.ScanStruct(&data)
   160  			if err != nil {
   161  				return err
   162  			}
   163  			return res.Err()
   164  		}, query.WithIdempotent())
   165  		require.NoError(t, err)
   166  		require.NotNil(t, data.P1)
   167  		require.EqualValues(t, "test", *data.P1)
   168  		require.EqualValues(t, 100500000000, data.P2)
   169  		require.EqualValues(t, time.Duration(100500000000), data.P3)
   170  		require.Nil(t, data.P4)
   171  	})
   172  	t.Run("Transaction", func(t *testing.T) {
   173  		t.Run("Explicit", func(t *testing.T) {
   174  			err = db.Query().Do(ctx, func(ctx context.Context, s query.Session) (err error) {
   175  				tx, err := s.Begin(ctx, query.TxSettings(query.WithSerializableReadWrite()))
   176  				if err != nil {
   177  					return err
   178  				}
   179  				res, err := tx.Execute(ctx, `SELECT 1`)
   180  				if err != nil {
   181  					return err
   182  				}
   183  				rs, err := res.NextResultSet(ctx)
   184  				if err != nil {
   185  					return err
   186  				}
   187  				row, err := rs.NextRow(ctx)
   188  				if err != nil {
   189  					return err
   190  				}
   191  				var v int32
   192  				err = row.Scan(&v)
   193  				if err != nil {
   194  					return err
   195  				}
   196  				if v != 1 {
   197  					return fmt.Errorf("unexpected value from database: %d", v)
   198  				}
   199  				if err = res.Err(); err != nil {
   200  					return err
   201  				}
   202  				return tx.CommitTx(ctx)
   203  			}, query.WithIdempotent())
   204  			require.NoError(t, err)
   205  		})
   206  		t.Run("Lazy", func(t *testing.T) {
   207  			err = db.Query().Do(ctx, func(ctx context.Context, s query.Session) (err error) {
   208  				tx, res, err := s.Execute(ctx, `SELECT 1`,
   209  					query.WithTxControl(query.TxControl(query.BeginTx(query.WithSerializableReadWrite()))),
   210  				)
   211  				if err != nil {
   212  					return err
   213  				}
   214  				rs, err := res.NextResultSet(ctx)
   215  				if err != nil {
   216  					return err
   217  				}
   218  				row, err := rs.NextRow(ctx)
   219  				if err != nil {
   220  					return err
   221  				}
   222  				var v int32
   223  				err = row.Scan(&v)
   224  				if err != nil {
   225  					return err
   226  				}
   227  				if v != 1 {
   228  					return fmt.Errorf("unexpected value from database: %d", v)
   229  				}
   230  				if err = res.Err(); err != nil {
   231  					return err
   232  				}
   233  				res, err = tx.Execute(ctx, `SELECT 2`, query.WithCommit())
   234  				if err != nil {
   235  					return err
   236  				}
   237  				rs, err = res.NextResultSet(ctx)
   238  				if err != nil {
   239  					return err
   240  				}
   241  				row, err = rs.NextRow(ctx)
   242  				if err != nil {
   243  					return err
   244  				}
   245  				err = row.Scan(&v)
   246  				if err != nil {
   247  					return err
   248  				}
   249  				if v != 2 {
   250  					return fmt.Errorf("unexpected value from database: %d", v)
   251  				}
   252  				return res.Err()
   253  			}, query.WithIdempotent())
   254  			require.NoError(t, err)
   255  		})
   256  	})
   257  }