diff --git a/examples/ddl/ddl.go b/examples/ddl/ddl.go index d602e919b..4aae7c6b3 100644 --- a/examples/ddl/ddl.go +++ b/examples/ddl/ddl.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/ydb-platform/ydb-go-sdk/v3/table" + "github.com/ydb-platform/ydb-go-sdk/v3/query" ) //nolint:lll @@ -67,17 +67,6 @@ ALTER TABLE small_table3 SET (TTL = Interval("PT3H") ON d); ` ) -func executeQuery(ctx context.Context, c table.Client, prefix, sql string) (err error) { - err = c.Do(ctx, - func(ctx context.Context, s table.Session) error { - err = s.ExecuteSchemeQuery(ctx, fmt.Sprintf(sql, prefix)) - - return err - }, - ) - if err != nil { - return err - } - - return nil +func executeQuery(ctx context.Context, c query.Client, prefix, sql string) (err error) { + return c.Exec(ctx, fmt.Sprintf(sql, prefix), query.WithTxControl(query.ImplicitTxControl())) } diff --git a/examples/ddl/main.go b/examples/ddl/main.go index bf8d491aa..650a6e63e 100644 --- a/examples/ddl/main.go +++ b/examples/ddl/main.go @@ -65,43 +65,43 @@ func main() { prefix = path.Join(db.Name(), prefix) // simple creation with composite primary key - err = executeQuery(ctx, db.Table(), prefix, simpleCreateQuery) + err = executeQuery(ctx, db.Query(), prefix, simpleCreateQuery) if err != nil { panic(err) } // creation with column family - err = executeQuery(ctx, db.Table(), prefix, familyCreateQuery) + err = executeQuery(ctx, db.Query(), prefix, familyCreateQuery) if err != nil { panic(err) } // creation with table settings - err = executeQuery(ctx, db.Table(), prefix, settingsCreateQuery) + err = executeQuery(ctx, db.Query(), prefix, settingsCreateQuery) if err != nil { panic(err) } // add column and drop column. - err = executeQuery(ctx, db.Table(), prefix, alterQuery) + err = executeQuery(ctx, db.Query(), prefix, alterQuery) if err != nil { panic(err) } // change AUTO_PARTITIONING_BY_SIZE setting. - err = executeQuery(ctx, db.Table(), prefix, alterSettingsQuery) + err = executeQuery(ctx, db.Query(), prefix, alterSettingsQuery) if err != nil { panic(err) } // add TTL. Clear the old data after the three-hour interval has expired. - err = executeQuery(ctx, db.Table(), prefix, alterTTLQuery) + err = executeQuery(ctx, db.Query(), prefix, alterTTLQuery) if err != nil { panic(err) } // drop tables small_table,small_table2,small_table3. - err = executeQuery(ctx, db.Table(), prefix, dropQuery) + err = executeQuery(ctx, db.Query(), prefix, dropQuery) if err != nil { panic(err) } diff --git a/examples/decimal/main.go b/examples/decimal/main.go index a71ab66ea..3f04be3f1 100644 --- a/examples/decimal/main.go +++ b/examples/decimal/main.go @@ -10,8 +10,7 @@ import ( environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" ydb "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/table" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) @@ -69,28 +68,21 @@ func main() { prefix = path.Join(db.Name(), prefix) tablePath := path.Join(prefix, "decimals") - err = db.Table().Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - return s.CreateTable(ctx, tablePath, - options.WithColumn("id", types.Optional(types.TypeUint32)), - options.WithColumn("value", types.Optional(types.DefaultDecimal)), - options.WithPrimaryKeyColumn("id"), - ) - }, + err = db.Query().Exec(ctx, + fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS `+"`%s`"+` ( + id Uint32, + value Decimal(22,9), + PRIMARY KEY (id) + )`, tablePath), + query.WithTxControl(query.ImplicitTxControl()), ) if err != nil { panic(err) } - err = db.Table().Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - txc := table.TxControl( - table.BeginTx( - table.WithSerializableReadWrite(), - ), - table.CommitTx(), - ) - + err = db.Query().DoTx(ctx, + func(ctx context.Context, tx query.TxActor) (err error) { x := big.NewInt(42 * 1000000000) x.Mul(x, big.NewInt(2)) parsedDecimal, err := types.DecimalValueFromString("42.00", 22, 9) @@ -98,48 +90,53 @@ func main() { panic(err) } - _, _, err = s.Execute(ctx, txc, render(writeQuery, templateConfig{ + err = tx.Exec(ctx, render(writeQuery, templateConfig{ TablePathPrefix: prefix, - }), table.NewQueryParameters( - table.ValueParam("$decimals", - types.ListValue( - types.StructValue( - types.StructFieldValue("id", types.Uint32Value(42)), - types.StructFieldValue("value", types.DecimalValueFromBigInt(x, 22, 9)), - ), - types.StructValue( - types.StructFieldValue("id", types.Uint32Value(43)), - types.StructFieldValue("value", parsedDecimal), - ), - ), + }), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$decimals").Any( + types.ListValue( + types.StructValue( + types.StructFieldValue("id", types.Uint32Value(42)), + types.StructFieldValue("value", types.DecimalValueFromBigInt(x, 22, 9)), + ), + types.StructValue( + types.StructFieldValue("id", types.Uint32Value(43)), + types.StructFieldValue("value", parsedDecimal), + ), + ), + ). + Build(), ), - )) + ) if err != nil { return err } - _, res, err := s.Execute(ctx, txc, render(readQuery, templateConfig{ + rs, err := tx.QueryResultSet(ctx, render(readQuery, templateConfig{ TablePathPrefix: prefix, - }), nil) + })) if err != nil { return err } defer func() { - _ = res.Close() + _ = rs.Close(ctx) }() - var p *types.Decimal - for res.NextResultSet(ctx) { - for res.NextRow() { - err = res.Scan(&p) - if err != nil { - return err - } - fmt.Println(p.String()) + for row, err := range rs.Rows(ctx) { + if err != nil { + return err + } + var p *types.Decimal + err = row.Scan(&p) + if err != nil { + return err } + fmt.Println(p.String()) } - return res.Err() + return nil }, ) if err != nil { diff --git a/examples/opensource_night2024/main.go b/examples/opensource_night2024/main.go index c83a3ade2..5a27a8ae9 100644 --- a/examples/opensource_night2024/main.go +++ b/examples/opensource_night2024/main.go @@ -11,12 +11,11 @@ import ( "fmt" "io" "os" - "path" "strconv" "time" - "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/table" + ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topictypes" @@ -288,8 +287,41 @@ func fillTableWeather(ctx context.Context, db *ydb.Driver) error { values = append(values, value) } - return db.Table().BulkUpsert(ctx, path.Join(db.Name(), "weather"), - table.BulkUpsertDataRows(types.ListValue(values...)), + return db.Query().Exec(ctx, + ` + DECLARE $rows AS List>; + UPSERT INTO weather SELECT * FROM AS_TABLE($rows); + `, + query.WithParameters( + ydb.ParamsBuilder().Param("$rows").Any(types.ListValue(values...)).Build(), + ), ) } diff --git a/examples/pagination/cities.go b/examples/pagination/cities.go index 620e9ee72..587f17884 100644 --- a/examples/pagination/cities.go +++ b/examples/pagination/cities.go @@ -4,15 +4,14 @@ import ( "context" "fmt" - "github.com/ydb-platform/ydb-go-sdk/v3/table" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" - "github.com/ydb-platform/ydb-go-sdk/v3/table/result/named" + ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) func selectPaging( ctx context.Context, - c table.Client, + c query.Client, prefix string, limit int, lastNum *uint, @@ -21,7 +20,7 @@ func selectPaging( empty bool, err error, ) { - query := fmt.Sprintf(` + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $limit AS Uint64; @@ -50,50 +49,62 @@ func selectPaging( ORDER BY city, number LIMIT $limit; `, prefix) - readTx := table.TxControl(table.BeginTx(table.WithOnlineReadOnly()), table.CommitTx()) - err = c.Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, res, err := s.Execute(ctx, readTx, query, - table.NewQueryParameters( - table.ValueParam("$limit", types.Uint64Value(uint64(limit))), - table.ValueParam("$lastCity", types.TextValue(*lastCity)), - table.ValueParam("$lastNumber", types.Uint32Value(uint32(*lastNum))), + func(ctx context.Context, s query.Session) (err error) { + rs, err := s.QueryResultSet(ctx, sql, + query.WithTxControl(query.OnlineReadOnlyTxControl()), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$limit").Any(types.Uint64Value(uint64(limit))). + Param("$lastCity").Any(types.TextValue(*lastCity)). + Param("$lastNumber").Any(types.Uint32Value(uint32(*lastNum))). + Build(), ), ) if err != nil { return err } defer func() { - _ = res.Close() + _ = rs.Close(ctx) }() - if !res.NextResultSet(ctx) || !res.HasNextRow() { - empty = true - return res.Err() - } - var addr string - for res.NextRow() { - err = res.ScanNamed( - named.Optional("city", &lastCity), - named.Optional("number", &lastNum), - named.OptionalWithDefault("address", &addr), + hasRows := false + for row, err := range rs.Rows(ctx) { + if err != nil { + return err + } + hasRows = true + var ( + city *string + number *uint32 + address string + ) + err = row.ScanNamed( + query.Named("city", &city), + query.Named("number", &number), + query.Named("address", &address), ) if err != nil { return err } - fmt.Printf("\t%v, School #%v, Address: %v\n", *lastCity, *lastNum, addr) + *lastCity = *city + *lastNum = uint(*number) + fmt.Printf("\t%v, School #%v, Address: %v\n", *lastCity, *lastNum, address) + } + + if !hasRows { + empty = true } - return res.Err() + return nil }, ) return empty, err } -func fillTableWithData(ctx context.Context, c table.Client, prefix string) (err error) { - query := fmt.Sprintf(` +func fillTableWithData(ctx context.Context, c query.Client, prefix string) (err error) { + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $schoolsData AS List Page %v:\n", i+1) - empty, err = selectPaging(ctx, db.Table(), prefix, limit, &lastNum, &lastCity) + empty, err = selectPaging(ctx, db.Query(), prefix, limit, &lastNum, &lastCity) if err != nil { panic(fmt.Errorf("get page %v error: %w", i, err)) } diff --git a/examples/serverless/healthcheck/service.go b/examples/serverless/healthcheck/service.go index d1a39e744..a10841d73 100644 --- a/examples/serverless/healthcheck/service.go +++ b/examples/serverless/healthcheck/service.go @@ -14,9 +14,9 @@ import ( "time" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" - "github.com/ydb-platform/ydb-go-sdk/v3" + ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" - "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) @@ -72,24 +72,22 @@ func (s *service) createTableIfNotExists(ctx context.Context) error { if exists { return nil } - query := fmt.Sprintf(` - PRAGMA TablePathPrefix("%s"); - - CREATE TABLE healthchecks ( - url Text, - code Int32, - ts DateTime, - error Text, - PRIMARY KEY (url, ts) - ) WITH ( - AUTO_PARTITIONING_BY_LOAD = ENABLED - );`, path.Join(s.db.Name(), prefix), - ) - return s.db.Table().Do(ctx, - func(ctx context.Context, s table.Session) error { - return s.ExecuteSchemeQuery(ctx, query) - }, + return s.db.Query().Exec(ctx, + fmt.Sprintf(` + PRAGMA TablePathPrefix("%s"); + + CREATE TABLE IF NOT EXISTS healthchecks ( + url Text, + code Int32, + ts DateTime, + error Text, + PRIMARY KEY (url, ts) + ) WITH ( + AUTO_PARTITIONING_BY_LOAD = ENABLED + );`, path.Join(s.db.Name(), prefix), + ), + query.WithTxControl(query.ImplicitTxControl()), ) } @@ -169,31 +167,27 @@ func (s *service) upsertRows(ctx context.Context, rows []row) (err error) { }(rows[i].err))), ) } - err = s.db.Table().Do(ctx, - func(ctx context.Context, session table.Session) (err error) { - _, _, err = session.Execute(ctx, - table.SerializableReadWriteTxControl(table.CommitTx()), - fmt.Sprintf(` - PRAGMA TablePathPrefix("%s"); - - DECLARE $rows AS List>; - - UPSERT INTO healthchecks ( url, code, ts, error ) - SELECT url, code, ts, error FROM AS_TABLE($rows);`, - path.Join(s.db.Name(), prefix), - ), - table.NewQueryParameters( - table.ValueParam("$rows", types.ListValue(values...)), - ), - ) - - return err - }, + err = s.db.Query().Exec(ctx, + fmt.Sprintf(` + PRAGMA TablePathPrefix("%s"); + + DECLARE $rows AS List>; + + UPSERT INTO healthchecks ( url, code, ts, error ) + SELECT url, code, ts, error FROM AS_TABLE($rows);`, + path.Join(s.db.Name(), prefix), + ), + query.WithTxControl(query.SerializableReadWriteTxControl(query.CommitTx())), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$rows").Any(types.ListValue(values...)). + Build(), + ), ) if err != nil { return fmt.Errorf("error on upsert rows: %w", err) diff --git a/examples/serverless/url_shortener/service.go b/examples/serverless/url_shortener/service.go index aabd504c3..e21d70e48 100644 --- a/examples/serverless/url_shortener/service.go +++ b/examples/serverless/url_shortener/service.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "context" "embed" "encoding/hex" @@ -23,10 +22,7 @@ import ( environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" ydbMetrics "github.com/ydb-platform/ydb-go-sdk-prometheus/v2" ydb "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/table" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" - "github.com/ydb-platform/ydb-go-sdk/v3/table/result" - "github.com/ydb-platform/ydb-go-sdk/v3/table/result/named" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -56,19 +52,6 @@ func isLongCorrect(link string) bool { return long.FindStringIndex(link) != nil } -func render(t *template.Template, data any) string { - var buf bytes.Buffer - if err := t.Execute(&buf, data); err != nil { - panic(err) - } - - return buf.String() -} - -type templateConfig struct { - TablePathPrefix string -} - type service struct { db *ydb.Driver registry *prometheus.Registry @@ -181,28 +164,14 @@ func (s *service) Close(ctx context.Context) { } func (s *service) createTable(ctx context.Context) (err error) { - query := render( - template.Must(template.New("").Parse(` - PRAGMA TablePathPrefix("{{ .TablePathPrefix }}"); - - CREATE TABLE urls ( + return s.db.Query().Exec(ctx, + fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS `+"`%s`"+` ( src Text, hash Text, - PRIMARY KEY (hash) - ); - `)), - templateConfig{ - TablePathPrefix: path.Join(s.db.Name(), prefix), - }, - ) - - return s.db.Table().Do(ctx, - func(ctx context.Context, s table.Session) error { - err := s.ExecuteSchemeQuery(ctx, query) - - return err - }, + )`, path.Join(s.db.Name(), prefix, "urls")), + query.WithTxControl(query.ImplicitTxControl()), ) } @@ -211,9 +180,9 @@ func (s *service) insertShort(ctx context.Context, url string) (h string, err er if err != nil { return "", err } - query := render( - template.Must(template.New("").Parse(` - PRAGMA TablePathPrefix("{{ .TablePathPrefix }}"); + err = s.db.Query().Exec(ctx, + fmt.Sprintf(` + PRAGMA TablePathPrefix("%s"); DECLARE $hash as Text; DECLARE $src as Text; @@ -222,38 +191,23 @@ func (s *service) insertShort(ctx context.Context, url string) (h string, err er urls (hash, src) VALUES ($hash, $src); - `)), - templateConfig{ - TablePathPrefix: path.Join(s.db.Name(), prefix), - }, - ) - writeTx := table.TxControl( - table.BeginTx( - table.WithSerializableReadWrite(), + `, path.Join(s.db.Name(), prefix)), + query.WithTxControl(query.SerializableReadWriteTxControl(query.CommitTx())), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$hash").Any(types.TextValue(h)). + Param("$src").Any(types.TextValue(url)). + Build(), ), - table.CommitTx(), - ) - err = s.db.Table().Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, _, err = s.Execute(ctx, writeTx, query, - table.NewQueryParameters( - table.ValueParam("$hash", types.TextValue(h)), - table.ValueParam("$src", types.TextValue(url)), - ), - options.WithCollectStatsModeBasic(), - ) - - return - }, ) return h, err } func (s *service) selectLong(ctx context.Context, hash string) (url string, err error) { - query := render( - template.Must(template.New("").Parse(` - PRAGMA TablePathPrefix("{{ .TablePathPrefix }}"); + row, err := s.db.Query().QueryRow(ctx, + fmt.Sprintf(` + PRAGMA TablePathPrefix("%s"); DECLARE $hash as Text; @@ -263,48 +217,21 @@ func (s *service) selectLong(ctx context.Context, hash string) (url string, err urls WHERE hash = $hash; - `)), - templateConfig{ - TablePathPrefix: path.Join(s.db.Name(), prefix), - }, - ) - readTx := table.TxControl( - table.BeginTx( - table.WithSnapshotReadOnly(), + `, path.Join(s.db.Name(), prefix)), + query.WithTxControl(query.SnapshotReadOnlyTxControl()), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$hash").Any(types.TextValue(hash)). + Build(), ), - table.CommitTx(), - ) - var res result.Result - err = s.db.Table().Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, res, err = s.Execute(ctx, readTx, query, - table.NewQueryParameters( - table.ValueParam("$hash", types.TextValue(hash)), - ), - options.WithCollectStatsModeBasic(), - ) - - return err - }, ) if err != nil { return "", err } - defer func() { - _ = res.Close() - }() - var src string - for res.NextResultSet(ctx) { - for res.NextRow() { - err = res.ScanNamed( - named.OptionalWithDefault("src", &src), - ) - - return src, err - } - } - return "", fmt.Errorf("hash '%s' is not found", hash) + err = row.ScanNamed(query.Named("src", &url)) + + return url, err } func writeResponse(w http.ResponseWriter, statusCode int, body string) { diff --git a/examples/topic/cdc-cache-bus-freeseats/database.go b/examples/topic/cdc-cache-bus-freeseats/database.go index ea2f9b1ef..a893e8b87 100644 --- a/examples/topic/cdc-cache-bus-freeseats/database.go +++ b/examples/topic/cdc-cache-bus-freeseats/database.go @@ -5,11 +5,10 @@ import ( "fmt" "log" "os" - "path" "time" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/table" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topictypes" ) @@ -27,14 +26,10 @@ func createTableAndCDC(ctx context.Context, db *ydb.Driver, consumersCount int) } func createTables(ctx context.Context, db *ydb.Driver) error { - err := db.Table().Do(ctx, func(ctx context.Context, s table.Session) error { - err := s.DropTable(ctx, path.Join(db.Name(), "bus")) - if ydb.IsOperationErrorSchemeError(err) { - err = nil - } - - return err - }) + err := db.Query().Exec(ctx, + "DROP TABLE IF EXISTS `bus`", + query.WithTxControl(query.ImplicitTxControl()), + ) if err != nil { return fmt.Errorf("failed to drop table: %w", err) } diff --git a/examples/topic/cdc-cache-bus-freeseats/webserver.go b/examples/topic/cdc-cache-bus-freeseats/webserver.go index 6fe86abd5..4544cfa2b 100644 --- a/examples/topic/cdc-cache-bus-freeseats/webserver.go +++ b/examples/topic/cdc-cache-bus-freeseats/webserver.go @@ -10,8 +10,8 @@ import ( "sync/atomic" "time" - "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/table" + ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) @@ -104,7 +104,7 @@ func (s *server) getFreeSeats(ctx context.Context, id string) (int64, error) { func (s *server) getContentFromDB(ctx context.Context, id string) (int64, error) { s.dbCounter.Add(1) var freeSeats int64 - err := s.db.Table().DoTx(ctx, func(ctx context.Context, tx table.TransactionActor) error { + err := s.db.Query().DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { var err error freeSeats, err = s.getFreeSeatsTx(ctx, tx, id) @@ -114,30 +114,23 @@ func (s *server) getContentFromDB(ctx context.Context, id string) (int64, error) return freeSeats, err } -func (s *server) getFreeSeatsTx(ctx context.Context, tx table.TransactionActor, id string) (int64, error) { - var freeSeats int64 - res, err := tx.Execute(ctx, ` +func (s *server) getFreeSeatsTx(ctx context.Context, tx query.TxActor, id string) (int64, error) { + row, err := tx.QueryRow(ctx, ` DECLARE $id AS Text; SELECT freeSeats FROM bus WHERE id=$id; -`, table.NewQueryParameters(table.ValueParam("$id", types.UTF8Value(id)))) - if err != nil { - return 0, err +`, query.WithParameters( + ydb.ParamsBuilder().Param("$id").Any(types.UTF8Value(id)).Build(), + )) + if errors.Is(err, query.ErrNoRows) { + return 0, errors.New("not found") } - - err = res.NextResultSetErr(ctx, "freeSeats") if err != nil { return 0, err } - if !res.NextRow() { - freeSeats = 0 - - return 0, errors.New("not found") - } - - err = res.ScanWithDefaults(&freeSeats) - if err != nil { + var freeSeats int64 + if err := row.Scan(&freeSeats); err != nil { return 0, err } @@ -146,7 +139,7 @@ SELECT freeSeats FROM bus WHERE id=$id; func (s *server) sellTicket(ctx context.Context, id string) (int64, error) { var freeSeats int64 - err := s.db.Table().DoTx(ctx, func(ctx context.Context, tx table.TransactionActor) error { + err := s.db.Query().DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { var err error freeSeats, err = s.getFreeSeatsTx(ctx, tx, id) if err != nil { @@ -156,13 +149,13 @@ func (s *server) sellTicket(ctx context.Context, id string) (int64, error) { return fmt.Errorf("failed to sell ticket: %w", errNotEnthoughtFreeSeats) } - _, err = tx.Execute(ctx, ` + return tx.Exec(ctx, ` DECLARE $id AS Text; UPDATE bus SET freeSeats = freeSeats - 1 WHERE id=$id; -`, table.NewQueryParameters(table.ValueParam("$id", types.UTF8Value(id)))) - - return err +`, query.WithParameters( + ydb.ParamsBuilder().Param("$id").Any(types.UTF8Value(id)).Build(), + )) }) if err == nil { freeSeats-- @@ -176,21 +169,22 @@ func (s *server) IndexPageHandler(writer http.ResponseWriter, request *http.Requ var busIDs []string - err := s.db.Table().DoTx(ctx, func(ctx context.Context, tx table.TransactionActor) error { - res, err := tx.Execute(ctx, "SELECT id FROM bus ORDER BY id", nil) + err := s.db.Query().DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { + rs, err := tx.QueryResultSet(ctx, "SELECT id FROM bus ORDER BY id") if err != nil { return err } + defer rs.Close(ctx) - res.NextResultSet(ctx, "id") - - for res.HasNextRow() { - res.NextRow() - var id string - err = res.ScanWithDefaults(&id) + busIDs = busIDs[:0] + for row, err := range rs.Rows(ctx) { if err != nil { return err } + var id string + if err = row.Scan(&id); err != nil { + return err + } busIDs = append(busIDs, id) } diff --git a/examples/topic/cdc-fill-and-read/main.go b/examples/topic/cdc-fill-and-read/main.go index 15878cd51..c2b82c2c2 100644 --- a/examples/topic/cdc-fill-and-read/main.go +++ b/examples/topic/cdc-fill-and-read/main.go @@ -47,10 +47,10 @@ func main() { prepareTableWithCDC(ctx, db, prefix, tableName, topicPath, consumerName) - go fillTable(ctx, db.Table(), prefix, tableName) + go fillTable(ctx, db.Query(), prefix, tableName) go func() { time.Sleep(interval / 2) - removeFromTable(ctx, db.Table(), prefix, tableName) + removeFromTable(ctx, db.Query(), prefix, tableName) }() cdcRead(ctx, db, consumerName, topicPath) @@ -82,7 +82,7 @@ func prepareTableWithCDC(ctx context.Context, db *ydb.Driver, prefix, tableName, log.Println("Drop table (if exists)...") err := dropTableIfExists( ctx, - db.Table(), + db.Query(), path.Join(prefix, tableName), ) if err != nil { @@ -93,7 +93,7 @@ func prepareTableWithCDC(ctx context.Context, db *ydb.Driver, prefix, tableName, log.Println("Create table...") err = createTable( ctx, - db.Table(), + db.Query(), prefix, tableName, ) if err != nil { diff --git a/examples/topic/cdc-fill-and-read/tables.go b/examples/topic/cdc-fill-and-read/tables.go index a522bdf11..13e9e974f 100644 --- a/examples/topic/cdc-fill-and-read/tables.go +++ b/examples/topic/cdc-fill-and-read/tables.go @@ -9,8 +9,7 @@ import ( "time" ydb "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/table" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) @@ -19,37 +18,28 @@ const ( interval = time.Second ) -func dropTableIfExists(ctx context.Context, c table.Client, path string) (err error) { - err = c.Do(ctx, - func(ctx context.Context, s table.Session) error { - return s.DropTable(ctx, path) - }, - table.WithIdempotent(), +func dropTableIfExists(ctx context.Context, c query.Client, tablePath string) (err error) { + return c.Exec(ctx, + fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tablePath), + query.WithTxControl(query.ImplicitTxControl()), ) - if !ydb.IsOperationErrorSchemeError(err) { - return err - } - - return nil } -func createTable(ctx context.Context, c table.Client, prefix, tableName string) (err error) { - err = c.Do(ctx, - func(ctx context.Context, s table.Session) error { - return s.CreateTable(ctx, path.Join(prefix, tableName), - options.WithColumn("id", types.Optional(types.TypeUint64)), - options.WithColumn("value", types.Optional(types.TypeUTF8)), - options.WithPrimaryKeyColumn("id"), - ) - }, - table.WithIdempotent(), +func createTable(ctx context.Context, c query.Client, prefix, tableName string) (err error) { + err = c.Exec(ctx, + fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS `+"`%s`"+` ( + id Uint64, + value Text, + PRIMARY KEY (id) + )`, path.Join(prefix, tableName)), + query.WithTxControl(query.ImplicitTxControl()), ) if err != nil { return fmt.Errorf("failed to create table: %w", err) } - err = c.Do(ctx, func(ctx context.Context, s table.Session) error { - query := fmt.Sprintf(` + err = c.Exec(ctx, fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); ALTER TABLE @@ -60,10 +50,9 @@ WITH ( FORMAT = 'JSON', MODE = 'NEW_AND_OLD_IMAGES' ) -`, prefix, tableName) - - return s.ExecuteSchemeQuery(ctx, query) - }) +`, prefix, tableName), + query.WithTxControl(query.ImplicitTxControl()), + ) if err != nil { return fmt.Errorf("failed to add changefeed to test table: %w", err) } @@ -71,8 +60,8 @@ WITH ( return nil } -func fillTable(ctx context.Context, c table.Client, prefix, tableName string) { - query := fmt.Sprintf(` +func fillTable(ctx context.Context, c query.Client, prefix, tableName string) { + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $id AS Uint64; @@ -87,22 +76,23 @@ VALUES for { id := uint64(rand.Intn(maxID)) //nolint:gosec val := "val-" + strconv.Itoa(rand.Intn(10)) //nolint:gosec - params := table.NewQueryParameters( - table.ValueParam("$id", types.Uint64Value(id)), - table.ValueParam("$value", types.UTF8Value(val)), - ) - _ = c.DoTx(ctx, func(ctx context.Context, tx table.TransactionActor) error { - _, err := tx.Execute(ctx, query, params) - - return err + _ = c.DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { + return tx.Exec(ctx, sql, + query.WithParameters( + ydb.ParamsBuilder(). + Param("$id").Any(types.Uint64Value(id)). + Param("$value").Any(types.UTF8Value(val)). + Build(), + ), + ) }) time.Sleep(interval) } } -func removeFromTable(ctx context.Context, c table.Client, prefix, tableName string) { - query := fmt.Sprintf(` +func removeFromTable(ctx context.Context, c query.Client, prefix, tableName string) { + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $id AS Uint64; @@ -113,13 +103,14 @@ WHERE id=$id `, prefix, tableName) for { id := uint64(rand.Intn(maxID)) //nolint:gosec - params := table.NewQueryParameters( - table.ValueParam("$id", types.Uint64Value(id)), - ) - _ = c.DoTx(ctx, func(ctx context.Context, tx table.TransactionActor) error { - _, err := tx.Execute(ctx, query, params) - - return err + _ = c.DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { + return tx.Exec(ctx, sql, + query.WithParameters( + ydb.ParamsBuilder(). + Param("$id").Any(types.Uint64Value(id)). + Build(), + ), + ) }) time.Sleep(interval) diff --git a/examples/ttl/main.go b/examples/ttl/main.go index 5fcda6eb4..5d122db2b 100644 --- a/examples/ttl/main.go +++ b/examples/ttl/main.go @@ -74,12 +74,12 @@ func main() { prefix = path.Join(db.Name(), prefix) - err = createTables(ctx, db.Table(), prefix) + err = createTables(ctx, db.Query(), prefix) if err != nil { panic(fmt.Errorf("create tables error: %w", err)) } - err = addDocument(ctx, db.Table(), prefix, + err = addDocument(ctx, db.Query(), prefix, "https://yandex.ru/", "

Yandex

", 1) @@ -87,7 +87,7 @@ func main() { panic(fmt.Errorf("add document failed: %w", err)) } - err = addDocument(ctx, db.Table(), prefix, + err = addDocument(ctx, db.Query(), prefix, "https://ya.ru/", "

Ya

", 2) @@ -95,27 +95,27 @@ func main() { panic(fmt.Errorf("add document failed: %w", err)) } - err = readDocument(ctx, db.Table(), prefix, "https://yandex.ru/") + err = readDocument(ctx, db.Query(), prefix, "https://yandex.ru/") if err != nil { panic(fmt.Errorf("read document failed: %w", err)) } - err = readDocument(ctx, db.Table(), prefix, "https://ya.ru/") + err = readDocument(ctx, db.Query(), prefix, "https://ya.ru/") if err != nil { panic(fmt.Errorf("read document failed: %w", err)) } for i := range uint64(expirationQueueCount) { - if err = deleteExpired(ctx, db.Table(), prefix, i, 1); err != nil { + if err = deleteExpired(ctx, db.Query(), prefix, i, 1); err != nil { panic(fmt.Errorf("delete expired failed: %w", err)) } } - err = readDocument(ctx, db.Table(), prefix, "https://ya.ru/") + err = readDocument(ctx, db.Query(), prefix, "https://ya.ru/") if err != nil { panic(fmt.Errorf("read document failed: %w", err)) } - err = addDocument(ctx, db.Table(), prefix, + err = addDocument(ctx, db.Query(), prefix, "https://yandex.ru/", "

Yandex

", 2) @@ -123,7 +123,7 @@ func main() { panic(fmt.Errorf("add document failed: %w", err)) } - err = addDocument(ctx, db.Table(), prefix, + err = addDocument(ctx, db.Query(), prefix, "https://yandex.ru/", "

Yandex

", 3) @@ -132,16 +132,16 @@ func main() { } for i := range uint64(expirationQueueCount) { - if err = deleteExpired(ctx, db.Table(), prefix, i, 2); err != nil { + if err = deleteExpired(ctx, db.Query(), prefix, i, 2); err != nil { panic(fmt.Errorf("delete expired failed: %w", err)) } } - err = readDocument(ctx, db.Table(), prefix, "https://yandex.ru/") + err = readDocument(ctx, db.Query(), prefix, "https://yandex.ru/") if err != nil { panic(fmt.Errorf("read document failed: %w", err)) } - err = readDocument(ctx, db.Table(), prefix, "https://ya.ru/") + err = readDocument(ctx, db.Query(), prefix, "https://ya.ru/") if err != nil { panic(fmt.Errorf("read document failed: %w", err)) } diff --git a/examples/ttl/series.go b/examples/ttl/series.go index ba68190b4..be555cb2f 100644 --- a/examples/ttl/series.go +++ b/examples/ttl/series.go @@ -6,10 +6,8 @@ import ( "math/rand" "path" - "github.com/ydb-platform/ydb-go-sdk/v3/table" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" - "github.com/ydb-platform/ydb-go-sdk/v3/table/result" - "github.com/ydb-platform/ydb-go-sdk/v3/table/result/named" + ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) @@ -18,11 +16,11 @@ const ( expirationQueueCount = 4 ) -func readExpiredBatchTransaction(ctx context.Context, c table.Client, prefix string, queue, - timestamp, prevTimestamp, prevDocID uint64) (result.Result, +func readExpiredBatchTransaction(ctx context.Context, c query.Client, prefix string, queue, + timestamp, prevTimestamp, prevDocID uint64) (query.ClosableResultSet, error, ) { - query := fmt.Sprintf(` + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $timestamp AS Uint64; @@ -52,16 +50,19 @@ func readExpiredBatchTransaction(ctx context.Context, c table.Client, prefix str ORDER BY ts, doc_id LIMIT 100;`, prefix, queue, queue) - readTx := table.TxControl(table.BeginTx(table.WithOnlineReadOnly()), table.CommitTx()) - - var res result.Result + var rs query.ClosableResultSet err := c.Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, res, err = s.Execute(ctx, readTx, query, table.NewQueryParameters( - table.ValueParam("$timestamp", types.Uint64Value(timestamp)), - table.ValueParam("$prev_timestamp", types.Uint64Value(prevTimestamp)), - table.ValueParam("$prev_doc_id", types.Uint64Value(prevDocID)), - )) + func(ctx context.Context, s query.Session) (err error) { + rs, err = s.QueryResultSet(ctx, sql, + query.WithTxControl(query.OnlineReadOnlyTxControl()), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$timestamp").Any(types.Uint64Value(timestamp)). + Param("$prev_timestamp").Any(types.Uint64Value(prevTimestamp)). + Param("$prev_doc_id").Any(types.Uint64Value(prevDocID)). + Build(), + ), + ) return err }, @@ -69,17 +70,14 @@ func readExpiredBatchTransaction(ctx context.Context, c table.Client, prefix str if err != nil { return nil, err } - if res.Err() != nil { - return nil, res.Err() - } - return res, nil + return rs, nil } func deleteDocumentWithTimestamp(ctx context.Context, - c table.Client, prefix string, queue, lastDocID, timestamp uint64, + c query.Client, prefix string, queue, lastDocID, timestamp uint64, ) error { - query := fmt.Sprintf(` + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $doc_id AS Uint64; @@ -91,23 +89,22 @@ func deleteDocumentWithTimestamp(ctx context.Context, DELETE FROM expiration_queue_%v WHERE ts = $timestamp AND doc_id = $doc_id;`, prefix, queue) - writeTx := table.TxControl(table.BeginTx(table.WithSerializableReadWrite()), table.CommitTx()) - - err := c.Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, _, err = s.Execute(ctx, writeTx, query, table.NewQueryParameters( - table.ValueParam("$doc_id", types.Uint64Value(lastDocID)), - table.ValueParam("$timestamp", types.Uint64Value(timestamp)), - )) - - return err + return c.Do(ctx, + func(ctx context.Context, s query.Session) (err error) { + return s.Exec(ctx, sql, + query.WithTxControl(query.SerializableReadWriteTxControl(query.CommitTx())), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$doc_id").Any(types.Uint64Value(lastDocID)). + Param("$timestamp").Any(types.Uint64Value(timestamp)). + Build(), + ), + ) }, ) - - return err } -func deleteExpired(ctx context.Context, c table.Client, prefix string, queue, timestamp uint64) (err error) { +func deleteExpired(ctx context.Context, c query.Client, prefix string, queue, timestamp uint64) (err error) { fmt.Printf("> DeleteExpired from queue #%d:\n", queue) empty := false lastTimestamp := uint64(0) @@ -115,21 +112,23 @@ func deleteExpired(ctx context.Context, c table.Client, prefix string, queue, ti for !empty { err = func() (err error) { // for isolate defer inside lambda - res, err := readExpiredBatchTransaction(ctx, c, prefix, queue, timestamp, lastTimestamp, lastDocID) + rs, err := readExpiredBatchTransaction(ctx, c, prefix, queue, timestamp, lastTimestamp, lastDocID) if err != nil { return err } defer func() { - _ = res.Close() + _ = rs.Close(ctx) }() - empty = true - res.NextResultSet(ctx) - for res.NextRow() { - empty = false - err = res.ScanNamed( - named.OptionalWithDefault("doc_id", &lastDocID), - named.OptionalWithDefault("ts", &lastTimestamp), + hasRows := false + for row, err := range rs.Rows(ctx) { + if err != nil { + return err + } + hasRows = true + err = row.ScanNamed( + query.Named("doc_id", &lastDocID), + query.Named("ts", &lastTimestamp), ) if err != nil { return err @@ -142,7 +141,11 @@ func deleteExpired(ctx context.Context, c table.Client, prefix string, queue, ti } } - return res.Err() + if !hasRows { + empty = true + } + + return nil }() if err != nil { return err @@ -152,10 +155,10 @@ func deleteExpired(ctx context.Context, c table.Client, prefix string, queue, ti return nil } -func readDocument(ctx context.Context, c table.Client, prefix, url string) error { +func readDocument(ctx context.Context, c query.Client, prefix, url string) error { fmt.Printf("> ReadDocument \"%v\":\n", url) - query := fmt.Sprintf(` + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $url AS Text; @@ -166,31 +169,40 @@ func readDocument(ctx context.Context, c table.Client, prefix, url string) error FROM documents WHERE doc_id = $doc_id;`, prefix) - readTx := table.TxControl(table.BeginTx(table.WithOnlineReadOnly()), table.CommitTx()) - - err := c.Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, res, err := s.Execute(ctx, readTx, query, table.NewQueryParameters( - table.ValueParam("$url", types.TextValue(url)), - )) + return c.Do(ctx, + func(ctx context.Context, s query.Session) (err error) { + rs, err := s.QueryResultSet(ctx, sql, + query.WithTxControl(query.OnlineReadOnlyTxControl()), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$url").Any(types.TextValue(url)). + Build(), + ), + ) if err != nil { return err } defer func() { - _ = res.Close() + _ = rs.Close(ctx) }() - var ( - docID *uint64 - docURL *string - ts *uint64 - html *string - ) - if res.NextResultSet(ctx) && res.NextRow() { - err = res.ScanNamed( - named.Optional("doc_id", &docID), - named.Optional("url", &docURL), - named.Optional("ts", &ts), - named.Optional("html", &html), + + found := false + for row, err := range rs.Rows(ctx) { + if err != nil { + return err + } + found = true + var ( + docID *uint64 + docURL *string + ts *uint64 + html *string + ) + err = row.ScanNamed( + query.Named("doc_id", &docID), + query.Named("url", &docURL), + query.Named("ts", &ts), + query.Named("html", &html), ) if err != nil { return err @@ -199,22 +211,22 @@ func readDocument(ctx context.Context, c table.Client, prefix, url string) error fmt.Printf("\tUrl: %v\n", docURL) fmt.Printf("\tTimestamp: %v\n", ts) fmt.Printf("\tHtml: %v\n", html) - } else { + } + + if !found { fmt.Println("\tNot found") } - return res.Err() + return nil }, ) - - return err } -func addDocument(ctx context.Context, c table.Client, prefix, url, html string, timestamp uint64) error { +func addDocument(ctx context.Context, c query.Client, prefix, url, html string, timestamp uint64) error { fmt.Printf("> AddDocument: \n\tUrl: %v\n\tTimestamp: %v\n", url, timestamp) queue := rand.Intn(expirationQueueCount) //nolint:gosec - query := fmt.Sprintf(` + sql := fmt.Sprintf(` PRAGMA TablePathPrefix("%v"); DECLARE $url AS Text; @@ -233,35 +245,33 @@ func addDocument(ctx context.Context, c table.Client, prefix, url, html string, VALUES ($timestamp, $doc_id);`, prefix, queue) - writeTx := table.TxControl(table.BeginTx(table.WithSerializableReadWrite()), table.CommitTx()) - - err := c.Do(ctx, - func(ctx context.Context, s table.Session) (err error) { - _, _, err = s.Execute(ctx, writeTx, query, table.NewQueryParameters( - table.ValueParam("$url", types.TextValue(url)), - table.ValueParam("$html", types.TextValue(html)), - table.ValueParam("$timestamp", types.Uint64Value(timestamp)), - )) - - return err + return c.Do(ctx, + func(ctx context.Context, s query.Session) (err error) { + return s.Exec(ctx, sql, + query.WithTxControl(query.SerializableReadWriteTxControl(query.CommitTx())), + query.WithParameters( + ydb.ParamsBuilder(). + Param("$url").Any(types.TextValue(url)). + Param("$html").Any(types.TextValue(html)). + Param("$timestamp").Any(types.Uint64Value(timestamp)). + Build(), + ), + ) }, ) - - return err } -func createTables(ctx context.Context, c table.Client, prefix string) (err error) { - err = c.Do(ctx, - func(ctx context.Context, s table.Session) error { - return s.CreateTable(ctx, path.Join(prefix, "documents"), - options.WithColumn("doc_id", types.Optional(types.TypeUint64)), - options.WithColumn("url", types.Optional(types.TypeUTF8)), - options.WithColumn("html", types.Optional(types.TypeUTF8)), - options.WithColumn("ts", types.Optional(types.TypeUint64)), - options.WithPrimaryKeyColumn("doc_id"), - options.WithPartitions(options.WithUniformPartitions(uint64(docTablePartitionCount))), - ) - }, +func createTables(ctx context.Context, c query.Client, prefix string) (err error) { + err = c.Exec(ctx, + fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS `+"`%s`"+` ( + doc_id Uint64, + url Text, + html Text, + ts Uint64, + PRIMARY KEY (doc_id) + )`, path.Join(prefix, "documents")), + query.WithTxControl(query.ImplicitTxControl()), ) if err != nil { return err @@ -269,14 +279,14 @@ func createTables(ctx context.Context, c table.Client, prefix string) (err error for i := range expirationQueueCount { tableName := path.Join(prefix, fmt.Sprintf("expiration_queue_%v", i)) - err = c.Do(ctx, - func(ctx context.Context, s table.Session) error { - return s.CreateTable(ctx, tableName, - options.WithColumn("doc_id", types.Optional(types.TypeUint64)), - options.WithColumn("ts", types.Optional(types.TypeUint64)), - options.WithPrimaryKeyColumn("ts", "doc_id"), - ) - }, + err = c.Exec(ctx, + fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS `+"`%s`"+` ( + doc_id Uint64, + ts Uint64, + PRIMARY KEY (ts, doc_id) + )`, tableName), + query.WithTxControl(query.ImplicitTxControl()), ) if err != nil { return err