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

     1  # Migration from `ydb-go-sdk/v2` to `ydb-go-sdk/v3`
     2  
     3  > Article contains some cases for migrate from `github.com/yandex-cloud/ydb-go-sdk/v2` to `github.com/ydb-platform/ydb-go-sdk/v3`
     4  
     5  ## Table of contents
     6  1. [Imports](#imports)
     7  2. [Connect to `YDB` by `endpoint` and `database`](#connect)
     8  3. [Connect to `YDB` using connection string](#connect-dsn)
     9  4. [Make table client and session pool](#table-client)
    10  5. [Execute query with table client and session pool](#execute-queries)
    11  6. [About truncated result](#truncated)
    12  7. [Scan query result into local variables](#scan-result)
    13  8. [Logging SDK's events](#logs)
    14  9. [Add metrics about SDK's events](#metrics)
    15  10. [Add `Jaeger` traces about SDK's events](#jaeger)
    16  
    17  ## Imports <a name="imports"></a>
    18  - in `v2`: 
    19    ```
    20    "github.com/yandex-cloud/ydb-go-sdk/v2"
    21    "github.com/yandex-cloud/ydb-go-sdk/v2/table"
    22    ```
    23  - in `v3`: 
    24    ```
    25    "github.com/ydb-platform/ydb-go-sdk/v3"
    26    "github.com/ydb-platform/ydb-go-sdk/v3/table"
    27    ```  
    28  
    29  ## Connect to `YDB` by `endpoint` and `database` <a name="connect"></a>
    30  - in `v2`: 
    31    ```go
    32    config := &ydb.DriverConfig{
    33      Database: cfg.Database,
    34    }
    35    driver, err := (&ydb.Dialer{
    36      DriverConfig: config,
    37    }).Dial(ctx, cfg.Addr)
    38    if err != nil {
    39      // error fallback
    40    }
    41    defer func() {
    42      _ = driver.Close()
    43    }()
    44    ```
    45  - in `v3`: 
    46    ```go
    47    import (
    48      "github.com/ydb-platform/ydb-go-sdk/v3/sugar"
    49    )
    50    ...
    51    db, err := ydb.Open(ctx,
    52      sugar.DSN(cfg.Endpoint, cfg.Database, cfg.Secure)
    53    )
    54    if err != nil {
    55      // error fallback
    56    }
    57    defer func() {
    58      _ = db.Close(ctx)
    59    }()
    60    ```  
    61  
    62  ## Connect to `YDB` using connection string <a name="connect-dsn"></a>
    63  - in `v2`: 
    64    ```go
    65    import (
    66      "github.com/yandex-cloud/ydb-go-sdk/v2/connect"
    67    )
    68    ...
    69    params, err := connect.ConnectionString("grpc://ydb-ru.yandex.net:2135/?database=/ru/home/my/db")
    70    if err != nil {
    71      // error fallback
    72    }
    73    ...
    74    config.Database = params.Database()
    75    ...
    76    driver, err := (&ydb.Dialer{
    77      DriverConfig: config,
    78    }).Dial(ctx, params.Endpoint())
    79    ```
    80  - in `v3`: 
    81    ```go
    82    db, err := ydb.Open(ctx,
    83      "grpc://ydb-ru.yandex.net:2135/ru/home/my/db",
    84    )
    85    if err != nil {
    86      // error fallback
    87    }
    88    defer func() {
    89      _ = db.Close(ctx)
    90    }()
    91    ```
    92  
    93  ## Make table client and session pool <a name="table-client"></a>
    94  - in `v2`: 
    95    ```go
    96    import (
    97      "github.com/yandex-cloud/ydb-go-sdk/v2/table"
    98    )
    99    ...
   100    tableClient := &table.Client{
   101      Driver: driver,
   102    }
   103    sp := &table.SessionPool{
   104      Builder: tableClient,
   105    }
   106    defer func() {
   107      _ = sp.Close(ctx)
   108    }()
   109    ```
   110  - in `v3`: nothing to do, table client with internal session pool always available with `db.Table()`
   111  
   112  ## Execute query with table client and session pool <a name="execute-queries"></a>
   113  - in `v2`: 
   114    ```go
   115    var res *table.Result
   116    err := table.Retry(ctx, sp,
   117      table.OperationFunc(
   118          func(ctx context.Context, s *table.Session) (err error) {
   119              _, res, err = s.Execute(ctx, readTx, "SELECT 1+1")
   120              return err
   121          },
   122      )
   123    )
   124    if err != nil {
   125      // error fallback
   126    }
   127    ```
   128  - in `v3`: 
   129    ```go
   130    import (
   131      "github.com/ydb-platform/ydb-go-sdk/v3/table/result"  
   132    )
   133    ...
   134    var res result.Result
   135    err := db.Table().Do(ctx,
   136      func(ctx context.Context, s table.Session) (err error) {
   137          _, res, err = s.Execute(ctx, readTx, "SELECT 1+1")
   138          return err
   139      },
   140      table.WithIdempotent(), // only idempotent queries
   141    )
   142    if err != nil {
   143      // error fallback
   144    }
   145    ```
   146  
   147  ## About truncated result <a name="truncated"></a>
   148  
   149  Call of `session.Execute` may return a result with a flag `Truncated` because `YDB` have a default limit of rows is a 1000.
   150  In this case query must be changed for supporting pagination. Truncated flag in result must be checks explicitly.
   151  - in `v2`:
   152    ```go
   153    var res *table.Result
   154    err := table.Retry(ctx, sp,
   155      table.OperationFunc(
   156          func(ctx context.Context, s *table.Session) (err error) {
   157              _, res, err = s.Execute(ctx, readTx, "SELECT 1+1")
   158              if err != nil {
   159                // error fallback
   160              }
   161              for res.NextStreamSet(ctx) {
   162                  for res.NextRow() {
   163                     // process column values
   164                  }
   165              }
   166              if err := res.Err(); err != nil {
   167                  // error fallback
   168              }
   169              if res.Trucated() {
   170                  // alarm to query developers
   171              }
   172              return nil
   173          },
   174      ),
   175    }
   176    if err != nil {
   177      // error fallback
   178    }
   179    ```
   180  - in `v3`:
   181    By default, truncated result wraps as non-retryable error for `session.Execute` and retryable error for `session.StreamExecuteScanQuery`
   182    ```go
   183    import (
   184      "github.com/ydb-platform/ydb-go-sdk/v3/table/result"  
   185    )
   186    ...
   187    var res result.Result
   188    err := db.Table().Do(ctx,
   189      func(ctx context.Context, s table.Session) (err error) {
   190          _, res, err = s.Execute(ctx, readTx, "SELECT 1+1")
   191          if err != nil {
   192              // error fallback
   193          }
   194          for res.NextStreamSet(ctx) {
   195              for res.NextRow() {
   196                 // process column values
   197              }
   198          }
   199          // no need to check truncated result explicitly 
   200          // if res.Truncated() {
   201          //   // alarm to query developers
   202          // }
   203          return res.Err()
   204      },
   205      table.WithIdempotent(), // only idempotent queries
   206    )
   207    if err != nil {
   208      // error fallback
   209    }
   210    ```
   211    But if default behaviour are not allowed, wrapping truncated result as error may be disabled with option `ydb.WithIgnoreTruncated` 
   212  
   213  
   214  ## Scan query result into local variables <a name="scan-result"></a>
   215  - in `v2`: 
   216    ```go
   217    var (
   218      id    uint64
   219      title string
   220      date  uint64
   221      description string
   222      duration uint64
   223    )
   224    for res.NextStreamSet(ctx) {
   225      for res.NextRow() {
   226          res.SeekItem("series_id")
   227          id = res.OUint64()
   228    
   229          res.SeekItem("title")
   230          title = res.OUTF8()
   231    
   232          res.SeekItem("release_date")
   233          date = res.OUint64()
   234    
   235          res.SeekItem("description")
   236          description = res.OUTF8()
   237    
   238          res.SeekItem("duration")
   239          duration = res.OUint64()
   240    
   241          log.Printf("#  %d %s %s %s %v",
   242              id, title, time.UnixMilli(date).Format("02/01/2006, 15:04:05"),
   243              description, time.Duration(duration) * time.Millisecond,
   244          )
   245      }
   246    }
   247    if err := res.Err(); err != nil {
   248      // error fallback
   249    }
   250    ```
   251  - in `v3`: 
   252    ```go
   253    import (
   254      "github.com/ydb-platform/ydb-go-sdk/v3/table/result/named"  
   255    )
   256    ...
   257    var (
   258      id    uint64
   259      title *string
   260      date  *time.Time
   261      description *string
   262      duration time.Duration
   263    )
   264    for res.NextResultSet(ctx) {
   265      for res.NextRow() {
   266          err := res.ScanNamed(
   267              named.Required("series_id", &id),
   268              named.Optional("title", &title),
   269              named.Optional("release_date", &date),
   270              named.Optional("description", &description),
   271              named.OptionalWithDefault("duration", &duration),
   272          )
   273          if err != nil {
   274              // error fallback
   275          }
   276          log.Printf("#  %d %s %s %s %v",
   277              id, title, date.Format("02/01/2006, 15:04:05"),
   278              description, duration,
   279          )
   280      }
   281    }
   282    if err := res.Err(); err != nil {
   283      // error fallback
   284    }
   285    ```  
   286  
   287  ## Logging SDK's events <a name="logs"></a>
   288  - in `v2`: 
   289    ```go
   290    config.Trace = ydb.DriverTrace{
   291      OnDial: func(info ydb.DialStartInfo) func(info ydb.DialDoneInfo) {
   292          address := info.Address
   293          fmt.Printf(`dial start {address:"%s"}`, address)
   294          start := time.Now()
   295          return func(info ydb.DialDoneInfo) {
   296              if info.Error == nil {
   297                  fmt.Printf(`dial done {latency:"%s",address:"%s"}`, time.Since(start), address)
   298              } else {
   299                  fmt.Printf(`dial failed {latency:"%s",address:"%s",error:"%s"}`, time.Since(start), address, info.Error)
   300              }
   301          }
   302      },
   303      // ... and more callbacks of ydb.DriverTrace need to define  
   304    }
   305    sp.Trace = table.Trace{
   306      // must callbacks of table.Trace  
   307    }
   308    ```
   309  - in `v3`:
   310    * `ydb-go-sdk/v3` contains internal logger, which may to enable with env `YDB_LOG_SEVERITY_LEVEL=info`
   311    * external `zap` logger:
   312      ```go
   313      import ydbZap "github.com/ydb-platform/ydb-go-sdk-zap"
   314      ...
   315      db, err := ydb.Open(ctx, connectionString, 
   316          ...
   317          ydbZap.WithTraces(log, trace.DetailsAll),
   318      )
   319      ```
   320    * external `zerolog` logger:
   321      ```go
   322      import ydbZerolog "github.com/ydb-platform/ydb-go-sdk-zerolog"
   323      ...
   324      db, err := ydb.Open(ctx, connectionString, 
   325         ...
   326         ydbZerolog.WithTraces(log, trace.DetailsAll),
   327      )
   328      ```
   329  
   330  ## Add metrics about SDK's events <a name="metrics"></a>
   331  - in `v2`: 
   332    ```go
   333    config.Trace = ydb.DriverTrace{
   334      // must define callbacks of ydb.DriverTrace  
   335    }
   336    sp.Trace = table.Trace{
   337      // must define callbacks of table.Trace  
   338    }
   339    ```
   340  - in `v3`: 
   341    * metrics into `Prometheus` system
   342      ```go
   343      import (
   344         ydbMetrics "github.com/ydb-platform/ydb-go-sdk-prometheus"
   345      )
   346      ...
   347  	registry := prometheus.NewRegistry()
   348      db, err := ydb.Open(ctx, connectionString,
   349        ...
   350        ydbMetrics.WithTraces(registry, ydbMetrics.WithDetails(trace.DetailsAll)),
   351      )
   352      ```
   353    * metrics to other monitoring systems may be add with common package `"github.com/ydb-platform/ydb-go-sdk-metrics"`
   354  
   355  ## Add `Jaeger` traces about SDK's events <a name="jaeger"></a>
   356  - in `v2`: 
   357    ```go
   358    config.Trace = ydb.DriverTrace{
   359      // must define callbacks of ydb.DriverTrace  
   360    }
   361    sp.Trace = table.Trace{
   362      // must define callbacks of table.Trace  
   363    }
   364    ```
   365  - in `v3`: 
   366    ```go
   367    import (
   368      ydbTracing "github.com/ydb-platform/ydb-go-sdk-opentracing"
   369    )
   370    ...
   371    db, err := ydb.Open(ctx, connectionString,
   372      ...
   373      ydbTracing.WithTraces(trace.DriverConnEvents | trace.DriverClusterEvents | trace.DriverRepeaterEvents | trace.DiscoveryEvents),
   374    )
   375    ```  
   376  
   377  See additional docs in [code recipes](https://ydb.tech/docs/reference/ydb-sdk/recipes/).