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

     1  package table_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path"
     7  	"time"
     8  
     9  	"google.golang.org/grpc"
    10  	"google.golang.org/grpc/encoding/gzip"
    11  
    12  	"github.com/ydb-platform/ydb-go-sdk/v3"
    13  	"github.com/ydb-platform/ydb-go-sdk/v3/retry"
    14  	"github.com/ydb-platform/ydb-go-sdk/v3/table"
    15  	"github.com/ydb-platform/ydb-go-sdk/v3/table/options"
    16  	"github.com/ydb-platform/ydb-go-sdk/v3/table/result/named"
    17  	"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
    18  )
    19  
    20  func Example_select() {
    21  	ctx := context.TODO()
    22  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
    23  	if err != nil {
    24  		fmt.Printf("failed connect: %v", err)
    25  
    26  		return
    27  	}
    28  	defer db.Close(ctx) // cleanup resources
    29  	var (
    30  		query = `SELECT 42 as id, "my string" as myStr`
    31  		id    int32  // required value
    32  		myStr string // optional value
    33  	)
    34  	err = db.Table().Do( // Do retry operation on errors with best effort
    35  		ctx, // context manage exiting from Do
    36  		func(ctx context.Context, s table.Session) (err error) { // retry operation
    37  			_, res, err := s.Execute(ctx, table.DefaultTxControl(), query, nil)
    38  			if err != nil {
    39  				return err // for auto-retry with driver
    40  			}
    41  			defer res.Close()                                // cleanup resources
    42  			if err = res.NextResultSetErr(ctx); err != nil { // check single result set and switch to it
    43  				return err // for auto-retry with driver
    44  			}
    45  			for res.NextRow() { // iterate over rows
    46  				err = res.ScanNamed(
    47  					named.Required("id", &id),
    48  					named.OptionalWithDefault("myStr", &myStr),
    49  				)
    50  				if err != nil {
    51  					return err // generally scan error not retryable, return it for driver check error
    52  				}
    53  				fmt.Printf("id=%v, myStr='%s'\n", id, myStr)
    54  			}
    55  
    56  			return res.Err() // return finally result error for auto-retry with driver
    57  		},
    58  		table.WithIdempotent(),
    59  	)
    60  	if err != nil {
    61  		fmt.Printf("unexpected error: %v", err)
    62  	}
    63  }
    64  
    65  func Example_explainQuery() {
    66  	ctx := context.TODO()
    67  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
    68  	if err != nil {
    69  		panic(err)
    70  	}
    71  	defer db.Close(ctx) // cleanup resources
    72  	var (
    73  		plan string
    74  		ast  string
    75  	)
    76  	err = db.Table().Do( // Do retry operation on errors with best effort
    77  		ctx, // context manage exiting from Do
    78  		func(ctx context.Context, s table.Session) (err error) { // retry operation
    79  			explanation, err := s.Explain(ctx, `
    80  				DECLARE $id AS Optional<Uint64>;
    81  				DECLARE $myStr AS Optional<Text>;
    82  				SELECT $id AS id, $myStr AS myStr;
    83  			`)
    84  			if err != nil {
    85  				return err // for auto-retry with driver
    86  			}
    87  
    88  			plan, ast = explanation.Plan, explanation.AST
    89  
    90  			return nil
    91  		},
    92  		table.WithIdempotent(),
    93  	)
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  
    98  	fmt.Printf("Plan: %s\n", plan)
    99  	fmt.Printf("AST: %s\n", ast)
   100  }
   101  
   102  func Example_createTable() {
   103  	ctx := context.TODO()
   104  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   105  	if err != nil {
   106  		fmt.Printf("failed connect: %v", err)
   107  
   108  		return
   109  	}
   110  	defer db.Close(ctx) // cleanup resources
   111  	err = db.Table().Do(ctx,
   112  		func(ctx context.Context, s table.Session) (err error) {
   113  			return s.CreateTable(ctx, path.Join(db.Name(), "series"),
   114  				options.WithColumn("series_id", types.Optional(types.TypeUint64)),
   115  				options.WithColumn("title", types.Optional(types.TypeText)),
   116  				options.WithColumn("series_info", types.Optional(types.TypeText)),
   117  				options.WithColumn("release_date", types.Optional(types.TypeDate)),
   118  				options.WithColumn("expire_at", types.Optional(types.TypeDate)),
   119  				options.WithColumn("comment", types.Optional(types.TypeText)),
   120  				options.WithPrimaryKeyColumn("series_id"),
   121  				options.WithTimeToLiveSettings(
   122  					options.NewTTLSettings().ColumnDateType("expire_at").ExpireAfter(time.Hour),
   123  				),
   124  				options.WithIndex("idx_series_title",
   125  					options.WithIndexColumns("title"),
   126  					options.WithIndexType(options.GlobalAsyncIndex()),
   127  				),
   128  			)
   129  		},
   130  		table.WithIdempotent(),
   131  	)
   132  	if err != nil {
   133  		fmt.Printf("unexpected error: %v", err)
   134  	}
   135  }
   136  
   137  func Example_bulkUpsert() {
   138  	ctx := context.TODO()
   139  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   140  	if err != nil {
   141  		fmt.Printf("failed connect: %v", err)
   142  
   143  		return
   144  	}
   145  	defer db.Close(ctx) // cleanup resources
   146  	type logMessage struct {
   147  		App       string
   148  		Host      string
   149  		Timestamp time.Time
   150  		HTTPCode  uint32
   151  		Message   string
   152  	}
   153  	// prepare native go data
   154  	const batchSize = 10000
   155  	logs := make([]logMessage, 0, batchSize)
   156  	for i := 0; i < batchSize; i++ {
   157  		logs = append(logs, logMessage{
   158  			App:       fmt.Sprintf("App_%d", i/256),
   159  			Host:      fmt.Sprintf("192.168.0.%d", i%256),
   160  			Timestamp: time.Now().Add(time.Millisecond * time.Duration(i%1000)),
   161  			HTTPCode:  200,
   162  			Message:   "GET / HTTP/1.1",
   163  		})
   164  	}
   165  	// execute bulk upsert with native ydb data
   166  	err = db.Table().Do( // Do retry operation on errors with best effort
   167  		ctx, // context manage exiting from Do
   168  		func(ctx context.Context, s table.Session) (err error) { // retry operation
   169  			rows := make([]types.Value, 0, len(logs))
   170  			for _, msg := range logs {
   171  				rows = append(rows, types.StructValue(
   172  					types.StructFieldValue("App", types.TextValue(msg.App)),
   173  					types.StructFieldValue("Host", types.TextValue(msg.Host)),
   174  					types.StructFieldValue("Timestamp", types.TimestampValueFromTime(msg.Timestamp)),
   175  					types.StructFieldValue("HTTPCode", types.Uint32Value(msg.HTTPCode)),
   176  					types.StructFieldValue("Message", types.TextValue(msg.Message)),
   177  				))
   178  			}
   179  
   180  			return s.BulkUpsert(ctx, "/local/bulk_upsert_example", types.ListValue(rows...))
   181  		},
   182  		table.WithIdempotent(),
   183  	)
   184  	if err != nil {
   185  		fmt.Printf("unexpected error: %v", err)
   186  	}
   187  }
   188  
   189  func Example_alterTable() {
   190  	ctx := context.TODO()
   191  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   192  	if err != nil {
   193  		fmt.Printf("failed connect: %v", err)
   194  
   195  		return
   196  	}
   197  	defer db.Close(ctx) // cleanup resources
   198  	err = db.Table().Do(ctx,
   199  		func(ctx context.Context, s table.Session) (err error) {
   200  			return s.AlterTable(ctx, path.Join(db.Name(), "series"),
   201  				options.WithAddColumn("series_id", types.Optional(types.TypeUint64)),
   202  				options.WithAddColumn("title", types.Optional(types.TypeText)),
   203  				options.WithSetTimeToLiveSettings(
   204  					options.NewTTLSettings().ColumnDateType("expire_at").ExpireAfter(time.Hour),
   205  				),
   206  				options.WithDropTimeToLive(),
   207  				options.WithAddIndex("idx_series_series_id",
   208  					options.WithIndexColumns("series_id"),
   209  					options.WithDataColumns("title"),
   210  					options.WithIndexType(options.GlobalIndex()),
   211  				),
   212  				options.WithDropIndex("idx_series_title"),
   213  				options.WithAlterAttribute("hello", "world"),
   214  				options.WithAddAttribute("foo", "bar"),
   215  				options.WithDropAttribute("baz"),
   216  			)
   217  		},
   218  		table.WithIdempotent(),
   219  	)
   220  	if err != nil {
   221  		fmt.Printf("unexpected error: %v", err)
   222  	}
   223  }
   224  
   225  func Example_lazyTransaction() {
   226  	ctx := context.TODO()
   227  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   228  	if err != nil {
   229  		fmt.Printf("failed connect: %v", err)
   230  
   231  		return
   232  	}
   233  	defer db.Close(ctx)
   234  	err = db.Table().Do(ctx,
   235  		func(ctx context.Context, session table.Session) (err error) {
   236  			// execute query with opening lazy transaction
   237  			tx, result, err := session.Execute(ctx,
   238  				table.SerializableReadWriteTxControl(),
   239  				"DECLARE $id AS Uint64; "+
   240  					"SELECT `title`, `description` FROM `path/to/mytable` WHERE id = $id",
   241  				table.NewQueryParameters(
   242  					table.ValueParam("$id", types.Uint64Value(1)),
   243  				),
   244  			)
   245  			if err != nil {
   246  				return err
   247  			}
   248  			defer func() {
   249  				_ = tx.Rollback(ctx)
   250  				_ = result.Close()
   251  			}()
   252  			if !result.NextResultSet(ctx) {
   253  				return retry.RetryableError(fmt.Errorf("no result sets"))
   254  			}
   255  			if !result.NextRow() {
   256  				return retry.RetryableError(fmt.Errorf("no rows"))
   257  			}
   258  			var (
   259  				id          uint64
   260  				title       string
   261  				description string
   262  			)
   263  			if err = result.ScanNamed(
   264  				named.OptionalWithDefault("id", &id),
   265  				named.OptionalWithDefault("title", &title),
   266  				named.OptionalWithDefault("description", &description),
   267  			); err != nil {
   268  				return err
   269  			}
   270  			fmt.Println(id, title, description)
   271  			// execute query with commit transaction
   272  			_, err = tx.Execute(ctx,
   273  				"DECLARE $id AS Uint64; "+
   274  					"DECLARE $description AS Text; "+
   275  					"UPSERT INTO `path/to/mytable` "+
   276  					"(id, description) "+
   277  					"VALUES ($id, $description);",
   278  				table.NewQueryParameters(
   279  					table.ValueParam("$id", types.Uint64Value(1)),
   280  					table.ValueParam("$description", types.TextValue("changed description")),
   281  				),
   282  				options.WithCommit(),
   283  			)
   284  			if err != nil {
   285  				return err
   286  			}
   287  
   288  			return result.Err()
   289  		},
   290  		table.WithIdempotent(),
   291  	)
   292  	if err != nil {
   293  		fmt.Printf("unexpected error: %v", err)
   294  	}
   295  }
   296  
   297  func Example_bulkUpsertWithCompression() {
   298  	ctx := context.TODO()
   299  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   300  	if err != nil {
   301  		fmt.Printf("failed connect: %v", err)
   302  
   303  		return
   304  	}
   305  	defer db.Close(ctx) // cleanup resources
   306  	type logMessage struct {
   307  		App       string
   308  		Host      string
   309  		Timestamp time.Time
   310  		HTTPCode  uint32
   311  		Message   string
   312  	}
   313  	// prepare native go data
   314  	const batchSize = 10000
   315  	logs := make([]logMessage, 0, batchSize)
   316  	for i := 0; i < batchSize; i++ {
   317  		logs = append(logs, logMessage{
   318  			App:       fmt.Sprintf("App_%d", i/256),
   319  			Host:      fmt.Sprintf("192.168.0.%d", i%256),
   320  			Timestamp: time.Now().Add(time.Millisecond * time.Duration(i%1000)),
   321  			HTTPCode:  200,
   322  			Message:   "GET /images/logo.png HTTP/1.1",
   323  		})
   324  	}
   325  	// execute bulk upsert with native ydb data
   326  	err = db.Table().Do( // Do retry operation on errors with best effort
   327  		ctx, // context manage exiting from Do
   328  		func(ctx context.Context, s table.Session) (err error) { // retry operation
   329  			rows := make([]types.Value, 0, len(logs))
   330  			for _, msg := range logs {
   331  				rows = append(rows, types.StructValue(
   332  					types.StructFieldValue("App", types.TextValue(msg.App)),
   333  					types.StructFieldValue("Host", types.TextValue(msg.Host)),
   334  					types.StructFieldValue("Timestamp", types.TimestampValueFromTime(msg.Timestamp)),
   335  					types.StructFieldValue("HTTPCode", types.Uint32Value(msg.HTTPCode)),
   336  					types.StructFieldValue("Message", types.TextValue(msg.Message)),
   337  				))
   338  			}
   339  
   340  			return s.BulkUpsert(ctx, "/local/bulk_upsert_example", types.ListValue(rows...),
   341  				options.WithCallOptions(grpc.UseCompressor(gzip.Name)),
   342  			)
   343  		},
   344  		table.WithIdempotent(),
   345  	)
   346  	if err != nil {
   347  		fmt.Printf("unexpected error: %v", err)
   348  	}
   349  }
   350  
   351  func Example_dataQueryWithCompression() {
   352  	ctx := context.TODO()
   353  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   354  	if err != nil {
   355  		fmt.Printf("failed connect: %v", err)
   356  
   357  		return
   358  	}
   359  	defer db.Close(ctx) // cleanup resources
   360  	var (
   361  		query = `SELECT 42 as id, "my string" as myStr`
   362  		id    int32  // required value
   363  		myStr string // optional value
   364  	)
   365  	err = db.Table().Do( // Do retry operation on errors with best effort
   366  		ctx, // context manage exiting from Do
   367  		func(ctx context.Context, s table.Session) (err error) { // retry operation
   368  			_, res, err := s.Execute(ctx, table.DefaultTxControl(), query, nil,
   369  				options.WithCallOptions(
   370  					grpc.UseCompressor(gzip.Name),
   371  				),
   372  			)
   373  			if err != nil {
   374  				return err // for auto-retry with driver
   375  			}
   376  			defer res.Close()                                // cleanup resources
   377  			if err = res.NextResultSetErr(ctx); err != nil { // check single result set and switch to it
   378  				return err // for auto-retry with driver
   379  			}
   380  			for res.NextRow() { // iterate over rows
   381  				err = res.ScanNamed(
   382  					named.Required("id", &id),
   383  					named.OptionalWithDefault("myStr", &myStr),
   384  				)
   385  				if err != nil {
   386  					return err // generally scan error not retryable, return it for driver check error
   387  				}
   388  				fmt.Printf("id=%v, myStr='%s'\n", id, myStr)
   389  			}
   390  
   391  			return res.Err() // return finally result error for auto-retry with driver
   392  		},
   393  		table.WithIdempotent(),
   394  	)
   395  	if err != nil {
   396  		fmt.Printf("unexpected error: %v", err)
   397  	}
   398  }
   399  
   400  func Example_scanQueryWithCompression() {
   401  	ctx := context.TODO()
   402  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   403  	if err != nil {
   404  		fmt.Printf("failed connect: %v", err)
   405  
   406  		return
   407  	}
   408  	defer db.Close(ctx) // cleanup resources
   409  	var (
   410  		query = `SELECT 42 as id, "my string" as myStr`
   411  		id    int32  // required value
   412  		myStr string // optional value
   413  	)
   414  	err = db.Table().Do( // Do retry operation on errors with best effort
   415  		ctx, // context manage exiting from Do
   416  		func(ctx context.Context, s table.Session) (err error) { // retry operation
   417  			res, err := s.StreamExecuteScanQuery(ctx, query, nil,
   418  				options.WithCallOptions(
   419  					grpc.UseCompressor(gzip.Name),
   420  				),
   421  			)
   422  			if err != nil {
   423  				return err // for auto-retry with driver
   424  			}
   425  			defer res.Close()                                // cleanup resources
   426  			if err = res.NextResultSetErr(ctx); err != nil { // check single result set and switch to it
   427  				return err // for auto-retry with driver
   428  			}
   429  			for res.NextRow() { // iterate over rows
   430  				err = res.ScanNamed(
   431  					named.Required("id", &id),
   432  					named.OptionalWithDefault("myStr", &myStr),
   433  				)
   434  				if err != nil {
   435  					return err // generally scan error not retryable, return it for driver check error
   436  				}
   437  				fmt.Printf("id=%v, myStr='%s'\n", id, myStr)
   438  			}
   439  
   440  			return res.Err() // return finally result error for auto-retry with driver
   441  		},
   442  		table.WithIdempotent(),
   443  	)
   444  	if err != nil {
   445  		fmt.Printf("unexpected error: %v", err)
   446  	}
   447  }
   448  
   449  func Example_copyTables() {
   450  	ctx := context.TODO()
   451  	db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
   452  	if err != nil {
   453  		fmt.Printf("failed connect: %v", err)
   454  
   455  		return
   456  	}
   457  	defer db.Close(ctx) // cleanup resources
   458  	err = db.Table().Do(ctx,
   459  		func(ctx context.Context, s table.Session) (err error) {
   460  			return s.CopyTables(ctx,
   461  				options.CopyTablesItem(
   462  					path.Join(db.Name(), "from", "series"),
   463  					path.Join(db.Name(), "to", "series"),
   464  					true,
   465  				),
   466  			)
   467  		},
   468  		table.WithIdempotent(),
   469  	)
   470  	if err != nil {
   471  		fmt.Printf("unexpected error: %v", err)
   472  	}
   473  }