github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/example_test.go (about)

     1  //go:build go1.23
     2  
     3  package ydb_test
     4  
     5  import (
     6  	"context"
     7  	"database/sql"
     8  	"fmt"
     9  	"io"
    10  	"log"
    11  	"time"
    12  
    13  	"google.golang.org/grpc"
    14  	"google.golang.org/grpc/encoding/gzip"
    15  
    16  	"github.com/ydb-platform/ydb-go-sdk/v3"
    17  	"github.com/ydb-platform/ydb-go-sdk/v3/balancers"
    18  	"github.com/ydb-platform/ydb-go-sdk/v3/config"
    19  	"github.com/ydb-platform/ydb-go-sdk/v3/query"
    20  	"github.com/ydb-platform/ydb-go-sdk/v3/retry"
    21  	"github.com/ydb-platform/ydb-go-sdk/v3/table"
    22  	"github.com/ydb-platform/ydb-go-sdk/v3/table/result/named"
    23  	"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
    24  	"github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions"
    25  )
    26  
    27  //nolint:testableexamples, nonamedreturns
    28  func Example_query() {
    29  	ctx := context.TODO()
    30  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
    31  	if err != nil {
    32  		panic(err)
    33  	}
    34  	defer db.Close(ctx) // cleanup resources
    35  
    36  	materializedResult, err := db.Query().Query( // Do retry operation on errors with best effort
    37  		ctx, // context manage exiting from Do
    38  		`SELECT $id as myId, $str as myStr`,
    39  		query.WithParameters(
    40  			ydb.ParamsBuilder().
    41  				Param("$id").Uint64(42).
    42  				Param("$str").Text("my string").
    43  				Build(),
    44  		),
    45  		query.WithIdempotent(),
    46  	)
    47  	if err != nil {
    48  		panic(err)
    49  	}
    50  	defer func() { _ = materializedResult.Close(ctx) }() // cleanup resources
    51  	for rs, err := range materializedResult.ResultSets(ctx) {
    52  		if err != nil {
    53  			panic(err)
    54  		}
    55  		for row, err := range rs.Rows(ctx) {
    56  			if err != nil {
    57  				panic(err)
    58  			}
    59  			type myStruct struct {
    60  				ID  uint64 `sql:"id"`
    61  				Str string `sql:"myStr"`
    62  			}
    63  			var s myStruct
    64  			if err = row.ScanStruct(&s); err != nil {
    65  				panic(err)
    66  			}
    67  		}
    68  	}
    69  	if err != nil {
    70  		panic(err)
    71  	}
    72  }
    73  
    74  //nolint:testableexamples, nonamedreturns
    75  func Example_table() {
    76  	ctx := context.TODO()
    77  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
    78  	if err != nil {
    79  		log.Fatal(err)
    80  	}
    81  	defer db.Close(ctx) // cleanup resources
    82  	var (
    83  		query = `SELECT 42 as id, "my string" as myStr`
    84  		id    int32  // required value
    85  		myStr string // optional value
    86  	)
    87  	err = db.Table().Do( // Do retry operation on errors with best effort
    88  		ctx, // context manage exiting from Do
    89  		func(ctx context.Context, s table.Session) (err error) { // retry operation
    90  			_, res, err := s.Execute(ctx, table.DefaultTxControl(), query, nil)
    91  			if err != nil {
    92  				return err // for auto-retry with driver
    93  			}
    94  			defer res.Close()                                // cleanup resources
    95  			if err = res.NextResultSetErr(ctx); err != nil { // check single result set and switch to it
    96  				return err // for auto-retry with driver
    97  			}
    98  			for res.NextRow() { // iterate over rows
    99  				err = res.ScanNamed(
   100  					named.Required("id", &id),
   101  					named.OptionalWithDefault("myStr", &myStr),
   102  				)
   103  				if err != nil {
   104  					return err // generally scan error not retryable, return it for driver check error
   105  				}
   106  				log.Printf("id=%v, myStr='%s'\n", id, myStr)
   107  			}
   108  
   109  			return res.Err() // return finally result error for auto-retry with driver
   110  		},
   111  		table.WithIdempotent(),
   112  	)
   113  	if err != nil {
   114  		log.Printf("unexpected error: %v", err)
   115  	}
   116  }
   117  
   118  //nolint:testableexamples
   119  func Example_databaseSQL() {
   120  	db, err := sql.Open("ydb", "grpc://localhost:2136/local")
   121  	if err != nil {
   122  		log.Fatal(err)
   123  	}
   124  	defer func() { _ = db.Close() }() // cleanup resources
   125  
   126  	db.SetMaxOpenConns(100)
   127  	db.SetMaxIdleConns(100)
   128  	db.SetConnMaxIdleTime(time.Second) // workaround for background keep-aliving of YDB sessions
   129  
   130  	var (
   131  		id    int32  // required value
   132  		myStr string // optional value
   133  	)
   134  	// retry transaction
   135  	err = retry.DoTx(context.TODO(), db, func(ctx context.Context, tx *sql.Tx) error {
   136  		row := tx.QueryRowContext(ctx, `SELECT 42 as id, "my string" as myStr`)
   137  		if err = row.Scan(&id, &myStr); err != nil {
   138  			return err
   139  		}
   140  		log.Printf("id=%v, myStr='%s'\n", id, myStr)
   141  
   142  		return nil
   143  	}, retry.WithIdempotent(true))
   144  	if err != nil {
   145  		log.Printf("query failed: %v", err)
   146  	}
   147  }
   148  
   149  //nolint:testableexamples
   150  func Example_databaseSQLBindNumericArgs() {
   151  	db, err := sql.Open("ydb",
   152  		"grpc://localhost:2136/local?go_query_bind=declare,numeric",
   153  	)
   154  	if err != nil {
   155  		log.Fatal(err)
   156  	}
   157  	defer func() { _ = db.Close() }() // cleanup resources
   158  
   159  	var (
   160  		id    int32  // required value
   161  		myStr string // optional value
   162  	)
   163  
   164  	// numeric args
   165  	row := db.QueryRowContext(context.TODO(), "SELECT $2, $1", 42, "my string")
   166  	if err = row.Scan(&myStr, &id); err != nil {
   167  		log.Printf("query failed: %v", err)
   168  	} else {
   169  		log.Printf("id=%v, myStr='%s'\n", id, myStr)
   170  	}
   171  }
   172  
   173  //nolint:testableexamples
   174  func Example_databaseSQLBindNumericArgsOverConnector() {
   175  	var (
   176  		ctx          = context.TODO()
   177  		nativeDriver = ydb.MustOpen(ctx, "grpc://localhost:2136/local")
   178  		db           = sql.OpenDB(
   179  			ydb.MustConnector(nativeDriver,
   180  				ydb.WithAutoDeclare(),
   181  				ydb.WithNumericArgs(),
   182  			),
   183  		)
   184  	)
   185  	defer nativeDriver.Close(ctx) // cleanup resources
   186  	defer db.Close()
   187  
   188  	// numeric args
   189  	row := db.QueryRowContext(context.TODO(),
   190  		"SELECT $2, $1",
   191  		42, "my string",
   192  	)
   193  
   194  	var (
   195  		id    int32  // required value
   196  		myStr string // optional value
   197  	)
   198  	if err := row.Scan(&myStr, &id); err != nil {
   199  		log.Printf("query failed: %v", err)
   200  	} else {
   201  		log.Printf("id=%v, myStr='%s'\n", id, myStr)
   202  	}
   203  }
   204  
   205  //nolint:testableexamples
   206  func Example_databaseSQLBindPositionalArgs() {
   207  	db, err := sql.Open("ydb",
   208  		"grpc://localhost:2136/local?go_query_bind=declare,positional",
   209  	)
   210  	if err != nil {
   211  		log.Fatal(err)
   212  	}
   213  	defer func() { _ = db.Close() }() // cleanup resources
   214  
   215  	var (
   216  		id    int32  // required value
   217  		myStr string // optional value
   218  	)
   219  
   220  	// positional args
   221  	row := db.QueryRowContext(context.TODO(), "SELECT ?, ?", 42, "my string")
   222  	if err = row.Scan(&id, &myStr); err != nil {
   223  		log.Printf("query failed: %v", err)
   224  	} else {
   225  		log.Printf("id=%v, myStr='%s'\n", id, myStr)
   226  	}
   227  }
   228  
   229  //nolint:testableexamples
   230  func Example_databaseSQLBindPositionalArgsOverConnector() {
   231  	var (
   232  		ctx          = context.TODO()
   233  		nativeDriver = ydb.MustOpen(ctx, "grpc://localhost:2136/local")
   234  		db           = sql.OpenDB(
   235  			ydb.MustConnector(nativeDriver,
   236  				ydb.WithAutoDeclare(),
   237  				ydb.WithNumericArgs(),
   238  			),
   239  		)
   240  	)
   241  	defer nativeDriver.Close(ctx) // cleanup resources
   242  	defer db.Close()
   243  
   244  	// positional args
   245  	row := db.QueryRowContext(context.TODO(), "SELECT ?, ?", 42, "my string")
   246  
   247  	var (
   248  		id    int32  // required value
   249  		myStr string // optional value
   250  	)
   251  	if err := row.Scan(&id, &myStr); err != nil {
   252  		log.Printf("query failed: %v", err)
   253  	} else {
   254  		log.Printf("id=%v, myStr='%s'\n", id, myStr)
   255  	}
   256  }
   257  
   258  //nolint:testableexamples
   259  func Example_databaseSQLBindTablePathPrefix() {
   260  	db, err := sql.Open("ydb",
   261  		"grpc://localhost:2136/local?go_query_bind=table_path_prefix(/local/path/to/tables)",
   262  	)
   263  	if err != nil {
   264  		log.Fatal(err)
   265  	}
   266  	defer func() { _ = db.Close() }() // cleanup resources
   267  
   268  	var (
   269  		id    int32  // required value
   270  		title string // optional value
   271  	)
   272  
   273  	// full table path is "/local/path/to/tables/series"
   274  	row := db.QueryRowContext(context.TODO(), "SELECT id, title FROM series")
   275  	if err = row.Scan(&id, &title); err != nil {
   276  		log.Printf("query failed: %v", err)
   277  	} else {
   278  		log.Printf("id=%v, title='%s'\n", id, title)
   279  	}
   280  }
   281  
   282  //nolint:testableexamples
   283  func Example_databaseSQLBindTablePathPrefixOverConnector() {
   284  	var (
   285  		ctx          = context.TODO()
   286  		nativeDriver = ydb.MustOpen(ctx, "grpc://localhost:2136/local")
   287  		db           = sql.OpenDB(ydb.MustConnector(nativeDriver,
   288  			ydb.WithTablePathPrefix("/local/path/to/my/folder"),
   289  		))
   290  	)
   291  
   292  	// full table path is "/local/path/to/tables/series"
   293  	row := db.QueryRowContext(context.TODO(), "SELECT id, title FROM series")
   294  
   295  	var (
   296  		id    int32  // required value
   297  		title string // optional value
   298  	)
   299  	if err := row.Scan(&id, &title); err != nil {
   300  		log.Printf("query failed: %v", err)
   301  	} else {
   302  		log.Printf("id=%v, title='%s'\n", id, title)
   303  	}
   304  }
   305  
   306  //nolint:testableexamples
   307  func Example_databaseSQLBindAutoDeclare() {
   308  	db, err := sql.Open("ydb",
   309  		"grpc://localhost:2136/local?go_query_bind=declare",
   310  	)
   311  	if err != nil {
   312  		log.Fatal(err)
   313  	}
   314  	defer func() { _ = db.Close() }() // cleanup resources
   315  
   316  	var (
   317  		id    int32  // required value
   318  		title string // optional value
   319  	)
   320  
   321  	row := db.QueryRowContext(context.TODO(), "SELECT $id, $title",
   322  		table.ValueParam("$id", types.Uint64Value(42)),
   323  		table.ValueParam("$title", types.TextValue("title")),
   324  	)
   325  	if err = row.Scan(&id, &title); err != nil {
   326  		log.Printf("query failed: %v", err)
   327  	} else {
   328  		log.Printf("id=%v, title='%s'\n", id, title)
   329  	}
   330  }
   331  
   332  //nolint:testableexamples
   333  func Example_databaseSQLBindAutoDeclareOverConnector() {
   334  	var (
   335  		ctx          = context.TODO()
   336  		nativeDriver = ydb.MustOpen(ctx, "grpc://localhost:2136/local")
   337  		db           = sql.OpenDB(ydb.MustConnector(nativeDriver,
   338  			ydb.WithAutoDeclare(),
   339  		))
   340  	)
   341  
   342  	row := db.QueryRowContext(context.TODO(), "SELECT $id, $title",
   343  		table.ValueParam("$id", types.Uint64Value(42)),
   344  		table.ValueParam("$title", types.TextValue("title")),
   345  	)
   346  
   347  	var (
   348  		id    int32  // required value
   349  		title string // optional value
   350  	)
   351  	if err := row.Scan(&id, &title); err != nil {
   352  		log.Printf("query failed: %v", err)
   353  	} else {
   354  		log.Printf("id=%v, title='%s'\n", id, title)
   355  	}
   356  }
   357  
   358  //nolint:testableexamples
   359  func Example_topic() {
   360  	ctx := context.TODO()
   361  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   362  	if err != nil {
   363  		fmt.Printf("failed connect: %v", err)
   364  
   365  		return
   366  	}
   367  	defer db.Close(ctx) // cleanup resources
   368  
   369  	reader, err := db.Topic().StartReader("consumer", topicoptions.ReadTopic("/topic/path"))
   370  	if err != nil {
   371  		fmt.Printf("failed start reader: %v", err)
   372  
   373  		return
   374  	}
   375  
   376  	for {
   377  		mess, err := reader.ReadMessage(ctx)
   378  		if err != nil {
   379  			fmt.Printf("failed start reader: %v", err)
   380  
   381  			return
   382  		}
   383  
   384  		content, err := io.ReadAll(mess)
   385  		if err != nil {
   386  			fmt.Printf("failed start reader: %v", err)
   387  
   388  			return
   389  		}
   390  		fmt.Println(string(content))
   391  	}
   392  }
   393  
   394  //nolint:testableexamples
   395  func Example_scripting() {
   396  	ctx := context.TODO()
   397  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   398  	if err != nil {
   399  		fmt.Printf("failed to connect: %v", err)
   400  
   401  		return
   402  	}
   403  	defer db.Close(ctx)                                               // cleanup resources
   404  	if err = retry.Retry(ctx, func(ctx context.Context) (err error) { //nolint:nonamedreturns
   405  		res, err := db.Scripting().Execute(
   406  			ctx,
   407  			"SELECT 1+1",
   408  			table.NewQueryParameters(),
   409  		)
   410  		if err != nil {
   411  			return err
   412  		}
   413  		defer res.Close() // cleanup resources
   414  		if !res.NextResultSet(ctx) {
   415  			return retry.RetryableError(
   416  				fmt.Errorf("no result sets"), //nolint:goerr113
   417  				retry.WithBackoff(retry.TypeNoBackoff),
   418  			)
   419  		}
   420  		if !res.NextRow() {
   421  			return retry.RetryableError(
   422  				fmt.Errorf("no rows"), //nolint:goerr113
   423  				retry.WithBackoff(retry.TypeSlowBackoff),
   424  			)
   425  		}
   426  		var sum int32
   427  		if err = res.Scan(&sum); err != nil {
   428  			return fmt.Errorf("scan failed: %w", err)
   429  		}
   430  		if sum != 2 {
   431  			return fmt.Errorf("unexpected sum: %v", sum) //nolint:goerr113
   432  		}
   433  
   434  		return res.Err()
   435  	}, retry.WithIdempotent(true)); err != nil {
   436  		fmt.Printf("Execute failed: %v", err)
   437  	}
   438  }
   439  
   440  //nolint:testableexamples
   441  func Example_discovery() {
   442  	ctx := context.TODO()
   443  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   444  	if err != nil {
   445  		fmt.Printf("failed to connect: %v", err)
   446  
   447  		return
   448  	}
   449  	defer db.Close(ctx) // cleanup resources
   450  	endpoints, err := db.Discovery().Discover(ctx)
   451  	if err != nil {
   452  		fmt.Printf("discover failed: %v", err)
   453  
   454  		return
   455  	}
   456  	fmt.Printf("%s endpoints:\n", db.Name())
   457  	for i, e := range endpoints {
   458  		fmt.Printf("%d) %s\n", i, e.String())
   459  	}
   460  }
   461  
   462  //nolint:testableexamples
   463  func Example_enableGzipCompressionForAllRequests() {
   464  	ctx := context.TODO()
   465  	db, err := ydb.Open(
   466  		ctx,
   467  		"grpc://localhost:2135/local",
   468  		ydb.WithAnonymousCredentials(),
   469  		ydb.With(config.WithGrpcOptions(
   470  			grpc.WithDefaultCallOptions(
   471  				grpc.UseCompressor(gzip.Name),
   472  			),
   473  		)),
   474  	)
   475  	if err != nil {
   476  		fmt.Printf("Driver failed: %v", err)
   477  	}
   478  	defer db.Close(ctx) // cleanup resources
   479  	fmt.Printf("connected to %s, database '%s'", db.Endpoint(), db.Name())
   480  }
   481  
   482  //nolint:testableexamples
   483  func ExampleOpen() {
   484  	ctx := context.TODO()
   485  	db, err := ydb.Open(ctx, "grpc://localhost:2135/local")
   486  	if err != nil {
   487  		fmt.Printf("Driver failed: %v", err)
   488  	}
   489  	defer db.Close(ctx) // cleanup resources
   490  	fmt.Printf("connected to %s, database '%s'", db.Endpoint(), db.Name())
   491  }
   492  
   493  //nolint:testableexamples
   494  func ExampleOpen_advanced() {
   495  	ctx := context.TODO()
   496  	db, err := ydb.Open(
   497  		ctx,
   498  		"grpc://localhost:2135/local",
   499  		ydb.WithAnonymousCredentials(),
   500  		ydb.WithBalancer(
   501  			balancers.PreferLocationsWithFallback(
   502  				balancers.RandomChoice(), "a", "b",
   503  			),
   504  		),
   505  		ydb.WithSessionPoolSizeLimit(100),
   506  	)
   507  	if err != nil {
   508  		fmt.Printf("Driver failed: %v", err)
   509  	}
   510  	defer db.Close(ctx) // cleanup resources
   511  	fmt.Printf("connected to %s, database '%s'", db.Endpoint(), db.Name())
   512  }