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 }