From c2d837c599483abd64969c3e5ced6ccc43cdb2a0 Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Thu, 26 Oct 2023 13:04:52 -0400 Subject: [PATCH 1/7] Add GetSchemaByVersionID Also adds a bunch of infrastructure that will be also used by GetSchema funcs in the next few commits. --- cli/cli.go | 1 + cli/schema_describe.go | 74 +++++++++++++++ client/db.go | 6 ++ client/mocks/db.go | 53 +++++++++++ db/schema.go | 8 ++ db/txn_db.go | 22 +++++ http/client.go | 15 +++ http/handler_store.go | 57 ++++++++++++ http/openapi.go | 1 + tests/clients/cli/wrapper.go | 15 +++ tests/clients/http/wrapper.go | 4 + tests/integration/schema/get_schema_test.go | 32 +++++++ tests/integration/schema/simple_test.go | 21 +++++ .../schema/updates/add/field/simple_test.go | 91 +++++++++++++++++++ tests/integration/test_case.go | 17 ++++ tests/integration/utils2.go | 26 ++++++ 16 files changed, 443 insertions(+) create mode 100644 cli/schema_describe.go create mode 100644 tests/integration/schema/get_schema_test.go diff --git a/cli/cli.go b/cli/cli.go index 0cb9fbb5bc..0f93b69633 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -59,6 +59,7 @@ func NewDefraCommand(cfg *config.Config) *cobra.Command { MakeSchemaAddCommand(), MakeSchemaPatchCommand(), MakeSchemaSetDefaultCommand(), + MakeSchemaDescribeCommand(), schema_migrate, ) diff --git a/cli/schema_describe.go b/cli/schema_describe.go new file mode 100644 index 0000000000..51b4e8eba7 --- /dev/null +++ b/cli/schema_describe.go @@ -0,0 +1,74 @@ +// Copyright 2023 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/sourcenetwork/defradb/client" +) + +func MakeSchemaDescribeCommand() *cobra.Command { + var name string + var root string + var versionID string + + var cmd = &cobra.Command{ + Use: "describe", + Short: "View schema description.", + Long: `Introspect schema types. + +Example: view all schema + defradb client schema describe + +Example: view schema by name + defradb client schema describe --name User + +Example: view schema by root + defradb client schema describe --root bae123 + +Example: view schema by version id + defradb client schema describe --version bae123 + `, + RunE: func(cmd *cobra.Command, args []string) error { + store := mustGetStoreContext(cmd) + + var schemas []client.SchemaDescription + switch { + case versionID != "": + schema, err := store.GetSchemaByVersionID(cmd.Context(), versionID) + if err != nil { + return err + } + schemas = []client.SchemaDescription{schema} + + case root != "": + panic("todo") + + case name != "": + panic("todo") + + default: + panic("todo") + } + + if len(schemas) == 1 { + return writeJSON(cmd, schemas[0]) + } + + return writeJSON(cmd, schemas) + }, + } + cmd.PersistentFlags().StringVar(&name, "name", "", "Schema name") + cmd.PersistentFlags().StringVar(&root, "root", "", "Schema root") + cmd.PersistentFlags().StringVar(&versionID, "version", "", "Schema Version ID") + return cmd +} diff --git a/client/db.go b/client/db.go index 81376bd6ca..c7dc46f15f 100644 --- a/client/db.go +++ b/client/db.go @@ -161,6 +161,12 @@ type Store interface { // this [Store]. GetAllCollections(context.Context) ([]Collection, error) + // GetSchemaByVersionID returns the schema description for the schema version of the + // ID provided. + // + // Will return an error if it is not found. + GetSchemaByVersionID(context.Context, string) (SchemaDescription, error) + // GetAllIndexes returns all the indexes that currently exist within this [Store]. GetAllIndexes(context.Context) (map[CollectionName][]IndexDescription, error) diff --git a/client/mocks/db.go b/client/mocks/db.go index f021d1fd10..c812cb2aa5 100644 --- a/client/mocks/db.go +++ b/client/mocks/db.go @@ -603,6 +603,59 @@ func (_c *DB_GetCollectionsByVersionID_Call) RunAndReturn(run func(context.Conte return _c } +// GetSchemaByVersionID provides a mock function with given fields: _a0, _a1 +func (_m *DB) GetSchemaByVersionID(_a0 context.Context, _a1 string) (client.SchemaDescription, error) { + ret := _m.Called(_a0, _a1) + + var r0 client.SchemaDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (client.SchemaDescription, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, string) client.SchemaDescription); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(client.SchemaDescription) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_GetSchemaByVersionID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemaByVersionID' +type DB_GetSchemaByVersionID_Call struct { + *mock.Call +} + +// GetSchemaByVersionID is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +func (_e *DB_Expecter) GetSchemaByVersionID(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByVersionID_Call { + return &DB_GetSchemaByVersionID_Call{Call: _e.mock.On("GetSchemaByVersionID", _a0, _a1)} +} + +func (_c *DB_GetSchemaByVersionID_Call) Run(run func(_a0 context.Context, _a1 string)) *DB_GetSchemaByVersionID_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *DB_GetSchemaByVersionID_Call) Return(_a0 client.SchemaDescription, _a1 error) *DB_GetSchemaByVersionID_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_GetSchemaByVersionID_Call) RunAndReturn(run func(context.Context, string) (client.SchemaDescription, error)) *DB_GetSchemaByVersionID_Call { + _c.Call.Return(run) + return _c +} + // LensRegistry provides a mock function with given fields: func (_m *DB) LensRegistry() client.LensRegistry { ret := _m.Called() diff --git a/db/schema.go b/db/schema.go index 627602119b..a0b9d06038 100644 --- a/db/schema.go +++ b/db/schema.go @@ -289,6 +289,14 @@ func substituteSchemaPatch( return patch, nil } +func (db *db) getSchemaByVersionID( + ctx context.Context, + txn datastore.Txn, + versionID string, +) (client.SchemaDescription, error) { + return description.GetSchemaVersion(ctx, txn, versionID) +} + // getSubstituteFieldKind checks and attempts to get the underlying integer value for the given string // Field Kind value. It will return the value if one is found, else returns an [ErrFieldKindNotFound]. // diff --git a/db/txn_db.go b/db/txn_db.go index d9c1b4b206..be4811bb70 100644 --- a/db/txn_db.go +++ b/db/txn_db.go @@ -175,6 +175,28 @@ func (db *explicitTxnDB) GetAllCollections(ctx context.Context) ([]client.Collec return db.getAllCollections(ctx, db.txn) } +// GetSchemaByVersionID returns the schema description for the schema version of the +// ID provided. +// +// Will return an error if it is not found. +func (db *implicitTxnDB) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { + txn, err := db.NewTxn(ctx, true) + if err != nil { + return client.SchemaDescription{}, err + } + defer txn.Discard(ctx) + + return db.getSchemaByVersionID(ctx, txn, versionID) +} + +// GetSchemaByVersionID returns the schema description for the schema version of the +// ID provided. +// +// Will return an error if it is not found. +func (db *explicitTxnDB) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { + return db.getSchemaByVersionID(ctx, db.txn, versionID) +} + // GetAllIndexes gets all the indexes in the database. func (db *implicitTxnDB) GetAllIndexes( ctx context.Context, diff --git a/http/client.go b/http/client.go index 15c44aca38..5b5e09f6e4 100644 --- a/http/client.go +++ b/http/client.go @@ -242,6 +242,21 @@ func (c *Client) GetAllCollections(ctx context.Context) ([]client.Collection, er return collections, nil } +func (c *Client) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { + methodURL := c.http.baseURL.JoinPath("schema") + methodURL.RawQuery = url.Values{"version_id": []string{versionID}}.Encode() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, methodURL.String(), nil) + if err != nil { + return client.SchemaDescription{}, err + } + var schema client.SchemaDescription + if err := c.http.requestJson(req, &schema); err != nil { + return client.SchemaDescription{}, err + } + return schema, nil +} + func (c *Client) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { methodURL := c.http.baseURL.JoinPath("indexes") diff --git a/http/handler_store.go b/http/handler_store.go index 4a3bf0127c..9ecb449608 100644 --- a/http/handler_store.go +++ b/http/handler_store.go @@ -153,6 +153,26 @@ func (s *storeHandler) GetCollection(rw http.ResponseWriter, req *http.Request) } } +func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { + store := req.Context().Value(storeContextKey).(client.Store) + + switch { + case req.URL.Query().Has("name"): + panic("todo") + case req.URL.Query().Has("root"): + panic("todo") + case req.URL.Query().Has("version_id"): + schema, err := store.GetSchemaByVersionID(req.Context(), req.URL.Query().Get("version_id")) + if err != nil { + responseJSON(rw, http.StatusBadRequest, errorResponse{err}) + return + } + responseJSON(rw, http.StatusOK, schema) + default: + panic("todo") + } +} + func (s *storeHandler) GetAllIndexes(rw http.ResponseWriter, req *http.Request) { store := req.Context().Value(storeContextKey).(client.Store) @@ -291,6 +311,9 @@ func (h *storeHandler) bindRoutes(router *Router) { collectionSchema := &openapi3.SchemaRef{ Ref: "#/components/schemas/collection", } + schemaSchema := &openapi3.SchemaRef{ + Ref: "#/components/schemas/schema", + } graphQLRequestSchema := &openapi3.SchemaRef{ Ref: "#/components/schemas/graphql_request", } @@ -411,6 +434,39 @@ func (h *storeHandler) bindRoutes(router *Router) { collectionDescribe.AddResponse(200, collectionsResponse) collectionDescribe.Responses["400"] = errorResponse + schemaNameQueryParam := openapi3.NewQueryParameter("name"). + WithDescription("Schema name"). + WithSchema(openapi3.NewStringSchema()) + schemaSchemaRootQueryParam := openapi3.NewQueryParameter("root"). + WithDescription("Schema root"). + WithSchema(openapi3.NewStringSchema()) + schemaVersionIDQueryParam := openapi3.NewQueryParameter("version_id"). + WithDescription("Schema version id"). + WithSchema(openapi3.NewStringSchema()) + + schemasSchema := openapi3.NewArraySchema() + schemasSchema.Items = schemaSchema + + schemaResponseSchema := openapi3.NewOneOfSchema() + schemaResponseSchema.OneOf = openapi3.SchemaRefs{ + schemaSchema, + openapi3.NewSchemaRef("", schemasSchema), + } + + schemaResponse := openapi3.NewResponse(). + WithDescription("Schema(s) with matching name, schema id, or version id."). + WithJSONSchema(schemaResponseSchema) + + schemaDescribe := openapi3.NewOperation() + schemaDescribe.OperationID = "schema_describe" + schemaDescribe.Description = "Introspect schema(s) by name, schema root, or version id." + schemaDescribe.Tags = []string{"schema"} + schemaDescribe.AddParameter(schemaNameQueryParam) + schemaDescribe.AddParameter(schemaSchemaRootQueryParam) + schemaDescribe.AddParameter(schemaVersionIDQueryParam) + schemaDescribe.AddResponse(200, schemaResponse) + schemaDescribe.Responses["400"] = errorResponse + graphQLRequest := openapi3.NewRequestBody(). WithContent(openapi3.NewContentWithJSONSchemaRef(graphQLRequestSchema)) @@ -455,5 +511,6 @@ func (h *storeHandler) bindRoutes(router *Router) { router.AddRoute("/debug/dump", http.MethodGet, debugDump, h.PrintDump) router.AddRoute("/schema", http.MethodPost, addSchema, h.AddSchema) router.AddRoute("/schema", http.MethodPatch, patchSchema, h.PatchSchema) + router.AddRoute("/schema", http.MethodGet, schemaDescribe, h.GetSchema) router.AddRoute("/schema/default", http.MethodPost, setDefaultSchemaVersion, h.SetDefaultSchemaVersion) } diff --git a/http/openapi.go b/http/openapi.go index 88a8f2097d..4aa217e939 100644 --- a/http/openapi.go +++ b/http/openapi.go @@ -29,6 +29,7 @@ var openApiSchemas = map[string]any{ "graphql_response": &GraphQLResponse{}, "backup_config": &client.BackupConfig{}, "collection": &client.CollectionDescription{}, + "schema": &client.SchemaDescription{}, "index": &client.IndexDescription{}, "delete_result": &client.DeleteResult{}, "update_result": &client.UpdateResult{}, diff --git a/tests/clients/cli/wrapper.go b/tests/clients/cli/wrapper.go index 0215d92d82..59005b0dc6 100644 --- a/tests/clients/cli/wrapper.go +++ b/tests/clients/cli/wrapper.go @@ -281,6 +281,21 @@ func (w *Wrapper) GetAllCollections(ctx context.Context) ([]client.Collection, e return cols, err } +func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { + args := []string{"client", "schema", "describe"} + args = append(args, "--version", versionID) + + data, err := w.cmd.execute(ctx, args) + if err != nil { + return client.SchemaDescription{}, err + } + var schema client.SchemaDescription + if err := json.Unmarshal(data, &schema); err != nil { + return client.SchemaDescription{}, err + } + return schema, err +} + func (w *Wrapper) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { args := []string{"client", "index", "list"} diff --git a/tests/clients/http/wrapper.go b/tests/clients/http/wrapper.go index 3a26b6c0fd..a1ea89f02e 100644 --- a/tests/clients/http/wrapper.go +++ b/tests/clients/http/wrapper.go @@ -127,6 +127,10 @@ func (w *Wrapper) GetAllCollections(ctx context.Context) ([]client.Collection, e return w.client.GetAllCollections(ctx) } +func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { + return w.client.GetSchemaByVersionID(ctx, versionID) +} + func (w *Wrapper) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { return w.client.GetAllIndexes(ctx) } diff --git a/tests/integration/schema/get_schema_test.go b/tests/integration/schema/get_schema_test.go new file mode 100644 index 0000000000..c5e2d90641 --- /dev/null +++ b/tests/integration/schema/get_schema_test.go @@ -0,0 +1,32 @@ +// Copyright 2023 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package schema + +import ( + "testing" + + "github.com/sourcenetwork/immutable" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" +) + +func TestGetSchema_GivenNonExistantSchemaVersionID_Errors(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.GetSchema{ + VersionID: immutable.Some("does not exist"), + ExpectedError: "datastore: key not found", + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/schema/simple_test.go b/tests/integration/schema/simple_test.go index 47ef9810be..6bcb2a1dec 100644 --- a/tests/integration/schema/simple_test.go +++ b/tests/integration/schema/simple_test.go @@ -13,10 +13,15 @@ package schema import ( "testing" + "github.com/sourcenetwork/immutable" + + "github.com/sourcenetwork/defradb/client" testUtils "github.com/sourcenetwork/defradb/tests/integration" ) func TestSchemaSimpleCreatesSchemaGivenEmptyType(t *testing.T) { + schemaVersionID := "bafkreickgf3nbjaairxkkqawmrv7fafaafyccl4qygqeveagisdn42eohu" + test := testUtils.TestCase{ Actions: []any{ testUtils.SchemaUpdate{ @@ -38,6 +43,22 @@ func TestSchemaSimpleCreatesSchemaGivenEmptyType(t *testing.T) { }, }, }, + testUtils.GetSchema{ + VersionID: immutable.Some(schemaVersionID), + ExpectedResults: []client.SchemaDescription{ + { + Name: "Users", + VersionID: schemaVersionID, + Root: schemaVersionID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + }, + }, + }, + }, + }, }, } diff --git a/tests/integration/schema/updates/add/field/simple_test.go b/tests/integration/schema/updates/add/field/simple_test.go index 56931567d4..69ddfd1734 100644 --- a/tests/integration/schema/updates/add/field/simple_test.go +++ b/tests/integration/schema/updates/add/field/simple_test.go @@ -15,10 +15,14 @@ import ( "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/client" testUtils "github.com/sourcenetwork/defradb/tests/integration" ) func TestSchemaUpdatesAddFieldSimple(t *testing.T) { + schemaVersion1ID := "bafkreih27vuxrj4j2tmxnibfm77wswa36xji74hwhq7deipj5rvh3qyabq" + schemaVersion2ID := "bafkreid5bpw7sipm63l5gxxjrs34yrq2ur5xrzyseez5rnj3pvnvkaya6m" + test := testUtils.TestCase{ Description: "Test schema update, add field", Actions: []any{ @@ -45,6 +49,35 @@ func TestSchemaUpdatesAddFieldSimple(t *testing.T) { }`, Results: []map[string]any{}, }, + testUtils.GetSchema{ + VersionID: immutable.Some(schemaVersion2ID), + ExpectedResults: []client.SchemaDescription{ + { + Name: "Users", + VersionID: schemaVersion2ID, + Root: schemaVersion1ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + Typ: client.LWW_REGISTER, + }, + { + Name: "name", + ID: 1, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + { + Name: "email", + ID: 2, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + }, + }, + }, + }, }, } testUtils.ExecuteTestCase(t, test) @@ -83,6 +116,64 @@ func TestSchemaUpdates_AddFieldSimpleDoNotSetDefault_Errors(t *testing.T) { testUtils.ExecuteTestCase(t, test) } +func TestSchemaUpdates_AddFieldSimpleDoNotSetDefault_VersionIsQueryable(t *testing.T) { + schemaVersion1ID := "bafkreih27vuxrj4j2tmxnibfm77wswa36xji74hwhq7deipj5rvh3qyabq" + schemaVersion2ID := "bafkreid5bpw7sipm63l5gxxjrs34yrq2ur5xrzyseez5rnj3pvnvkaya6m" + + test := testUtils.TestCase{ + Description: "Test schema update, add field", + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Users { + name: String + } + `, + }, + testUtils.SchemaPatch{ + Patch: ` + [ + { "op": "add", "path": "/Users/Fields/-", "value": {"Name": "email", "Kind": 11} } + ] + `, + SetAsDefaultVersion: immutable.Some(false), + }, + testUtils.GetSchema{ + VersionID: immutable.Some(schemaVersion2ID), + ExpectedResults: []client.SchemaDescription{ + { + Name: "Users", + // Even though schema version 2 is not active, it should still be possible to + // fetch it. + VersionID: schemaVersion2ID, + Root: schemaVersion1ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + Typ: client.LWW_REGISTER, + }, + { + Name: "name", + ID: 1, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + { + Name: "email", + ID: 2, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + }, + }, + }, + }, + }, + } + testUtils.ExecuteTestCase(t, test) +} + func TestSchemaUpdatesAddFieldSimpleErrorsAddingToUnknownCollection(t *testing.T) { test := testUtils.TestCase{ Description: "Test schema update, add to unknown collection fails", diff --git a/tests/integration/test_case.go b/tests/integration/test_case.go index fabdccbbfd..21933a7292 100644 --- a/tests/integration/test_case.go +++ b/tests/integration/test_case.go @@ -91,6 +91,23 @@ type SchemaPatch struct { ExpectedError string } +// GetSchema is an action that fetches schema using the provided options. +type GetSchema struct { + // NodeID may hold the ID (index) of a node to apply this patch to. + // + // If a value is not provided the patch will be applied to all nodes. + NodeID immutable.Option[int] + + // The VersionID of the schema version to fetch. + // + // This option will be prioritized over all other options. + VersionID immutable.Option[string] + + ExpectedResults []client.SchemaDescription + + ExpectedError string +} + // SetDefaultSchemaVersion is an action that will set the default schema version to the // given value. type SetDefaultSchemaVersion struct { diff --git a/tests/integration/utils2.go b/tests/integration/utils2.go index 01c6c7c69f..c0af266065 100644 --- a/tests/integration/utils2.go +++ b/tests/integration/utils2.go @@ -254,6 +254,9 @@ func performAction( case SchemaPatch: patchSchema(s, action) + case GetSchema: + getSchema(s, action) + case SetDefaultSchemaVersion: setDefaultSchemaVersion(s, action) @@ -949,6 +952,29 @@ func patchSchema( refreshIndexes(s) } +func getSchema( + s *state, + action GetSchema, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + var results []client.SchemaDescription + var err error + switch { + case action.VersionID.HasValue(): + result, e := node.GetSchemaByVersionID(s.ctx, action.VersionID.Value()) + err = e + results = []client.SchemaDescription{result} + } + + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if !expectedErrorRaised { + require.Equal(s.t, action.ExpectedResults, results) + } + } +} + func setDefaultSchemaVersion( s *state, action SetDefaultSchemaVersion, From 85087360194ab2e5518447b57fcfb8d4e6ff5286 Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Thu, 26 Oct 2023 14:31:39 -0400 Subject: [PATCH 2/7] Add GetAllSchema --- cli/schema_describe.go | 6 +- client/db.go | 4 + client/mocks/db.go | 54 +++++++++++++ db/description/schema.go | 41 ++++++++++ db/schema.go | 7 ++ db/txn_db.go | 18 +++++ http/client.go | 14 ++++ http/handler_store.go | 7 +- tests/clients/cli/wrapper.go | 14 ++++ tests/clients/http/wrapper.go | 4 + tests/integration/schema/get_schema_test.go | 88 +++++++++++++++++++++ tests/integration/utils2.go | 2 + 12 files changed, 257 insertions(+), 2 deletions(-) diff --git a/cli/schema_describe.go b/cli/schema_describe.go index 51b4e8eba7..5fac85d268 100644 --- a/cli/schema_describe.go +++ b/cli/schema_describe.go @@ -57,7 +57,11 @@ Example: view schema by version id panic("todo") default: - panic("todo") + s, err := store.GetAllSchema(cmd.Context()) + if err != nil { + return err + } + schemas = s } if len(schemas) == 1 { diff --git a/client/db.go b/client/db.go index c7dc46f15f..18307383b2 100644 --- a/client/db.go +++ b/client/db.go @@ -167,6 +167,10 @@ type Store interface { // Will return an error if it is not found. GetSchemaByVersionID(context.Context, string) (SchemaDescription, error) + // GetAllSchema returns all schema versions that currently exist within + // this [Store]. + GetAllSchema(context.Context) ([]SchemaDescription, error) + // GetAllIndexes returns all the indexes that currently exist within this [Store]. GetAllIndexes(context.Context) (map[CollectionName][]IndexDescription, error) diff --git a/client/mocks/db.go b/client/mocks/db.go index c812cb2aa5..f01df33b30 100644 --- a/client/mocks/db.go +++ b/client/mocks/db.go @@ -438,6 +438,60 @@ func (_c *DB_GetAllIndexes_Call) RunAndReturn(run func(context.Context) (map[str return _c } +// GetAllSchema provides a mock function with given fields: _a0 +func (_m *DB) GetAllSchema(_a0 context.Context) ([]client.SchemaDescription, error) { + ret := _m.Called(_a0) + + var r0 []client.SchemaDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) ([]client.SchemaDescription, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) []client.SchemaDescription); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]client.SchemaDescription) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_GetAllSchema_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllSchema' +type DB_GetAllSchema_Call struct { + *mock.Call +} + +// GetAllSchema is a helper method to define mock.On call +// - _a0 context.Context +func (_e *DB_Expecter) GetAllSchema(_a0 interface{}) *DB_GetAllSchema_Call { + return &DB_GetAllSchema_Call{Call: _e.mock.On("GetAllSchema", _a0)} +} + +func (_c *DB_GetAllSchema_Call) Run(run func(_a0 context.Context)) *DB_GetAllSchema_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *DB_GetAllSchema_Call) Return(_a0 []client.SchemaDescription, _a1 error) *DB_GetAllSchema_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_GetAllSchema_Call) RunAndReturn(run func(context.Context) ([]client.SchemaDescription, error)) *DB_GetAllSchema_Call { + _c.Call.Return(run) + return _c +} + // GetCollectionByName provides a mock function with given fields: _a0, _a1 func (_m *DB) GetCollectionByName(_a0 context.Context, _a1 string) (client.Collection, error) { ret := _m.Called(_a0, _a1) diff --git a/db/description/schema.go b/db/description/schema.go index 832e614f32..5bc064bad7 100644 --- a/db/description/schema.go +++ b/db/description/schema.go @@ -161,6 +161,47 @@ func GetSchemas( return descriptions, nil } +// GetSchemas returns all schema versions in the system. +func GetAllSchemas( + ctx context.Context, + txn datastore.Txn, +) ([]client.SchemaDescription, error) { + prefix := core.NewSchemaVersionKey("") + q, err := txn.Systemstore().Query(ctx, query.Query{ + Prefix: prefix.ToString(), + }) + if err != nil { + return nil, NewErrFailedToCreateSchemaQuery(err) + } + + schema := make([]client.SchemaDescription, 0) + for res := range q.Next() { + if res.Error != nil { + if err := q.Close(); err != nil { + return nil, NewErrFailedToCloseSchemaQuery(err) + } + return nil, err + } + + var desc client.SchemaDescription + err = json.Unmarshal(res.Value, &desc) + if err != nil { + if err := q.Close(); err != nil { + return nil, NewErrFailedToCloseSchemaQuery(err) + } + return nil, err + } + + schema = append(schema, desc) + } + + if err := q.Close(); err != nil { + return nil, NewErrFailedToCloseSchemaQuery(err) + } + + return schema, nil +} + func GetSchemaVersionIDs( ctx context.Context, txn datastore.Txn, diff --git a/db/schema.go b/db/schema.go index a0b9d06038..e9878b3a53 100644 --- a/db/schema.go +++ b/db/schema.go @@ -297,6 +297,13 @@ func (db *db) getSchemaByVersionID( return description.GetSchemaVersion(ctx, txn, versionID) } +func (db *db) getAllSchema( + ctx context.Context, + txn datastore.Txn, +) ([]client.SchemaDescription, error) { + return description.GetAllSchemas(ctx, txn) +} + // getSubstituteFieldKind checks and attempts to get the underlying integer value for the given string // Field Kind value. It will return the value if one is found, else returns an [ErrFieldKindNotFound]. // diff --git a/db/txn_db.go b/db/txn_db.go index be4811bb70..5795569f4e 100644 --- a/db/txn_db.go +++ b/db/txn_db.go @@ -197,6 +197,24 @@ func (db *explicitTxnDB) GetSchemaByVersionID(ctx context.Context, versionID str return db.getSchemaByVersionID(ctx, db.txn, versionID) } +// GetAllSchema returns all schema versions that currently exist within +// this [Store]. +func (db *implicitTxnDB) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { + txn, err := db.NewTxn(ctx, true) + if err != nil { + return nil, err + } + defer txn.Discard(ctx) + + return db.getAllSchema(ctx, txn) +} + +// GetAllSchema returns all schema versions that currently exist within +// this [Store]. +func (db *explicitTxnDB) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { + return db.getAllSchema(ctx, db.txn) +} + // GetAllIndexes gets all the indexes in the database. func (db *implicitTxnDB) GetAllIndexes( ctx context.Context, diff --git a/http/client.go b/http/client.go index 5b5e09f6e4..7b09490001 100644 --- a/http/client.go +++ b/http/client.go @@ -257,6 +257,20 @@ func (c *Client) GetSchemaByVersionID(ctx context.Context, versionID string) (cl return schema, nil } +func (c *Client) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { + methodURL := c.http.baseURL.JoinPath("schema") + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, methodURL.String(), nil) + if err != nil { + return nil, err + } + var schema []client.SchemaDescription + if err := c.http.requestJson(req, &schema); err != nil { + return nil, err + } + return schema, nil +} + func (c *Client) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { methodURL := c.http.baseURL.JoinPath("indexes") diff --git a/http/handler_store.go b/http/handler_store.go index 9ecb449608..c774a0e70d 100644 --- a/http/handler_store.go +++ b/http/handler_store.go @@ -169,7 +169,12 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { } responseJSON(rw, http.StatusOK, schema) default: - panic("todo") + schema, err := store.GetAllSchema(req.Context()) + if err != nil { + responseJSON(rw, http.StatusBadRequest, errorResponse{err}) + return + } + responseJSON(rw, http.StatusOK, schema) } } diff --git a/tests/clients/cli/wrapper.go b/tests/clients/cli/wrapper.go index 59005b0dc6..76b8ea7277 100644 --- a/tests/clients/cli/wrapper.go +++ b/tests/clients/cli/wrapper.go @@ -296,6 +296,20 @@ func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (c return schema, err } +func (w *Wrapper) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { + args := []string{"client", "schema", "describe"} + + data, err := w.cmd.execute(ctx, args) + if err != nil { + return nil, err + } + var schema []client.SchemaDescription + if err := json.Unmarshal(data, &schema); err != nil { + return nil, err + } + return schema, err +} + func (w *Wrapper) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { args := []string{"client", "index", "list"} diff --git a/tests/clients/http/wrapper.go b/tests/clients/http/wrapper.go index a1ea89f02e..08f183c302 100644 --- a/tests/clients/http/wrapper.go +++ b/tests/clients/http/wrapper.go @@ -131,6 +131,10 @@ func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (c return w.client.GetSchemaByVersionID(ctx, versionID) } +func (w *Wrapper) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { + return w.client.GetAllSchema(ctx) +} + func (w *Wrapper) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { return w.client.GetAllIndexes(ctx) } diff --git a/tests/integration/schema/get_schema_test.go b/tests/integration/schema/get_schema_test.go index c5e2d90641..1bd50a6851 100644 --- a/tests/integration/schema/get_schema_test.go +++ b/tests/integration/schema/get_schema_test.go @@ -15,6 +15,7 @@ import ( "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/client" testUtils "github.com/sourcenetwork/defradb/tests/integration" ) @@ -30,3 +31,90 @@ func TestGetSchema_GivenNonExistantSchemaVersionID_Errors(t *testing.T) { testUtils.ExecuteTestCase(t, test) } + +func TestGetSchema_GivenNoSchemaReturnsEmptySet(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.GetSchema{ + ExpectedResults: []client.SchemaDescription{}, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} + +func TestGetSchema_ReturnsAllSchema(t *testing.T) { + usersSchemaVersion1ID := "bafkreickgf3nbjaairxkkqawmrv7fafaafyccl4qygqeveagisdn42eohu" + usersSchemaVersion2ID := "bafkreicseqwxooxo2wf2bgzdalwtm2rtsj7x4mgsir4rp4htmpnwnffwre" + booksSchemaVersion1ID := "bafkreigbfibfn7g6neen2gghc54dzocexefi7vshc3opgvy6j7jflar2nm" + + test := testUtils.TestCase{ + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Users {} + `, + }, + testUtils.SchemaUpdate{ + Schema: ` + type Books {} + `, + }, + testUtils.SchemaPatch{ + Patch: ` + [ + { "op": "add", "path": "/Users/Fields/-", "value": {"Name": "name", "Kind": "String"} } + ] + `, + SetAsDefaultVersion: immutable.Some(false), + }, + testUtils.GetSchema{ + ExpectedResults: []client.SchemaDescription{ + { + Name: "Users", + Root: usersSchemaVersion1ID, + VersionID: usersSchemaVersion1ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + }, + }, + }, + { + Name: "Users", + Root: usersSchemaVersion1ID, + VersionID: usersSchemaVersion2ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + Typ: client.LWW_REGISTER, + }, + { + Name: "name", + ID: 1, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + }, + }, + { + Name: "Books", + Root: booksSchemaVersion1ID, + VersionID: booksSchemaVersion1ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + }, + }, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/utils2.go b/tests/integration/utils2.go index c0af266065..59fb814807 100644 --- a/tests/integration/utils2.go +++ b/tests/integration/utils2.go @@ -964,6 +964,8 @@ func getSchema( result, e := node.GetSchemaByVersionID(s.ctx, action.VersionID.Value()) err = e results = []client.SchemaDescription{result} + default: + results, err = node.GetAllSchema(s.ctx) } expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) From 8246ee19ac78570444973f64c2b41dfffd3a26b2 Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Thu, 26 Oct 2023 14:57:51 -0400 Subject: [PATCH 3/7] Add GetSchemaByRoot --- cli/schema_describe.go | 6 +- client/db.go | 3 + client/mocks/db.go | 55 +++++++++++++++ db/description/schema.go | 21 ++++++ db/schema.go | 8 +++ db/txn_db.go | 16 +++++ http/client.go | 15 ++++ http/handler_store.go | 7 +- tests/clients/cli/wrapper.go | 15 ++++ tests/clients/http/wrapper.go | 4 ++ tests/integration/schema/get_schema_test.go | 77 +++++++++++++++++++++ tests/integration/test_case.go | 5 ++ tests/integration/utils2.go | 2 + 13 files changed, 232 insertions(+), 2 deletions(-) diff --git a/cli/schema_describe.go b/cli/schema_describe.go index 5fac85d268..3e2aaecba1 100644 --- a/cli/schema_describe.go +++ b/cli/schema_describe.go @@ -51,7 +51,11 @@ Example: view schema by version id schemas = []client.SchemaDescription{schema} case root != "": - panic("todo") + s, err := store.GetSchemaByRoot(cmd.Context(), root) + if err != nil { + return err + } + schemas = s case name != "": panic("todo") diff --git a/client/db.go b/client/db.go index 18307383b2..3c888c1b1e 100644 --- a/client/db.go +++ b/client/db.go @@ -167,6 +167,9 @@ type Store interface { // Will return an error if it is not found. GetSchemaByVersionID(context.Context, string) (SchemaDescription, error) + // GetSchemaByRoot returns the all schema versions for the given root. + GetSchemaByRoot(context.Context, string) ([]SchemaDescription, error) + // GetAllSchema returns all schema versions that currently exist within // this [Store]. GetAllSchema(context.Context) ([]SchemaDescription, error) diff --git a/client/mocks/db.go b/client/mocks/db.go index f01df33b30..562fa7b39f 100644 --- a/client/mocks/db.go +++ b/client/mocks/db.go @@ -657,6 +657,61 @@ func (_c *DB_GetCollectionsByVersionID_Call) RunAndReturn(run func(context.Conte return _c } +// GetSchemaByRoot provides a mock function with given fields: _a0, _a1 +func (_m *DB) GetSchemaByRoot(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { + ret := _m.Called(_a0, _a1) + + var r0 []client.SchemaDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) ([]client.SchemaDescription, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, string) []client.SchemaDescription); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]client.SchemaDescription) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_GetSchemaByRoot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemaByRoot' +type DB_GetSchemaByRoot_Call struct { + *mock.Call +} + +// GetSchemaByRoot is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +func (_e *DB_Expecter) GetSchemaByRoot(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByRoot_Call { + return &DB_GetSchemaByRoot_Call{Call: _e.mock.On("GetSchemaByRoot", _a0, _a1)} +} + +func (_c *DB_GetSchemaByRoot_Call) Run(run func(_a0 context.Context, _a1 string)) *DB_GetSchemaByRoot_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *DB_GetSchemaByRoot_Call) Return(_a0 []client.SchemaDescription, _a1 error) *DB_GetSchemaByRoot_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_GetSchemaByRoot_Call) RunAndReturn(run func(context.Context, string) ([]client.SchemaDescription, error)) *DB_GetSchemaByRoot_Call { + _c.Call.Return(run) + return _c +} + // GetSchemaByVersionID provides a mock function with given fields: _a0, _a1 func (_m *DB) GetSchemaByVersionID(_a0 context.Context, _a1 string) (client.SchemaDescription, error) { ret := _m.Called(_a0, _a1) diff --git a/db/description/schema.go b/db/description/schema.go index 5bc064bad7..77e5cde861 100644 --- a/db/description/schema.go +++ b/db/description/schema.go @@ -105,6 +105,27 @@ func GetSchemaVersion( return desc, nil } +// GetSchemaByRoot returns all the schema with the given root. +func GetSchemaByRoot( + ctx context.Context, + txn datastore.Txn, + root string, +) ([]client.SchemaDescription, error) { + allSchemas, err := GetAllSchemas(ctx, txn) + if err != nil { + return nil, err + } + + rootSchema := []client.SchemaDescription{} + for _, schema := range allSchemas { + if schema.Root == root { + rootSchema = append(rootSchema, schema) + } + } + + return rootSchema, nil +} + // GetSchemas returns the schema of all the default schema versions in the system. func GetSchemas( ctx context.Context, diff --git a/db/schema.go b/db/schema.go index e9878b3a53..370931b6e5 100644 --- a/db/schema.go +++ b/db/schema.go @@ -297,6 +297,14 @@ func (db *db) getSchemaByVersionID( return description.GetSchemaVersion(ctx, txn, versionID) } +func (db *db) getSchemaByRoot( + ctx context.Context, + txn datastore.Txn, + root string, +) ([]client.SchemaDescription, error) { + return description.GetSchemaByRoot(ctx, txn, root) +} + func (db *db) getAllSchema( ctx context.Context, txn datastore.Txn, diff --git a/db/txn_db.go b/db/txn_db.go index 5795569f4e..23158b54b6 100644 --- a/db/txn_db.go +++ b/db/txn_db.go @@ -197,6 +197,22 @@ func (db *explicitTxnDB) GetSchemaByVersionID(ctx context.Context, versionID str return db.getSchemaByVersionID(ctx, db.txn, versionID) } +// GetSchemaByRoot returns the all schema versions for the given root. +func (db *implicitTxnDB) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + txn, err := db.NewTxn(ctx, true) + if err != nil { + return nil, err + } + defer txn.Discard(ctx) + + return db.getSchemaByRoot(ctx, txn, root) +} + +// GetSchemaByRoot returns the all schema versions for the given root. +func (db *explicitTxnDB) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + return db.getSchemaByRoot(ctx, db.txn, root) +} + // GetAllSchema returns all schema versions that currently exist within // this [Store]. func (db *implicitTxnDB) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { diff --git a/http/client.go b/http/client.go index 7b09490001..bfc673daee 100644 --- a/http/client.go +++ b/http/client.go @@ -257,6 +257,21 @@ func (c *Client) GetSchemaByVersionID(ctx context.Context, versionID string) (cl return schema, nil } +func (c *Client) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + methodURL := c.http.baseURL.JoinPath("schema") + methodURL.RawQuery = url.Values{"root": []string{root}}.Encode() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, methodURL.String(), nil) + if err != nil { + return nil, err + } + var schema []client.SchemaDescription + if err := c.http.requestJson(req, &schema); err != nil { + return nil, err + } + return schema, nil +} + func (c *Client) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { methodURL := c.http.baseURL.JoinPath("schema") diff --git a/http/handler_store.go b/http/handler_store.go index c774a0e70d..db814b0e9c 100644 --- a/http/handler_store.go +++ b/http/handler_store.go @@ -160,7 +160,12 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { case req.URL.Query().Has("name"): panic("todo") case req.URL.Query().Has("root"): - panic("todo") + schema, err := store.GetSchemaByRoot(req.Context(), req.URL.Query().Get("root")) + if err != nil { + responseJSON(rw, http.StatusBadRequest, errorResponse{err}) + return + } + responseJSON(rw, http.StatusOK, schema) case req.URL.Query().Has("version_id"): schema, err := store.GetSchemaByVersionID(req.Context(), req.URL.Query().Get("version_id")) if err != nil { diff --git a/tests/clients/cli/wrapper.go b/tests/clients/cli/wrapper.go index 76b8ea7277..29e3bde502 100644 --- a/tests/clients/cli/wrapper.go +++ b/tests/clients/cli/wrapper.go @@ -296,6 +296,21 @@ func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (c return schema, err } +func (w *Wrapper) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + args := []string{"client", "schema", "describe"} + args = append(args, "--root", root) + + data, err := w.cmd.execute(ctx, args) + if err != nil { + return nil, err + } + var schema []client.SchemaDescription + if err := json.Unmarshal(data, &schema); err != nil { + return nil, err + } + return schema, err +} + func (w *Wrapper) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { args := []string{"client", "schema", "describe"} diff --git a/tests/clients/http/wrapper.go b/tests/clients/http/wrapper.go index 08f183c302..5ac0a5db69 100644 --- a/tests/clients/http/wrapper.go +++ b/tests/clients/http/wrapper.go @@ -131,6 +131,10 @@ func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (c return w.client.GetSchemaByVersionID(ctx, versionID) } +func (w *Wrapper) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + return w.client.GetSchemaByRoot(ctx, root) +} + func (w *Wrapper) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { return w.client.GetAllSchema(ctx) } diff --git a/tests/integration/schema/get_schema_test.go b/tests/integration/schema/get_schema_test.go index 1bd50a6851..0ae3662238 100644 --- a/tests/integration/schema/get_schema_test.go +++ b/tests/integration/schema/get_schema_test.go @@ -44,6 +44,19 @@ func TestGetSchema_GivenNoSchemaReturnsEmptySet(t *testing.T) { testUtils.ExecuteTestCase(t, test) } +func TestGetSchema_GivenNoSchemaGivenUnknownRoot(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.GetSchema{ + Root: immutable.Some("does not exist"), + ExpectedResults: []client.SchemaDescription{}, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} + func TestGetSchema_ReturnsAllSchema(t *testing.T) { usersSchemaVersion1ID := "bafkreickgf3nbjaairxkkqawmrv7fafaafyccl4qygqeveagisdn42eohu" usersSchemaVersion2ID := "bafkreicseqwxooxo2wf2bgzdalwtm2rtsj7x4mgsir4rp4htmpnwnffwre" @@ -118,3 +131,67 @@ func TestGetSchema_ReturnsAllSchema(t *testing.T) { testUtils.ExecuteTestCase(t, test) } + +func TestGetSchema_ReturnsSchemaForGivenRoot(t *testing.T) { + usersSchemaVersion1ID := "bafkreickgf3nbjaairxkkqawmrv7fafaafyccl4qygqeveagisdn42eohu" + usersSchemaVersion2ID := "bafkreicseqwxooxo2wf2bgzdalwtm2rtsj7x4mgsir4rp4htmpnwnffwre" + + test := testUtils.TestCase{ + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Users {} + `, + }, + testUtils.SchemaUpdate{ + Schema: ` + type Books {} + `, + }, + testUtils.SchemaPatch{ + Patch: ` + [ + { "op": "add", "path": "/Users/Fields/-", "value": {"Name": "name", "Kind": "String"} } + ] + `, + SetAsDefaultVersion: immutable.Some(false), + }, + testUtils.GetSchema{ + Root: immutable.Some(usersSchemaVersion1ID), + ExpectedResults: []client.SchemaDescription{ + { + Name: "Users", + Root: usersSchemaVersion1ID, + VersionID: usersSchemaVersion1ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + }, + }, + }, + { + Name: "Users", + Root: usersSchemaVersion1ID, + VersionID: usersSchemaVersion2ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + Typ: client.LWW_REGISTER, + }, + { + Name: "name", + ID: 1, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + }, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/test_case.go b/tests/integration/test_case.go index 21933a7292..57f37312a7 100644 --- a/tests/integration/test_case.go +++ b/tests/integration/test_case.go @@ -103,6 +103,11 @@ type GetSchema struct { // This option will be prioritized over all other options. VersionID immutable.Option[string] + // The Root of the schema versions to fetch. + // + // This option will be prioritized over Name. + Root immutable.Option[string] + ExpectedResults []client.SchemaDescription ExpectedError string diff --git a/tests/integration/utils2.go b/tests/integration/utils2.go index 59fb814807..8520fcdefd 100644 --- a/tests/integration/utils2.go +++ b/tests/integration/utils2.go @@ -964,6 +964,8 @@ func getSchema( result, e := node.GetSchemaByVersionID(s.ctx, action.VersionID.Value()) err = e results = []client.SchemaDescription{result} + case action.Root.HasValue(): + results, err = node.GetSchemaByRoot(s.ctx, action.Root.Value()) default: results, err = node.GetAllSchema(s.ctx) } From 208267e5c566f2558de89ab976a32c6fb491c95e Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Thu, 26 Oct 2023 15:21:00 -0400 Subject: [PATCH 4/7] Add GetSchemaByName --- cli/schema_describe.go | 6 +- client/db.go | 3 + client/mocks/db.go | 55 +++++++++++++++ db/description/schema.go | 21 ++++++ db/schema.go | 8 +++ db/txn_db.go | 16 +++++ http/client.go | 15 ++++ http/handler_store.go | 7 +- tests/clients/cli/wrapper.go | 15 ++++ tests/clients/http/wrapper.go | 4 ++ tests/integration/schema/get_schema_test.go | 77 +++++++++++++++++++++ tests/integration/test_case.go | 3 + tests/integration/utils2.go | 2 + 13 files changed, 230 insertions(+), 2 deletions(-) diff --git a/cli/schema_describe.go b/cli/schema_describe.go index 3e2aaecba1..690838b1b1 100644 --- a/cli/schema_describe.go +++ b/cli/schema_describe.go @@ -58,7 +58,11 @@ Example: view schema by version id schemas = s case name != "": - panic("todo") + s, err := store.GetSchemaByName(cmd.Context(), name) + if err != nil { + return err + } + schemas = s default: s, err := store.GetAllSchema(cmd.Context()) diff --git a/client/db.go b/client/db.go index 3c888c1b1e..6f9fb36398 100644 --- a/client/db.go +++ b/client/db.go @@ -161,6 +161,9 @@ type Store interface { // this [Store]. GetAllCollections(context.Context) ([]Collection, error) + // GetSchemaByName returns the all schema versions with the given name. + GetSchemaByName(context.Context, string) ([]SchemaDescription, error) + // GetSchemaByVersionID returns the schema description for the schema version of the // ID provided. // diff --git a/client/mocks/db.go b/client/mocks/db.go index 562fa7b39f..0d6b7c1360 100644 --- a/client/mocks/db.go +++ b/client/mocks/db.go @@ -657,6 +657,61 @@ func (_c *DB_GetCollectionsByVersionID_Call) RunAndReturn(run func(context.Conte return _c } +// GetSchemaByName provides a mock function with given fields: _a0, _a1 +func (_m *DB) GetSchemaByName(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { + ret := _m.Called(_a0, _a1) + + var r0 []client.SchemaDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) ([]client.SchemaDescription, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, string) []client.SchemaDescription); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]client.SchemaDescription) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_GetSchemaByName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemaByName' +type DB_GetSchemaByName_Call struct { + *mock.Call +} + +// GetSchemaByName is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +func (_e *DB_Expecter) GetSchemaByName(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByName_Call { + return &DB_GetSchemaByName_Call{Call: _e.mock.On("GetSchemaByName", _a0, _a1)} +} + +func (_c *DB_GetSchemaByName_Call) Run(run func(_a0 context.Context, _a1 string)) *DB_GetSchemaByName_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *DB_GetSchemaByName_Call) Return(_a0 []client.SchemaDescription, _a1 error) *DB_GetSchemaByName_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_GetSchemaByName_Call) RunAndReturn(run func(context.Context, string) ([]client.SchemaDescription, error)) *DB_GetSchemaByName_Call { + _c.Call.Return(run) + return _c +} + // GetSchemaByRoot provides a mock function with given fields: _a0, _a1 func (_m *DB) GetSchemaByRoot(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { ret := _m.Called(_a0, _a1) diff --git a/db/description/schema.go b/db/description/schema.go index 77e5cde861..42bb9e72c8 100644 --- a/db/description/schema.go +++ b/db/description/schema.go @@ -105,6 +105,27 @@ func GetSchemaVersion( return desc, nil } +// GetSchemaByName returns all the schema with the given name. +func GetSchemaByName( + ctx context.Context, + txn datastore.Txn, + name string, +) ([]client.SchemaDescription, error) { + allSchemas, err := GetAllSchemas(ctx, txn) + if err != nil { + return nil, err + } + + nameSchema := []client.SchemaDescription{} + for _, schema := range allSchemas { + if schema.Name == name { + nameSchema = append(nameSchema, schema) + } + } + + return nameSchema, nil +} + // GetSchemaByRoot returns all the schema with the given root. func GetSchemaByRoot( ctx context.Context, diff --git a/db/schema.go b/db/schema.go index 370931b6e5..ba1932e5aa 100644 --- a/db/schema.go +++ b/db/schema.go @@ -289,6 +289,14 @@ func substituteSchemaPatch( return patch, nil } +func (db *db) getSchemaByName( + ctx context.Context, + txn datastore.Txn, + name string, +) ([]client.SchemaDescription, error) { + return description.GetSchemaByName(ctx, txn, name) +} + func (db *db) getSchemaByVersionID( ctx context.Context, txn datastore.Txn, diff --git a/db/txn_db.go b/db/txn_db.go index 23158b54b6..c06ea72473 100644 --- a/db/txn_db.go +++ b/db/txn_db.go @@ -175,6 +175,22 @@ func (db *explicitTxnDB) GetAllCollections(ctx context.Context) ([]client.Collec return db.getAllCollections(ctx, db.txn) } +// GetSchemaByName returns the all schema versions with the given name. +func (db *implicitTxnDB) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + txn, err := db.NewTxn(ctx, true) + if err != nil { + return nil, err + } + defer txn.Discard(ctx) + + return db.getSchemaByName(ctx, txn, name) +} + +// GetSchemaByName returns the all schema versions with the given name. +func (db *explicitTxnDB) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + return db.getSchemaByName(ctx, db.txn, name) +} + // GetSchemaByVersionID returns the schema description for the schema version of the // ID provided. // diff --git a/http/client.go b/http/client.go index bfc673daee..85b7859e7c 100644 --- a/http/client.go +++ b/http/client.go @@ -242,6 +242,21 @@ func (c *Client) GetAllCollections(ctx context.Context) ([]client.Collection, er return collections, nil } +func (c *Client) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + methodURL := c.http.baseURL.JoinPath("schema") + methodURL.RawQuery = url.Values{"name": []string{name}}.Encode() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, methodURL.String(), nil) + if err != nil { + return nil, err + } + var schema []client.SchemaDescription + if err := c.http.requestJson(req, &schema); err != nil { + return nil, err + } + return schema, nil +} + func (c *Client) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { methodURL := c.http.baseURL.JoinPath("schema") methodURL.RawQuery = url.Values{"version_id": []string{versionID}}.Encode() diff --git a/http/handler_store.go b/http/handler_store.go index db814b0e9c..b9f9d3154b 100644 --- a/http/handler_store.go +++ b/http/handler_store.go @@ -158,7 +158,12 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { switch { case req.URL.Query().Has("name"): - panic("todo") + schema, err := store.GetSchemaByName(req.Context(), req.URL.Query().Get("name")) + if err != nil { + responseJSON(rw, http.StatusBadRequest, errorResponse{err}) + return + } + responseJSON(rw, http.StatusOK, schema) case req.URL.Query().Has("root"): schema, err := store.GetSchemaByRoot(req.Context(), req.URL.Query().Get("root")) if err != nil { diff --git a/tests/clients/cli/wrapper.go b/tests/clients/cli/wrapper.go index 29e3bde502..08ebd0a0fc 100644 --- a/tests/clients/cli/wrapper.go +++ b/tests/clients/cli/wrapper.go @@ -281,6 +281,21 @@ func (w *Wrapper) GetAllCollections(ctx context.Context) ([]client.Collection, e return cols, err } +func (w *Wrapper) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + args := []string{"client", "schema", "describe"} + args = append(args, "--name", name) + + data, err := w.cmd.execute(ctx, args) + if err != nil { + return nil, err + } + var schema []client.SchemaDescription + if err := json.Unmarshal(data, &schema); err != nil { + return nil, err + } + return schema, err +} + func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { args := []string{"client", "schema", "describe"} args = append(args, "--version", versionID) diff --git a/tests/clients/http/wrapper.go b/tests/clients/http/wrapper.go index 5ac0a5db69..fae3542fc8 100644 --- a/tests/clients/http/wrapper.go +++ b/tests/clients/http/wrapper.go @@ -127,6 +127,10 @@ func (w *Wrapper) GetAllCollections(ctx context.Context) ([]client.Collection, e return w.client.GetAllCollections(ctx) } +func (w *Wrapper) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + return w.client.GetSchemaByName(ctx, name) +} + func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { return w.client.GetSchemaByVersionID(ctx, versionID) } diff --git a/tests/integration/schema/get_schema_test.go b/tests/integration/schema/get_schema_test.go index 0ae3662238..e6d5f166ac 100644 --- a/tests/integration/schema/get_schema_test.go +++ b/tests/integration/schema/get_schema_test.go @@ -57,6 +57,19 @@ func TestGetSchema_GivenNoSchemaGivenUnknownRoot(t *testing.T) { testUtils.ExecuteTestCase(t, test) } +func TestGetSchema_GivenNoSchemaGivenUnknownName(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.GetSchema{ + Name: immutable.Some("does not exist"), + ExpectedResults: []client.SchemaDescription{}, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} + func TestGetSchema_ReturnsAllSchema(t *testing.T) { usersSchemaVersion1ID := "bafkreickgf3nbjaairxkkqawmrv7fafaafyccl4qygqeveagisdn42eohu" usersSchemaVersion2ID := "bafkreicseqwxooxo2wf2bgzdalwtm2rtsj7x4mgsir4rp4htmpnwnffwre" @@ -195,3 +208,67 @@ func TestGetSchema_ReturnsSchemaForGivenRoot(t *testing.T) { testUtils.ExecuteTestCase(t, test) } + +func TestGetSchema_ReturnsSchemaForGivenName(t *testing.T) { + usersSchemaVersion1ID := "bafkreickgf3nbjaairxkkqawmrv7fafaafyccl4qygqeveagisdn42eohu" + usersSchemaVersion2ID := "bafkreicseqwxooxo2wf2bgzdalwtm2rtsj7x4mgsir4rp4htmpnwnffwre" + + test := testUtils.TestCase{ + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Users {} + `, + }, + testUtils.SchemaUpdate{ + Schema: ` + type Books {} + `, + }, + testUtils.SchemaPatch{ + Patch: ` + [ + { "op": "add", "path": "/Users/Fields/-", "value": {"Name": "name", "Kind": "String"} } + ] + `, + SetAsDefaultVersion: immutable.Some(false), + }, + testUtils.GetSchema{ + Name: immutable.Some("Users"), + ExpectedResults: []client.SchemaDescription{ + { + Name: "Users", + Root: usersSchemaVersion1ID, + VersionID: usersSchemaVersion1ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + }, + }, + }, + { + Name: "Users", + Root: usersSchemaVersion1ID, + VersionID: usersSchemaVersion2ID, + Fields: []client.FieldDescription{ + { + Name: "_key", + Kind: client.FieldKind_DocKey, + Typ: client.LWW_REGISTER, + }, + { + Name: "name", + ID: 1, + Kind: client.FieldKind_STRING, + Typ: client.LWW_REGISTER, + }, + }, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/test_case.go b/tests/integration/test_case.go index 57f37312a7..112a497dc8 100644 --- a/tests/integration/test_case.go +++ b/tests/integration/test_case.go @@ -108,6 +108,9 @@ type GetSchema struct { // This option will be prioritized over Name. Root immutable.Option[string] + // The Name of the schema versions to fetch. + Name immutable.Option[string] + ExpectedResults []client.SchemaDescription ExpectedError string diff --git a/tests/integration/utils2.go b/tests/integration/utils2.go index 8520fcdefd..13a9f15c5d 100644 --- a/tests/integration/utils2.go +++ b/tests/integration/utils2.go @@ -966,6 +966,8 @@ func getSchema( results = []client.SchemaDescription{result} case action.Root.HasValue(): results, err = node.GetSchemaByRoot(s.ctx, action.Root.Value()) + case action.Name.HasValue(): + results, err = node.GetSchemaByName(s.ctx, action.Name.Value()) default: results, err = node.GetAllSchema(s.ctx) } From d9dffa20812969034ad239646bc33dd5a2007606 Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Fri, 27 Oct 2023 13:25:12 -0400 Subject: [PATCH 5/7] PR FIXUP - Rework cli array stuff --- cli/schema_describe.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cli/schema_describe.go b/cli/schema_describe.go index 690838b1b1..a544fb9904 100644 --- a/cli/schema_describe.go +++ b/cli/schema_describe.go @@ -48,7 +48,7 @@ Example: view schema by version id if err != nil { return err } - schemas = []client.SchemaDescription{schema} + return writeJSON(cmd, schema) case root != "": s, err := store.GetSchemaByRoot(cmd.Context(), root) @@ -72,10 +72,6 @@ Example: view schema by version id schemas = s } - if len(schemas) == 1 { - return writeJSON(cmd, schemas[0]) - } - return writeJSON(cmd, schemas) }, } From 28ad92d96a5367a17baa64c9c88bf15069ab011e Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Fri, 27 Oct 2023 13:31:56 -0400 Subject: [PATCH 6/7] PR FIXUP - Pluralize schema(s) --- cli/schema_describe.go | 16 ++++++++-------- client/db.go | 12 ++++++------ client/mocks/db.go | 36 +++++++++++++++++------------------ db/description/schema.go | 26 ++++++++++++------------- db/schema.go | 10 +++++----- db/txn_db.go | 36 +++++++++++++++++------------------ http/client.go | 6 +++--- http/handler_store.go | 6 +++--- tests/clients/cli/wrapper.go | 6 +++--- tests/clients/http/wrapper.go | 12 ++++++------ tests/integration/utils2.go | 6 +++--- 11 files changed, 86 insertions(+), 86 deletions(-) diff --git a/cli/schema_describe.go b/cli/schema_describe.go index a544fb9904..72d8eda474 100644 --- a/cli/schema_describe.go +++ b/cli/schema_describe.go @@ -23,19 +23,19 @@ func MakeSchemaDescribeCommand() *cobra.Command { var cmd = &cobra.Command{ Use: "describe", - Short: "View schema description.", + Short: "View schema descriptions.", Long: `Introspect schema types. -Example: view all schema +Example: view all schemas defradb client schema describe -Example: view schema by name +Example: view schemas by name defradb client schema describe --name User -Example: view schema by root +Example: view schemas by root defradb client schema describe --root bae123 -Example: view schema by version id +Example: view a single schema by version id defradb client schema describe --version bae123 `, RunE: func(cmd *cobra.Command, args []string) error { @@ -51,21 +51,21 @@ Example: view schema by version id return writeJSON(cmd, schema) case root != "": - s, err := store.GetSchemaByRoot(cmd.Context(), root) + s, err := store.GetSchemasByRoot(cmd.Context(), root) if err != nil { return err } schemas = s case name != "": - s, err := store.GetSchemaByName(cmd.Context(), name) + s, err := store.GetSchemasByName(cmd.Context(), name) if err != nil { return err } schemas = s default: - s, err := store.GetAllSchema(cmd.Context()) + s, err := store.GetAllSchemas(cmd.Context()) if err != nil { return err } diff --git a/client/db.go b/client/db.go index 6f9fb36398..b1b63f29d6 100644 --- a/client/db.go +++ b/client/db.go @@ -161,8 +161,8 @@ type Store interface { // this [Store]. GetAllCollections(context.Context) ([]Collection, error) - // GetSchemaByName returns the all schema versions with the given name. - GetSchemaByName(context.Context, string) ([]SchemaDescription, error) + // GetSchemasByName returns the all schema versions with the given name. + GetSchemasByName(context.Context, string) ([]SchemaDescription, error) // GetSchemaByVersionID returns the schema description for the schema version of the // ID provided. @@ -170,12 +170,12 @@ type Store interface { // Will return an error if it is not found. GetSchemaByVersionID(context.Context, string) (SchemaDescription, error) - // GetSchemaByRoot returns the all schema versions for the given root. - GetSchemaByRoot(context.Context, string) ([]SchemaDescription, error) + // GetSchemasByRoot returns the all schema versions for the given root. + GetSchemasByRoot(context.Context, string) ([]SchemaDescription, error) - // GetAllSchema returns all schema versions that currently exist within + // GetAllSchemas returns all schema versions that currently exist within // this [Store]. - GetAllSchema(context.Context) ([]SchemaDescription, error) + GetAllSchemas(context.Context) ([]SchemaDescription, error) // GetAllIndexes returns all the indexes that currently exist within this [Store]. GetAllIndexes(context.Context) (map[CollectionName][]IndexDescription, error) diff --git a/client/mocks/db.go b/client/mocks/db.go index 0d6b7c1360..df7b53fb5a 100644 --- a/client/mocks/db.go +++ b/client/mocks/db.go @@ -438,8 +438,8 @@ func (_c *DB_GetAllIndexes_Call) RunAndReturn(run func(context.Context) (map[str return _c } -// GetAllSchema provides a mock function with given fields: _a0 -func (_m *DB) GetAllSchema(_a0 context.Context) ([]client.SchemaDescription, error) { +// GetAllSchemas provides a mock function with given fields: _a0 +func (_m *DB) GetAllSchemas(_a0 context.Context) ([]client.SchemaDescription, error) { ret := _m.Called(_a0) var r0 []client.SchemaDescription @@ -464,15 +464,15 @@ func (_m *DB) GetAllSchema(_a0 context.Context) ([]client.SchemaDescription, err return r0, r1 } -// DB_GetAllSchema_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllSchema' +// DB_GetAllSchema_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllSchemas' type DB_GetAllSchema_Call struct { *mock.Call } -// GetAllSchema is a helper method to define mock.On call +// GetAllSchemas is a helper method to define mock.On call // - _a0 context.Context -func (_e *DB_Expecter) GetAllSchema(_a0 interface{}) *DB_GetAllSchema_Call { - return &DB_GetAllSchema_Call{Call: _e.mock.On("GetAllSchema", _a0)} +func (_e *DB_Expecter) GetAllSchemas(_a0 interface{}) *DB_GetAllSchema_Call { + return &DB_GetAllSchema_Call{Call: _e.mock.On("GetAllSchemas", _a0)} } func (_c *DB_GetAllSchema_Call) Run(run func(_a0 context.Context)) *DB_GetAllSchema_Call { @@ -657,8 +657,8 @@ func (_c *DB_GetCollectionsByVersionID_Call) RunAndReturn(run func(context.Conte return _c } -// GetSchemaByName provides a mock function with given fields: _a0, _a1 -func (_m *DB) GetSchemaByName(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { +// GetSchemasByName provides a mock function with given fields: _a0, _a1 +func (_m *DB) GetSchemasByName(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { ret := _m.Called(_a0, _a1) var r0 []client.SchemaDescription @@ -683,16 +683,16 @@ func (_m *DB) GetSchemaByName(_a0 context.Context, _a1 string) ([]client.SchemaD return r0, r1 } -// DB_GetSchemaByName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemaByName' +// DB_GetSchemaByName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemasByName' type DB_GetSchemaByName_Call struct { *mock.Call } -// GetSchemaByName is a helper method to define mock.On call +// GetSchemasByName is a helper method to define mock.On call // - _a0 context.Context // - _a1 string -func (_e *DB_Expecter) GetSchemaByName(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByName_Call { - return &DB_GetSchemaByName_Call{Call: _e.mock.On("GetSchemaByName", _a0, _a1)} +func (_e *DB_Expecter) GetSchemasByName(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByName_Call { + return &DB_GetSchemaByName_Call{Call: _e.mock.On("GetSchemasByName", _a0, _a1)} } func (_c *DB_GetSchemaByName_Call) Run(run func(_a0 context.Context, _a1 string)) *DB_GetSchemaByName_Call { @@ -712,8 +712,8 @@ func (_c *DB_GetSchemaByName_Call) RunAndReturn(run func(context.Context, string return _c } -// GetSchemaByRoot provides a mock function with given fields: _a0, _a1 -func (_m *DB) GetSchemaByRoot(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { +// GetSchemasByRoot provides a mock function with given fields: _a0, _a1 +func (_m *DB) GetSchemasByRoot(_a0 context.Context, _a1 string) ([]client.SchemaDescription, error) { ret := _m.Called(_a0, _a1) var r0 []client.SchemaDescription @@ -738,16 +738,16 @@ func (_m *DB) GetSchemaByRoot(_a0 context.Context, _a1 string) ([]client.SchemaD return r0, r1 } -// DB_GetSchemaByRoot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemaByRoot' +// DB_GetSchemaByRoot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSchemasByRoot' type DB_GetSchemaByRoot_Call struct { *mock.Call } -// GetSchemaByRoot is a helper method to define mock.On call +// GetSchemasByRoot is a helper method to define mock.On call // - _a0 context.Context // - _a1 string -func (_e *DB_Expecter) GetSchemaByRoot(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByRoot_Call { - return &DB_GetSchemaByRoot_Call{Call: _e.mock.On("GetSchemaByRoot", _a0, _a1)} +func (_e *DB_Expecter) GetSchemasByRoot(_a0 interface{}, _a1 interface{}) *DB_GetSchemaByRoot_Call { + return &DB_GetSchemaByRoot_Call{Call: _e.mock.On("GetSchemasByRoot", _a0, _a1)} } func (_c *DB_GetSchemaByRoot_Call) Run(run func(_a0 context.Context, _a1 string)) *DB_GetSchemaByRoot_Call { diff --git a/db/description/schema.go b/db/description/schema.go index 42bb9e72c8..06b129f3df 100644 --- a/db/description/schema.go +++ b/db/description/schema.go @@ -105,8 +105,8 @@ func GetSchemaVersion( return desc, nil } -// GetSchemaByName returns all the schema with the given name. -func GetSchemaByName( +// GetSchemasByName returns all the schema with the given name. +func GetSchemasByName( ctx context.Context, txn datastore.Txn, name string, @@ -116,18 +116,18 @@ func GetSchemaByName( return nil, err } - nameSchema := []client.SchemaDescription{} + nameSchemas := []client.SchemaDescription{} for _, schema := range allSchemas { if schema.Name == name { - nameSchema = append(nameSchema, schema) + nameSchemas = append(nameSchemas, schema) } } - return nameSchema, nil + return nameSchemas, nil } -// GetSchemaByRoot returns all the schema with the given root. -func GetSchemaByRoot( +// GetSchemasByRoot returns all the schema with the given root. +func GetSchemasByRoot( ctx context.Context, txn datastore.Txn, root string, @@ -137,14 +137,14 @@ func GetSchemaByRoot( return nil, err } - rootSchema := []client.SchemaDescription{} + rootSchemas := []client.SchemaDescription{} for _, schema := range allSchemas { if schema.Root == root { - rootSchema = append(rootSchema, schema) + rootSchemas = append(rootSchemas, schema) } } - return rootSchema, nil + return rootSchemas, nil } // GetSchemas returns the schema of all the default schema versions in the system. @@ -216,7 +216,7 @@ func GetAllSchemas( return nil, NewErrFailedToCreateSchemaQuery(err) } - schema := make([]client.SchemaDescription, 0) + schemas := make([]client.SchemaDescription, 0) for res := range q.Next() { if res.Error != nil { if err := q.Close(); err != nil { @@ -234,14 +234,14 @@ func GetAllSchemas( return nil, err } - schema = append(schema, desc) + schemas = append(schemas, desc) } if err := q.Close(); err != nil { return nil, NewErrFailedToCloseSchemaQuery(err) } - return schema, nil + return schemas, nil } func GetSchemaVersionIDs( diff --git a/db/schema.go b/db/schema.go index ba1932e5aa..df95df60e2 100644 --- a/db/schema.go +++ b/db/schema.go @@ -289,12 +289,12 @@ func substituteSchemaPatch( return patch, nil } -func (db *db) getSchemaByName( +func (db *db) getSchemasByName( ctx context.Context, txn datastore.Txn, name string, ) ([]client.SchemaDescription, error) { - return description.GetSchemaByName(ctx, txn, name) + return description.GetSchemasByName(ctx, txn, name) } func (db *db) getSchemaByVersionID( @@ -305,15 +305,15 @@ func (db *db) getSchemaByVersionID( return description.GetSchemaVersion(ctx, txn, versionID) } -func (db *db) getSchemaByRoot( +func (db *db) getSchemasByRoot( ctx context.Context, txn datastore.Txn, root string, ) ([]client.SchemaDescription, error) { - return description.GetSchemaByRoot(ctx, txn, root) + return description.GetSchemasByRoot(ctx, txn, root) } -func (db *db) getAllSchema( +func (db *db) getAllSchemas( ctx context.Context, txn datastore.Txn, ) ([]client.SchemaDescription, error) { diff --git a/db/txn_db.go b/db/txn_db.go index c06ea72473..380cfeed34 100644 --- a/db/txn_db.go +++ b/db/txn_db.go @@ -175,20 +175,20 @@ func (db *explicitTxnDB) GetAllCollections(ctx context.Context) ([]client.Collec return db.getAllCollections(ctx, db.txn) } -// GetSchemaByName returns the all schema versions with the given name. -func (db *implicitTxnDB) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { +// GetSchemasByName returns the all schema versions with the given name. +func (db *implicitTxnDB) GetSchemasByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { txn, err := db.NewTxn(ctx, true) if err != nil { return nil, err } defer txn.Discard(ctx) - return db.getSchemaByName(ctx, txn, name) + return db.getSchemasByName(ctx, txn, name) } -// GetSchemaByName returns the all schema versions with the given name. -func (db *explicitTxnDB) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { - return db.getSchemaByName(ctx, db.txn, name) +// GetSchemasByName returns the all schema versions with the given name. +func (db *explicitTxnDB) GetSchemasByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + return db.getSchemasByName(ctx, db.txn, name) } // GetSchemaByVersionID returns the schema description for the schema version of the @@ -213,38 +213,38 @@ func (db *explicitTxnDB) GetSchemaByVersionID(ctx context.Context, versionID str return db.getSchemaByVersionID(ctx, db.txn, versionID) } -// GetSchemaByRoot returns the all schema versions for the given root. -func (db *implicitTxnDB) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { +// GetSchemasByRoot returns the all schema versions for the given root. +func (db *implicitTxnDB) GetSchemasByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { txn, err := db.NewTxn(ctx, true) if err != nil { return nil, err } defer txn.Discard(ctx) - return db.getSchemaByRoot(ctx, txn, root) + return db.getSchemasByRoot(ctx, txn, root) } -// GetSchemaByRoot returns the all schema versions for the given root. -func (db *explicitTxnDB) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { - return db.getSchemaByRoot(ctx, db.txn, root) +// GetSchemasByRoot returns the all schema versions for the given root. +func (db *explicitTxnDB) GetSchemasByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + return db.getSchemasByRoot(ctx, db.txn, root) } -// GetAllSchema returns all schema versions that currently exist within +// GetAllSchemas returns all schema versions that currently exist within // this [Store]. -func (db *implicitTxnDB) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { +func (db *implicitTxnDB) GetAllSchemas(ctx context.Context) ([]client.SchemaDescription, error) { txn, err := db.NewTxn(ctx, true) if err != nil { return nil, err } defer txn.Discard(ctx) - return db.getAllSchema(ctx, txn) + return db.getAllSchemas(ctx, txn) } -// GetAllSchema returns all schema versions that currently exist within +// GetAllSchemas returns all schema versions that currently exist within // this [Store]. -func (db *explicitTxnDB) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { - return db.getAllSchema(ctx, db.txn) +func (db *explicitTxnDB) GetAllSchemas(ctx context.Context) ([]client.SchemaDescription, error) { + return db.getAllSchemas(ctx, db.txn) } // GetAllIndexes gets all the indexes in the database. diff --git a/http/client.go b/http/client.go index 85b7859e7c..148715e877 100644 --- a/http/client.go +++ b/http/client.go @@ -242,7 +242,7 @@ func (c *Client) GetAllCollections(ctx context.Context) ([]client.Collection, er return collections, nil } -func (c *Client) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { +func (c *Client) GetSchemasByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { methodURL := c.http.baseURL.JoinPath("schema") methodURL.RawQuery = url.Values{"name": []string{name}}.Encode() @@ -272,7 +272,7 @@ func (c *Client) GetSchemaByVersionID(ctx context.Context, versionID string) (cl return schema, nil } -func (c *Client) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { +func (c *Client) GetSchemasByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { methodURL := c.http.baseURL.JoinPath("schema") methodURL.RawQuery = url.Values{"root": []string{root}}.Encode() @@ -287,7 +287,7 @@ func (c *Client) GetSchemaByRoot(ctx context.Context, root string) ([]client.Sch return schema, nil } -func (c *Client) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { +func (c *Client) GetAllSchemas(ctx context.Context) ([]client.SchemaDescription, error) { methodURL := c.http.baseURL.JoinPath("schema") req, err := http.NewRequestWithContext(ctx, http.MethodGet, methodURL.String(), nil) diff --git a/http/handler_store.go b/http/handler_store.go index b9f9d3154b..9993b4027a 100644 --- a/http/handler_store.go +++ b/http/handler_store.go @@ -158,14 +158,14 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { switch { case req.URL.Query().Has("name"): - schema, err := store.GetSchemaByName(req.Context(), req.URL.Query().Get("name")) + schema, err := store.GetSchemasByName(req.Context(), req.URL.Query().Get("name")) if err != nil { responseJSON(rw, http.StatusBadRequest, errorResponse{err}) return } responseJSON(rw, http.StatusOK, schema) case req.URL.Query().Has("root"): - schema, err := store.GetSchemaByRoot(req.Context(), req.URL.Query().Get("root")) + schema, err := store.GetSchemasByRoot(req.Context(), req.URL.Query().Get("root")) if err != nil { responseJSON(rw, http.StatusBadRequest, errorResponse{err}) return @@ -179,7 +179,7 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { } responseJSON(rw, http.StatusOK, schema) default: - schema, err := store.GetAllSchema(req.Context()) + schema, err := store.GetAllSchemas(req.Context()) if err != nil { responseJSON(rw, http.StatusBadRequest, errorResponse{err}) return diff --git a/tests/clients/cli/wrapper.go b/tests/clients/cli/wrapper.go index 08ebd0a0fc..43c0aba820 100644 --- a/tests/clients/cli/wrapper.go +++ b/tests/clients/cli/wrapper.go @@ -281,7 +281,7 @@ func (w *Wrapper) GetAllCollections(ctx context.Context) ([]client.Collection, e return cols, err } -func (w *Wrapper) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { +func (w *Wrapper) GetSchemasByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { args := []string{"client", "schema", "describe"} args = append(args, "--name", name) @@ -311,7 +311,7 @@ func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (c return schema, err } -func (w *Wrapper) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { +func (w *Wrapper) GetSchemasByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { args := []string{"client", "schema", "describe"} args = append(args, "--root", root) @@ -326,7 +326,7 @@ func (w *Wrapper) GetSchemaByRoot(ctx context.Context, root string) ([]client.Sc return schema, err } -func (w *Wrapper) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { +func (w *Wrapper) GetAllSchemas(ctx context.Context) ([]client.SchemaDescription, error) { args := []string{"client", "schema", "describe"} data, err := w.cmd.execute(ctx, args) diff --git a/tests/clients/http/wrapper.go b/tests/clients/http/wrapper.go index fae3542fc8..ab7975a525 100644 --- a/tests/clients/http/wrapper.go +++ b/tests/clients/http/wrapper.go @@ -127,20 +127,20 @@ func (w *Wrapper) GetAllCollections(ctx context.Context) ([]client.Collection, e return w.client.GetAllCollections(ctx) } -func (w *Wrapper) GetSchemaByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { - return w.client.GetSchemaByName(ctx, name) +func (w *Wrapper) GetSchemasByName(ctx context.Context, name string) ([]client.SchemaDescription, error) { + return w.client.GetSchemasByName(ctx, name) } func (w *Wrapper) GetSchemaByVersionID(ctx context.Context, versionID string) (client.SchemaDescription, error) { return w.client.GetSchemaByVersionID(ctx, versionID) } -func (w *Wrapper) GetSchemaByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { - return w.client.GetSchemaByRoot(ctx, root) +func (w *Wrapper) GetSchemasByRoot(ctx context.Context, root string) ([]client.SchemaDescription, error) { + return w.client.GetSchemasByRoot(ctx, root) } -func (w *Wrapper) GetAllSchema(ctx context.Context) ([]client.SchemaDescription, error) { - return w.client.GetAllSchema(ctx) +func (w *Wrapper) GetAllSchemas(ctx context.Context) ([]client.SchemaDescription, error) { + return w.client.GetAllSchemas(ctx) } func (w *Wrapper) GetAllIndexes(ctx context.Context) (map[client.CollectionName][]client.IndexDescription, error) { diff --git a/tests/integration/utils2.go b/tests/integration/utils2.go index 13a9f15c5d..a9480c15ec 100644 --- a/tests/integration/utils2.go +++ b/tests/integration/utils2.go @@ -965,11 +965,11 @@ func getSchema( err = e results = []client.SchemaDescription{result} case action.Root.HasValue(): - results, err = node.GetSchemaByRoot(s.ctx, action.Root.Value()) + results, err = node.GetSchemasByRoot(s.ctx, action.Root.Value()) case action.Name.HasValue(): - results, err = node.GetSchemaByName(s.ctx, action.Name.Value()) + results, err = node.GetSchemasByName(s.ctx, action.Name.Value()) default: - results, err = node.GetAllSchema(s.ctx) + results, err = node.GetAllSchemas(s.ctx) } expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) From efdf13bb456b17d0f95a4006fc386b5793d3c240 Mon Sep 17 00:00:00 2001 From: Andrew Sisley Date: Fri, 27 Oct 2023 13:55:01 -0400 Subject: [PATCH 7/7] PR FIXUP - Reorder switch statement Is now consistent with the CLI --- http/handler_store.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/http/handler_store.go b/http/handler_store.go index 9993b4027a..aadbb37731 100644 --- a/http/handler_store.go +++ b/http/handler_store.go @@ -157,8 +157,8 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { store := req.Context().Value(storeContextKey).(client.Store) switch { - case req.URL.Query().Has("name"): - schema, err := store.GetSchemasByName(req.Context(), req.URL.Query().Get("name")) + case req.URL.Query().Has("version_id"): + schema, err := store.GetSchemaByVersionID(req.Context(), req.URL.Query().Get("version_id")) if err != nil { responseJSON(rw, http.StatusBadRequest, errorResponse{err}) return @@ -171,8 +171,8 @@ func (s *storeHandler) GetSchema(rw http.ResponseWriter, req *http.Request) { return } responseJSON(rw, http.StatusOK, schema) - case req.URL.Query().Has("version_id"): - schema, err := store.GetSchemaByVersionID(req.Context(), req.URL.Query().Get("version_id")) + case req.URL.Query().Has("name"): + schema, err := store.GetSchemasByName(req.Context(), req.URL.Query().Get("name")) if err != nil { responseJSON(rw, http.StatusBadRequest, errorResponse{err}) return