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

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