Skip to content

Commit

Permalink
Added logic for working with Tarantool schema via Box
Browse files Browse the repository at this point in the history
- Implemented the `box.Schema()` method that returns a `Schema` object for schema-related operations
  • Loading branch information
maksim.konovalov committed Jan 23, 2025
1 parent d8e2284 commit a492cb5
Show file tree
Hide file tree
Showing 13 changed files with 1,392 additions and 50 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
### Added

- Extend box with replication information (#427).
- Implemented all box.schema.user operations requests and sugar interface.
- Implemented box.session.su request and sugar interface only for current session granting.

### Changed

Expand Down
6 changes: 6 additions & 0 deletions box/box.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ func New(conn tarantool.Doer) *Box {
}
}

// Schema returns a new Schema instance, providing access to schema-related operations.
// It uses the connection from the Box instance to communicate with Tarantool.
func (b *Box) Schema() *Schema {
return NewSchema(b.conn)
}

// Info retrieves the current information of the Tarantool instance.
// It calls the "box.info" function and parses the result into the Info structure.
func (b *Box) Info() (Info, error) {
Expand Down
128 changes: 127 additions & 1 deletion box/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
"github.com/tarantool/go-tarantool/v2/box"
)

func Example() {
func ExampleBox_Info() {
dialer := tarantool.NetDialer{
Address: "127.0.0.1:3013",
User: "test",
Expand Down Expand Up @@ -58,3 +58,129 @@ func Example() {
fmt.Printf("Box info uuids are equal")
fmt.Printf("Current box info: %+v\n", resp.Info)
}

func ExampleSchemaUser_Exists() {
dialer := tarantool.NetDialer{
Address: "127.0.0.1:3013",
User: "test",
Password: "test",
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
client, err := tarantool.Connect(ctx, dialer, tarantool.Opts{})
cancel()
if err != nil {
log.Fatalf("Failed to connect: %s", err)
}

// You can use UserExistsRequest type and call it directly.
fut := client.Do(box.NewUserExistsRequest("user"))

resp := &box.UserExistsResponse{}

err = fut.GetTyped(resp)
if err != nil {
log.Fatalf("Failed get box schema user exists with error: %s", err)
}

// Or use simple User implementation.
b := box.New(client)
exists, err := b.Schema().User().Exists(ctx, "user")
if err != nil {
log.Fatalf("Failed get box schema user exists with error: %s", err)
}

if exists != resp.Exists {
log.Fatalf("Box schema users exists are not equal")
}

fmt.Printf("Box schema users exists are equal")
fmt.Printf("Current exists state: %+v\n", exists)
}

func ExampleSchemaUser_Create() {
// Connect to Tarantool
dialer := tarantool.NetDialer{
Address: "127.0.0.1:3013",
User: "test",
Password: "test",
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
client, err := tarantool.Connect(ctx, dialer, tarantool.Opts{})
cancel()
if err != nil {
log.Fatalf("Failed to connect: %s", err)
}

// Create SchemaUser
schemaUser := box.NewSchemaUser(client)

// Create a new user
username := "new_user"
options := box.UserCreateOptions{
IfNotExists: true,
Password: "secure_password",
}
err = schemaUser.Create(ctx, username, options)
if err != nil {
log.Fatalf("Failed to create user: %s", err)
}

fmt.Printf("User '%s' created successfully\n", username)
}

func ExampleSchemaUser_Drop() {
// Connect to Tarantool
dialer := tarantool.NetDialer{
Address: "127.0.0.1:3013",
User: "test",
Password: "test",
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
client, err := tarantool.Connect(ctx, dialer, tarantool.Opts{})
cancel()
if err != nil {
log.Fatalf("Failed to connect: %s", err)
}

// Create SchemaUser
schemaUser := box.NewSchemaUser(client)

// Drop an existing user
username := "new_user"
options := box.UserDropOptions{
IfExists: true,
}
err = schemaUser.Drop(ctx, username, options)
if err != nil {
log.Fatalf("Failed to drop user: %s", err)
}

fmt.Printf("User '%s' dropped successfully\n", username)
}

func ExampleSchemaUser_Password() {
// Connect to Tarantool
dialer := tarantool.NetDialer{
Address: "127.0.0.1:3013",
User: "test",
Password: "test",
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
client, err := tarantool.Connect(ctx, dialer, tarantool.Opts{})
cancel()
if err != nil {
log.Fatalf("Failed to connect: %s", err)
}

// Create SchemaUser
schemaUser := box.NewSchemaUser(client)

// Get the password hash
password := "my-password"
passwordHash, err := schemaUser.Password(ctx, password)
if err != nil {
log.Fatalf("Failed to get password hash: %s", err)
}

fmt.Printf("Password '%s' hash: %s\n", password, passwordHash)
}
16 changes: 6 additions & 10 deletions box/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,14 @@ func (ir *InfoResponse) DecodeMsgpack(d *msgpack.Decoder) error {
// InfoRequest represents a request to retrieve information about the Tarantool instance.
// It implements the tarantool.Request interface.
type InfoRequest struct {
baseRequest
}

// Body method is used to serialize the request's body.
// It is part of the tarantool.Request interface implementation.
func (i InfoRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error {
return i.impl.Body(res, enc)
*tarantool.CallRequest // Underlying Tarantool call request.
}

// NewInfoRequest returns a new empty info request.
func NewInfoRequest() InfoRequest {
req := InfoRequest{}
req.impl = newCall("box.info")
return req
callReq := tarantool.NewCallRequest("box.info")

return InfoRequest{
callReq,
}
}
38 changes: 0 additions & 38 deletions box/request.go

This file was deleted.

21 changes: 21 additions & 0 deletions box/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package box

import "github.com/tarantool/go-tarantool/v2"

// Schema represents the schema-related operations in Tarantool.
// It holds a connection to interact with the Tarantool instance.
type Schema struct {
conn tarantool.Doer // Connection interface for interacting with Tarantool.
}

// NewSchema creates a new Schema instance with the provided Tarantool connection.
// It initializes a Schema object that can be used for schema-related operations
// such as managing users, tables, and other schema elements in the Tarantool instance.
func NewSchema(conn tarantool.Doer) *Schema {
return &Schema{conn: conn} // Pass the connection to the Schema.
}

// User returns a new SchemaUser instance, allowing schema-related user operations.
func (s *Schema) User() *SchemaUser {
return NewSchemaUser(s.conn)
}
16 changes: 16 additions & 0 deletions box/schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package box

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestNewSchema(t *testing.T) {
// Create a schema instance with a nil connection. This should lead to a panic later.
b := NewSchema(nil)

// Ensure the schema is not nil (which it shouldn't be), but this is not meaningful
// since we will panic when we call the schema methods with the nil connection.
require.NotNil(t, b)
}
Loading

0 comments on commit a492cb5

Please sign in to comment.